\n"); + } else { + cr(html); + cmark_strbuf_puts(html, "\n"); + } + break; + + case CMARK_NODE_LIST: { + cmark_list_type list_type = node->as.list.list_type; + int start = node->as.list.start; + + if (entering) { + cr(html); + if (list_type == CMARK_BULLET_LIST) { + cmark_strbuf_puts(html, "
");
+ } else {
+ bufsize_t first_tag = 0;
+ while (first_tag < node->as.code.info.len &&
+ !cmark_isspace(node->as.code.info.data[first_tag])) {
+ first_tag += 1;
+ }
+
+ cmark_strbuf_puts(html, "as.code.info.data, first_tag);
+ cmark_strbuf_puts(html, "\">");
+ }
+
+ escape_html(html, node->as.code.literal.data, node->as.code.literal.len);
+ cmark_strbuf_puts(html, "
\n");
+ break;
+
+ case CMARK_NODE_HTML_BLOCK:
+ cr(html);
+ if (options & CMARK_OPT_SAFE) {
+ cmark_strbuf_puts(html, "");
+ } else {
+ cmark_strbuf_put(html, node->as.literal.data, node->as.literal.len);
+ }
+ cr(html);
+ break;
+
+ case CMARK_NODE_CUSTOM_BLOCK:
+ cr(html);
+ if (entering) {
+ cmark_strbuf_put(html, node->as.custom.on_enter.data,
+ node->as.custom.on_enter.len);
+ } else {
+ cmark_strbuf_put(html, node->as.custom.on_exit.data,
+ node->as.custom.on_exit.len);
+ }
+ cr(html);
+ break;
+
+ case CMARK_NODE_THEMATIC_BREAK:
+ cr(html);
+ cmark_strbuf_puts(html, "
\n");
+ break;
+
+ case CMARK_NODE_PARAGRAPH:
+ parent = cmark_node_parent(node);
+ grandparent = cmark_node_parent(parent);
+ if (grandparent != NULL && grandparent->type == CMARK_NODE_LIST) {
+ tight = grandparent->as.list.tight;
+ } else {
+ tight = false;
+ }
+ if (!tight) {
+ if (entering) {
+ cr(html);
+ cmark_strbuf_puts(html, "');
+ } else {
+ cmark_strbuf_puts(html, "
\n");
+ }
+ }
+ break;
+
+ case CMARK_NODE_TEXT:
+ escape_html(html, node->as.literal.data, node->as.literal.len);
+ break;
+
+ case CMARK_NODE_LINEBREAK:
+ cmark_strbuf_puts(html, "
\n");
+ break;
+
+ case CMARK_NODE_SOFTBREAK:
+ if (options & CMARK_OPT_HARDBREAKS) {
+ cmark_strbuf_puts(html, "
\n");
+ } else if (options & CMARK_OPT_NOBREAKS) {
+ cmark_strbuf_putc(html, ' ');
+ } else {
+ cmark_strbuf_putc(html, '\n');
+ }
+ break;
+
+ case CMARK_NODE_CODE:
+ cmark_strbuf_puts(html, "");
+ escape_html(html, node->as.literal.data, node->as.literal.len);
+ cmark_strbuf_puts(html, "
");
+ break;
+
+ case CMARK_NODE_HTML_INLINE:
+ if (options & CMARK_OPT_SAFE) {
+ cmark_strbuf_puts(html, "");
+ } else {
+ cmark_strbuf_put(html, node->as.literal.data, node->as.literal.len);
+ }
+ break;
+
+ case CMARK_NODE_CUSTOM_INLINE:
+ if (entering) {
+ cmark_strbuf_put(html, node->as.custom.on_enter.data,
+ node->as.custom.on_enter.len);
+ } else {
+ cmark_strbuf_put(html, node->as.custom.on_exit.data,
+ node->as.custom.on_exit.len);
+ }
+ break;
+
+ case CMARK_NODE_STRONG:
+ if (entering) {
+ cmark_strbuf_puts(html, "");
+ } else {
+ cmark_strbuf_puts(html, "");
+ }
+ break;
+
+ case CMARK_NODE_EMPH:
+ if (entering) {
+ cmark_strbuf_puts(html, "");
+ } else {
+ cmark_strbuf_puts(html, "");
+ }
+ break;
+
+ case CMARK_NODE_LINK:
+ if (entering) {
+ cmark_strbuf_puts(html, "as.link.url, 0))) {
+ houdini_escape_href(html, node->as.link.url.data,
+ node->as.link.url.len);
+ }
+ if (node->as.link.title.len) {
+ cmark_strbuf_puts(html, "\" title=\"");
+ escape_html(html, node->as.link.title.data, node->as.link.title.len);
+ }
+ cmark_strbuf_puts(html, "\">");
+ } else {
+ cmark_strbuf_puts(html, "");
+ }
+ break;
+
+ case CMARK_NODE_IMAGE:
+ if (entering) {
+ cmark_strbuf_puts(html, "as.link.url, 0))) {
+ houdini_escape_href(html, node->as.link.url.data,
+ node->as.link.url.len);
+ }
+ cmark_strbuf_puts(html, "\" alt=\"");
+ state->plain = node;
+ } else {
+ if (node->as.link.title.len) {
+ cmark_strbuf_puts(html, "\" title=\"");
+ escape_html(html, node->as.link.title.data, node->as.link.title.len);
+ }
+
+ cmark_strbuf_puts(html, "\" />");
+ }
+ break;
+
+ default:
+ assert(false);
+ break;
+ }
+
+ // cmark_strbuf_putc(html, 'x');
+ return 1;
+}
+
+char *cmark_render_html(cmark_node *root, int options) {
+ char *result;
+ cmark_strbuf html = CMARK_BUF_INIT(cmark_node_mem(root));
+ cmark_event_type ev_type;
+ cmark_node *cur;
+ struct render_state state = {&html, NULL};
+ cmark_iter *iter = cmark_iter_new(root);
+
+ while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
+ cur = cmark_iter_get_node(iter);
+ S_render_node(cur, ev_type, &state, options);
+ }
+ result = (char *)cmark_strbuf_detach(&html);
+
+ cmark_iter_free(iter);
+ return result;
+}
diff --git a/include/cmark/inlines.c b/include/cmark/inlines.c
new file mode 100644
index 0000000..d31173d
--- /dev/null
+++ b/include/cmark/inlines.c
@@ -0,0 +1,1374 @@
+#include
+#include
+#include
+
+#include "cmark_ctype.h"
+#include "config.h"
+#include "node.h"
+#include "parser.h"
+#include "references.h"
+#include "cmark.h"
+#include "houdini.h"
+#include "utf8.h"
+#include "scanners.h"
+#include "inlines.h"
+
+static const char *EMDASH = "\xE2\x80\x94";
+static const char *ENDASH = "\xE2\x80\x93";
+static const char *ELLIPSES = "\xE2\x80\xA6";
+static const char *LEFTDOUBLEQUOTE = "\xE2\x80\x9C";
+static const char *RIGHTDOUBLEQUOTE = "\xE2\x80\x9D";
+static const char *LEFTSINGLEQUOTE = "\xE2\x80\x98";
+static const char *RIGHTSINGLEQUOTE = "\xE2\x80\x99";
+
+// Macros for creating various kinds of simple.
+#define make_str(subj, sc, ec, s) make_literal(subj, CMARK_NODE_TEXT, sc, ec, s)
+#define make_code(subj, sc, ec, s) make_literal(subj, CMARK_NODE_CODE, sc, ec, s)
+#define make_raw_html(subj, sc, ec, s) make_literal(subj, CMARK_NODE_HTML_INLINE, sc, ec, s)
+#define make_linebreak(mem) make_simple(mem, CMARK_NODE_LINEBREAK)
+#define make_softbreak(mem) make_simple(mem, CMARK_NODE_SOFTBREAK)
+#define make_emph(mem) make_simple(mem, CMARK_NODE_EMPH)
+#define make_strong(mem) make_simple(mem, CMARK_NODE_STRONG)
+
+#define MAXBACKTICKS 1000
+
+typedef struct delimiter {
+ struct delimiter *previous;
+ struct delimiter *next;
+ cmark_node *inl_text;
+ bufsize_t length;
+ unsigned char delim_char;
+ bool can_open;
+ bool can_close;
+} delimiter;
+
+typedef struct bracket {
+ struct bracket *previous;
+ struct delimiter *previous_delimiter;
+ cmark_node *inl_text;
+ bufsize_t position;
+ bool image;
+ bool active;
+ bool bracket_after;
+} bracket;
+
+typedef struct {
+ cmark_mem *mem;
+ cmark_chunk input;
+ int line;
+ bufsize_t pos;
+ int block_offset;
+ int column_offset;
+ cmark_reference_map *refmap;
+ delimiter *last_delim;
+ bracket *last_bracket;
+ bufsize_t backticks[MAXBACKTICKS + 1];
+ bool scanned_for_backticks;
+} subject;
+
+static CMARK_INLINE bool S_is_line_end_char(char c) {
+ return (c == '\n' || c == '\r');
+}
+
+static delimiter *S_insert_emph(subject *subj, delimiter *opener,
+ delimiter *closer);
+
+static int parse_inline(subject *subj, cmark_node *parent, int options);
+
+static void subject_from_buf(cmark_mem *mem, int line_number, int block_offset, subject *e,
+ cmark_chunk *chunk, cmark_reference_map *refmap);
+static bufsize_t subject_find_special_char(subject *subj, int options);
+
+// Create an inline with a literal string value.
+static CMARK_INLINE cmark_node *make_literal(subject *subj, cmark_node_type t,
+ int start_column, int end_column,
+ cmark_chunk s) {
+ cmark_node *e = (cmark_node *)subj->mem->calloc(1, sizeof(*e));
+ cmark_strbuf_init(subj->mem, &e->content, 0);
+ e->type = (uint16_t)t;
+ e->as.literal = s;
+ e->start_line = e->end_line = subj->line;
+ // columns are 1 based.
+ e->start_column = start_column + 1 + subj->column_offset + subj->block_offset;
+ e->end_column = end_column + 1 + subj->column_offset + subj->block_offset;
+ return e;
+}
+
+// Create an inline with no value.
+static CMARK_INLINE cmark_node *make_simple(cmark_mem *mem, cmark_node_type t) {
+ cmark_node *e = (cmark_node *)mem->calloc(1, sizeof(*e));
+ cmark_strbuf_init(mem, &e->content, 0);
+ e->type = t;
+ return e;
+}
+
+// Like make_str, but parses entities.
+static cmark_node *make_str_with_entities(subject *subj,
+ int start_column, int end_column,
+ cmark_chunk *content) {
+ cmark_strbuf unescaped = CMARK_BUF_INIT(subj->mem);
+
+ if (houdini_unescape_html(&unescaped, content->data, content->len)) {
+ return make_str(subj, start_column, end_column, cmark_chunk_buf_detach(&unescaped));
+ } else {
+ return make_str(subj, start_column, end_column, *content);
+ }
+}
+
+// Duplicate a chunk by creating a copy of the buffer not by reusing the
+// buffer like cmark_chunk_dup does.
+static cmark_chunk chunk_clone(cmark_mem *mem, cmark_chunk *src) {
+ cmark_chunk c;
+ bufsize_t len = src->len;
+
+ c.len = len;
+ c.data = (unsigned char *)mem->calloc(len + 1, 1);
+ c.alloc = 1;
+ if (len)
+ memcpy(c.data, src->data, len);
+ c.data[len] = '\0';
+
+ return c;
+}
+
+static cmark_chunk cmark_clean_autolink(cmark_mem *mem, cmark_chunk *url,
+ int is_email) {
+ cmark_strbuf buf = CMARK_BUF_INIT(mem);
+
+ cmark_chunk_trim(url);
+
+ if (url->len == 0) {
+ cmark_chunk result = CMARK_CHUNK_EMPTY;
+ return result;
+ }
+
+ if (is_email)
+ cmark_strbuf_puts(&buf, "mailto:");
+
+ houdini_unescape_html_f(&buf, url->data, url->len);
+ return cmark_chunk_buf_detach(&buf);
+}
+
+static CMARK_INLINE cmark_node *make_autolink(subject *subj,
+ int start_column, int end_column,
+ cmark_chunk url, int is_email) {
+ cmark_node *link = make_simple(subj->mem, CMARK_NODE_LINK);
+ link->as.link.url = cmark_clean_autolink(subj->mem, &url, is_email);
+ link->as.link.title = cmark_chunk_literal("");
+ link->start_line = link->end_line = subj->line;
+ link->start_column = start_column + 1;
+ link->end_column = end_column + 1;
+ cmark_node_append_child(link, make_str_with_entities(subj, start_column + 1, end_column - 1, &url));
+ return link;
+}
+
+static void subject_from_buf(cmark_mem *mem, int line_number, int block_offset, subject *e,
+ cmark_chunk *chunk, cmark_reference_map *refmap) {
+ int i;
+ e->mem = mem;
+ e->input = *chunk;
+ e->line = line_number;
+ e->pos = 0;
+ e->block_offset = block_offset;
+ e->column_offset = 0;
+ e->refmap = refmap;
+ e->last_delim = NULL;
+ e->last_bracket = NULL;
+ for (i = 0; i <= MAXBACKTICKS; i++) {
+ e->backticks[i] = 0;
+ }
+ e->scanned_for_backticks = false;
+}
+
+static CMARK_INLINE int isbacktick(int c) { return (c == '`'); }
+
+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 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 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 CMARK_INLINE bool skip_spaces(subject *subj) {
+ bool skipped = false;
+ while (peek_char(subj) == ' ' || peek_char(subj) == '\t') {
+ advance(subj);
+ skipped = true;
+ }
+ return skipped;
+}
+
+static CMARK_INLINE bool skip_line_end(subject *subj) {
+ bool seen_line_end_char = false;
+ if (peek_char(subj) == '\r') {
+ advance(subj);
+ seen_line_end_char = true;
+ }
+ if (peek_char(subj) == '\n') {
+ advance(subj);
+ seen_line_end_char = true;
+ }
+ return seen_line_end_char || is_eof(subj);
+}
+
+// Take characters while a predicate holds, and return a string.
+static CMARK_INLINE cmark_chunk take_while(subject *subj, int (*f)(int)) {
+ unsigned char c;
+ bufsize_t startpos = subj->pos;
+ bufsize_t len = 0;
+
+ while ((c = peek_char(subj)) && (*f)(c)) {
+ advance(subj);
+ len++;
+ }
+
+ return cmark_chunk_dup(&subj->input, startpos, len);
+}
+
+// Return the number of newlines in a given span of text in a subject. If
+// the number is greater than zero, also return the number of characters
+// between the last newline and the end of the span in `since_newline`.
+static int count_newlines(subject *subj, bufsize_t from, bufsize_t len, int *since_newline) {
+ int nls = 0;
+ int since_nl = 0;
+
+ while (len--) {
+ if (subj->input.data[from++] == '\n') {
+ ++nls;
+ since_nl = 0;
+ } else {
+ ++since_nl;
+ }
+ }
+
+ if (!nls)
+ return 0;
+
+ *since_newline = since_nl;
+ return nls;
+}
+
+// Adjust `node`'s `end_line`, `end_column`, and `subj`'s `line` and
+// `column_offset` according to the number of newlines in a just-matched span
+// of text in `subj`.
+static void adjust_subj_node_newlines(subject *subj, cmark_node *node, int matchlen, int extra, int options) {
+ if (!(options & CMARK_OPT_SOURCEPOS)) {
+ return;
+ }
+
+ int since_newline;
+ int newlines = count_newlines(subj, subj->pos - matchlen - extra, matchlen, &since_newline);
+ if (newlines) {
+ subj->line += newlines;
+ node->end_line += newlines;
+ node->end_column = since_newline;
+ subj->column_offset = -subj->pos + since_newline + extra;
+ }
+}
+
+// Try to process a backtick code span that began with a
+// span of ticks of length openticklength length (already
+// parsed). Return 0 if you don't find matching closing
+// backticks, otherwise return the position in the subject
+// after the closing backticks.
+static bufsize_t scan_to_closing_backticks(subject *subj,
+ bufsize_t openticklength) {
+
+ bool found = false;
+ if (openticklength > MAXBACKTICKS) {
+ // we limit backtick string length because of the array subj->backticks:
+ return 0;
+ }
+ if (subj->scanned_for_backticks &&
+ subj->backticks[openticklength] <= subj->pos) {
+ // return if we already know there's no closer
+ return 0;
+ }
+ while (!found) {
+ // read non backticks
+ unsigned char c;
+ while ((c = peek_char(subj)) && c != '`') {
+ advance(subj);
+ }
+ if (is_eof(subj)) {
+ break;
+ }
+ bufsize_t numticks = 0;
+ while (peek_char(subj) == '`') {
+ advance(subj);
+ numticks++;
+ }
+ // store position of ender
+ if (numticks <= MAXBACKTICKS) {
+ subj->backticks[numticks] = subj->pos - numticks;
+ }
+ if (numticks == openticklength) {
+ return (subj->pos);
+ }
+ }
+ // got through whole input without finding closer
+ subj->scanned_for_backticks = true;
+ return 0;
+}
+
+// Destructively modify string, converting newlines to
+// spaces, then removing a single leading + trailing space.
+static void S_normalize_code(cmark_strbuf *s) {
+ bufsize_t r, w;
+
+ for (r = 0, w = 0; r < s->size; ++r) {
+ switch (s->ptr[r]) {
+ case '\r':
+ if (s->ptr[r + 1] != '\n') {
+ s->ptr[w++] = ' ';
+ }
+ break;
+ case '\n':
+ s->ptr[w++] = ' ';
+ break;
+ default:
+ s->ptr[w++] = s->ptr[r];
+ }
+ }
+
+ // begins and ends with space?
+ if (s->ptr[0] == ' ' && s->ptr[w - 1] == ' ') {
+ cmark_strbuf_drop(s, 1);
+ cmark_strbuf_truncate(s, w - 2);
+ } else {
+ cmark_strbuf_truncate(s, w);
+ }
+
+}
+
+
+// Parse backtick code section or raw backticks, return an inline.
+// Assumes that the subject has a backtick at the current position.
+static cmark_node *handle_backticks(subject *subj, int options) {
+ cmark_chunk openticks = take_while(subj, isbacktick);
+ bufsize_t startpos = subj->pos;
+ bufsize_t endpos = scan_to_closing_backticks(subj, openticks.len);
+
+ if (endpos == 0) { // not found
+ subj->pos = startpos; // rewind
+ return make_str(subj, subj->pos, subj->pos, openticks);
+ } else {
+ cmark_strbuf buf = CMARK_BUF_INIT(subj->mem);
+
+ cmark_strbuf_set(&buf, subj->input.data + startpos,
+ endpos - startpos - openticks.len);
+ S_normalize_code(&buf);
+
+ cmark_node *node = make_code(subj, startpos, endpos - openticks.len - 1, cmark_chunk_buf_detach(&buf));
+ adjust_subj_node_newlines(subj, node, endpos - startpos, openticks.len, options);
+ return node;
+ }
+}
+
+
+// Scan ***, **, or * and return number scanned, or 0.
+// Advances position.
+static int scan_delims(subject *subj, unsigned char c, bool *can_open,
+ bool *can_close) {
+ int numdelims = 0;
+ bufsize_t before_char_pos;
+ int32_t after_char = 0;
+ int32_t before_char = 0;
+ int len;
+ bool left_flanking, right_flanking;
+
+ if (subj->pos == 0) {
+ before_char = 10;
+ } else {
+ before_char_pos = subj->pos - 1;
+ // walk back to the beginning of the UTF_8 sequence:
+ while (peek_at(subj, before_char_pos) >> 6 == 2 && before_char_pos > 0) {
+ before_char_pos -= 1;
+ }
+ len = cmark_utf8proc_iterate(subj->input.data + before_char_pos,
+ subj->pos - before_char_pos, &before_char);
+ if (len == -1) {
+ before_char = 10;
+ }
+ }
+
+ if (c == '\'' || c == '"') {
+ numdelims++;
+ advance(subj); // limit to 1 delim for quotes
+ } else {
+ while (peek_char(subj) == c) {
+ numdelims++;
+ advance(subj);
+ }
+ }
+
+ len = cmark_utf8proc_iterate(subj->input.data + subj->pos,
+ subj->input.len - subj->pos, &after_char);
+ if (len == -1) {
+ after_char = 10;
+ }
+ left_flanking = numdelims > 0 && !cmark_utf8proc_is_space(after_char) &&
+ (!cmark_utf8proc_is_punctuation(after_char) ||
+ cmark_utf8proc_is_space(before_char) ||
+ cmark_utf8proc_is_punctuation(before_char));
+ right_flanking = numdelims > 0 && !cmark_utf8proc_is_space(before_char) &&
+ (!cmark_utf8proc_is_punctuation(before_char) ||
+ cmark_utf8proc_is_space(after_char) ||
+ cmark_utf8proc_is_punctuation(after_char));
+ if (c == '_') {
+ *can_open = left_flanking &&
+ (!right_flanking || cmark_utf8proc_is_punctuation(before_char));
+ *can_close = right_flanking &&
+ (!left_flanking || cmark_utf8proc_is_punctuation(after_char));
+ } else if (c == '\'' || c == '"') {
+ *can_open = left_flanking && !right_flanking &&
+ before_char != ']' && before_char != ')';
+ *can_close = right_flanking;
+ } else {
+ *can_open = left_flanking;
+ *can_close = right_flanking;
+ }
+ return numdelims;
+}
+
+/*
+static void print_delimiters(subject *subj)
+{
+ delimiter *delim;
+ delim = subj->last_delim;
+ while (delim != NULL) {
+ printf("Item at stack pos %p: %d %d %d next(%p) prev(%p)\n",
+ (void*)delim, delim->delim_char,
+ delim->can_open, delim->can_close,
+ (void*)delim->next, (void*)delim->previous);
+ delim = delim->previous;
+ }
+}
+*/
+
+static void remove_delimiter(subject *subj, delimiter *delim) {
+ if (delim == NULL)
+ return;
+ if (delim->next == NULL) {
+ // end of list:
+ assert(delim == subj->last_delim);
+ subj->last_delim = delim->previous;
+ } else {
+ delim->next->previous = delim->previous;
+ }
+ if (delim->previous != NULL) {
+ delim->previous->next = delim->next;
+ }
+ subj->mem->free(delim);
+}
+
+static void pop_bracket(subject *subj) {
+ bracket *b;
+ if (subj->last_bracket == NULL)
+ return;
+ b = subj->last_bracket;
+ subj->last_bracket = subj->last_bracket->previous;
+ subj->mem->free(b);
+}
+
+static void push_delimiter(subject *subj, unsigned char c, bool can_open,
+ bool can_close, cmark_node *inl_text) {
+ delimiter *delim = (delimiter *)subj->mem->calloc(1, sizeof(delimiter));
+ delim->delim_char = c;
+ delim->can_open = can_open;
+ delim->can_close = can_close;
+ delim->inl_text = inl_text;
+ delim->length = inl_text->as.literal.len;
+ delim->previous = subj->last_delim;
+ delim->next = NULL;
+ if (delim->previous != NULL) {
+ delim->previous->next = delim;
+ }
+ subj->last_delim = delim;
+}
+
+static void push_bracket(subject *subj, bool image, cmark_node *inl_text) {
+ bracket *b = (bracket *)subj->mem->calloc(1, sizeof(bracket));
+ if (subj->last_bracket != NULL) {
+ subj->last_bracket->bracket_after = true;
+ }
+ b->image = image;
+ b->active = true;
+ b->inl_text = inl_text;
+ b->previous = subj->last_bracket;
+ b->previous_delimiter = subj->last_delim;
+ b->position = subj->pos;
+ b->bracket_after = false;
+ subj->last_bracket = b;
+}
+
+// Assumes the subject has a c at the current position.
+static cmark_node *handle_delim(subject *subj, unsigned char c, bool smart) {
+ bufsize_t numdelims;
+ cmark_node *inl_text;
+ bool can_open, can_close;
+ cmark_chunk contents;
+
+ numdelims = scan_delims(subj, c, &can_open, &can_close);
+
+ if (c == '\'' && smart) {
+ contents = cmark_chunk_literal(RIGHTSINGLEQUOTE);
+ } else if (c == '"' && smart) {
+ contents =
+ cmark_chunk_literal(can_close ? RIGHTDOUBLEQUOTE : LEFTDOUBLEQUOTE);
+ } else {
+ contents = cmark_chunk_dup(&subj->input, subj->pos - numdelims, numdelims);
+ }
+
+ inl_text = make_str(subj, subj->pos - numdelims, subj->pos - 1, contents);
+
+ if ((can_open || can_close) && (!(c == '\'' || c == '"') || smart)) {
+ push_delimiter(subj, c, can_open, can_close, inl_text);
+ }
+
+ return inl_text;
+}
+
+// Assumes we have a hyphen at the current position.
+static cmark_node *handle_hyphen(subject *subj, bool smart) {
+ int startpos = subj->pos;
+
+ advance(subj);
+
+ if (!smart || peek_char(subj) != '-') {
+ return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("-"));
+ }
+
+ while (smart && peek_char(subj) == '-') {
+ advance(subj);
+ }
+
+ int numhyphens = subj->pos - startpos;
+ int en_count = 0;
+ int em_count = 0;
+ int i;
+ cmark_strbuf buf = CMARK_BUF_INIT(subj->mem);
+
+ if (numhyphens % 3 == 0) { // if divisible by 3, use all em dashes
+ em_count = numhyphens / 3;
+ } else if (numhyphens % 2 == 0) { // if divisible by 2, use all en dashes
+ en_count = numhyphens / 2;
+ } else if (numhyphens % 3 == 2) { // use one en dash at end
+ en_count = 1;
+ em_count = (numhyphens - 2) / 3;
+ } else { // use two en dashes at the end
+ en_count = 2;
+ em_count = (numhyphens - 4) / 3;
+ }
+
+ for (i = em_count; i > 0; i--) {
+ cmark_strbuf_puts(&buf, EMDASH);
+ }
+
+ for (i = en_count; i > 0; i--) {
+ cmark_strbuf_puts(&buf, ENDASH);
+ }
+
+ return make_str(subj, startpos, subj->pos - 1, cmark_chunk_buf_detach(&buf));
+}
+
+// Assumes we have a period at the current position.
+static cmark_node *handle_period(subject *subj, bool smart) {
+ advance(subj);
+ if (smart && peek_char(subj) == '.') {
+ advance(subj);
+ if (peek_char(subj) == '.') {
+ advance(subj);
+ return make_str(subj, subj->pos - 3, subj->pos - 1, cmark_chunk_literal(ELLIPSES));
+ } else {
+ return make_str(subj, subj->pos - 2, subj->pos - 1, cmark_chunk_literal(".."));
+ }
+ } else {
+ return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("."));
+ }
+}
+
+static void process_emphasis(subject *subj, delimiter *stack_bottom) {
+ delimiter *closer = subj->last_delim;
+ delimiter *opener;
+ delimiter *old_closer;
+ bool opener_found;
+ int openers_bottom_index;
+ delimiter *openers_bottom[6] = {stack_bottom, stack_bottom, stack_bottom,
+ stack_bottom, stack_bottom, stack_bottom};
+
+ // move back to first relevant delim.
+ while (closer != NULL && closer->previous != stack_bottom) {
+ closer = closer->previous;
+ }
+
+ // now move forward, looking for closers, and handling each
+ while (closer != NULL) {
+ if (closer->can_close) {
+ switch (closer->delim_char) {
+ case '"':
+ openers_bottom_index = 0;
+ break;
+ case '\'':
+ openers_bottom_index = 1;
+ break;
+ case '_':
+ openers_bottom_index = 2;
+ break;
+ case '*':
+ openers_bottom_index = 3 + (closer->length % 3);
+ break;
+ default:
+ assert(false);
+ }
+
+ // Now look backwards for first matching opener:
+ opener = closer->previous;
+ opener_found = false;
+ while (opener != NULL && opener != openers_bottom[openers_bottom_index]) {
+ if (opener->can_open && opener->delim_char == closer->delim_char) {
+ // interior closer of size 2 can't match opener of size 1
+ // or of size 1 can't match 2
+ if (!(closer->can_open || opener->can_close) ||
+ ((opener->length + closer->length) % 3) != 0) {
+ opener_found = true;
+ break;
+ }
+ }
+ opener = opener->previous;
+ }
+ old_closer = closer;
+ if (closer->delim_char == '*' || closer->delim_char == '_') {
+ if (opener_found) {
+ closer = S_insert_emph(subj, opener, closer);
+ } else {
+ closer = closer->next;
+ }
+ } else if (closer->delim_char == '\'') {
+ cmark_chunk_free(subj->mem, &closer->inl_text->as.literal);
+ closer->inl_text->as.literal = cmark_chunk_literal(RIGHTSINGLEQUOTE);
+ if (opener_found) {
+ cmark_chunk_free(subj->mem, &opener->inl_text->as.literal);
+ opener->inl_text->as.literal = cmark_chunk_literal(LEFTSINGLEQUOTE);
+ }
+ closer = closer->next;
+ } else if (closer->delim_char == '"') {
+ cmark_chunk_free(subj->mem, &closer->inl_text->as.literal);
+ closer->inl_text->as.literal = cmark_chunk_literal(RIGHTDOUBLEQUOTE);
+ if (opener_found) {
+ cmark_chunk_free(subj->mem, &opener->inl_text->as.literal);
+ opener->inl_text->as.literal = cmark_chunk_literal(LEFTDOUBLEQUOTE);
+ }
+ closer = closer->next;
+ }
+ if (!opener_found) {
+ // set lower bound for future searches for openers
+ openers_bottom[openers_bottom_index] = old_closer->previous;
+ if (!old_closer->can_open) {
+ // we can remove a closer that can't be an
+ // opener, once we've seen there's no
+ // matching opener:
+ remove_delimiter(subj, old_closer);
+ }
+ }
+ } else {
+ closer = closer->next;
+ }
+ }
+ // free all delimiters in list until stack_bottom:
+ while (subj->last_delim != NULL && subj->last_delim != stack_bottom) {
+ remove_delimiter(subj, subj->last_delim);
+ }
+}
+
+static delimiter *S_insert_emph(subject *subj, delimiter *opener,
+ delimiter *closer) {
+ delimiter *delim, *tmp_delim;
+ bufsize_t use_delims;
+ cmark_node *opener_inl = opener->inl_text;
+ cmark_node *closer_inl = closer->inl_text;
+ bufsize_t opener_num_chars = opener_inl->as.literal.len;
+ bufsize_t closer_num_chars = closer_inl->as.literal.len;
+ cmark_node *tmp, *tmpnext, *emph;
+
+ // calculate the actual number of characters used from this closer
+ use_delims = (closer_num_chars >= 2 && opener_num_chars >= 2) ? 2 : 1;
+
+ // remove used characters from associated inlines.
+ opener_num_chars -= use_delims;
+ closer_num_chars -= use_delims;
+ opener_inl->as.literal.len = opener_num_chars;
+ closer_inl->as.literal.len = closer_num_chars;
+
+ // free delimiters between opener and closer
+ delim = closer->previous;
+ while (delim != NULL && delim != opener) {
+ tmp_delim = delim->previous;
+ remove_delimiter(subj, delim);
+ delim = tmp_delim;
+ }
+
+ // create new emph or strong, and splice it in to our inlines
+ // between the opener and closer
+ emph = use_delims == 1 ? make_emph(subj->mem) : make_strong(subj->mem);
+
+ tmp = opener_inl->next;
+ while (tmp && tmp != closer_inl) {
+ tmpnext = tmp->next;
+ cmark_node_append_child(emph, tmp);
+ tmp = tmpnext;
+ }
+ cmark_node_insert_after(opener_inl, emph);
+
+ emph->start_line = opener_inl->start_line;
+ emph->end_line = closer_inl->end_line;
+ emph->start_column = opener_inl->start_column;
+ emph->end_column = closer_inl->end_column;
+
+ // if opener has 0 characters, remove it and its associated inline
+ if (opener_num_chars == 0) {
+ cmark_node_free(opener_inl);
+ remove_delimiter(subj, opener);
+ }
+
+ // if closer has 0 characters, remove it and its associated inline
+ if (closer_num_chars == 0) {
+ // remove empty closer inline
+ cmark_node_free(closer_inl);
+ // remove closer from list
+ tmp_delim = closer->next;
+ remove_delimiter(subj, closer);
+ closer = tmp_delim;
+ }
+
+ return closer;
+}
+
+// Parse backslash-escape or just a backslash, returning an inline.
+static cmark_node *handle_backslash(subject *subj) {
+ advance(subj);
+ unsigned char nextchar = peek_char(subj);
+ if (cmark_ispunct(
+ nextchar)) { // only ascii symbols and newline can be escaped
+ advance(subj);
+ return make_str(subj, subj->pos - 2, subj->pos - 1, cmark_chunk_dup(&subj->input, subj->pos - 1, 1));
+ } else if (!is_eof(subj) && skip_line_end(subj)) {
+ return make_linebreak(subj->mem);
+ } else {
+ return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("\\"));
+ }
+}
+
+// Parse an entity or a regular "&" string.
+// Assumes the subject has an '&' character at the current position.
+static cmark_node *handle_entity(subject *subj) {
+ cmark_strbuf ent = CMARK_BUF_INIT(subj->mem);
+ bufsize_t len;
+
+ advance(subj);
+
+ len = houdini_unescape_ent(&ent, subj->input.data + subj->pos,
+ subj->input.len - subj->pos);
+
+ if (len == 0)
+ return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("&"));
+
+ subj->pos += len;
+ return make_str(subj, subj->pos - 1 - len, subj->pos - 1, cmark_chunk_buf_detach(&ent));
+}
+
+// Clean a URL: remove surrounding whitespace, and remove \ that escape
+// punctuation.
+cmark_chunk cmark_clean_url(cmark_mem *mem, cmark_chunk *url) {
+ cmark_strbuf buf = CMARK_BUF_INIT(mem);
+
+ cmark_chunk_trim(url);
+
+ if (url->len == 0) {
+ cmark_chunk result = CMARK_CHUNK_EMPTY;
+ return result;
+ }
+
+ houdini_unescape_html_f(&buf, url->data, url->len);
+
+ cmark_strbuf_unescape(&buf);
+ return cmark_chunk_buf_detach(&buf);
+}
+
+cmark_chunk cmark_clean_title(cmark_mem *mem, cmark_chunk *title) {
+ cmark_strbuf buf = CMARK_BUF_INIT(mem);
+ unsigned char first, last;
+
+ if (title->len == 0) {
+ cmark_chunk result = CMARK_CHUNK_EMPTY;
+ return result;
+ }
+
+ 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);
+ }
+
+ cmark_strbuf_unescape(&buf);
+ return cmark_chunk_buf_detach(&buf);
+}
+
+// Parse an autolink or HTML tag.
+// Assumes the subject has a '<' character at the current position.
+static cmark_node *handle_pointy_brace(subject *subj, int options) {
+ bufsize_t matchlen = 0;
+ cmark_chunk contents;
+
+ advance(subj); // advance past first <
+
+ // first try to match a URL autolink
+ matchlen = scan_autolink_uri(&subj->input, subj->pos);
+ if (matchlen > 0) {
+ contents = cmark_chunk_dup(&subj->input, subj->pos, matchlen - 1);
+ subj->pos += matchlen;
+
+ return make_autolink(subj, subj->pos - 1 - matchlen, subj->pos - 1, contents, 0);
+ }
+
+ // next try to match an email autolink
+ matchlen = scan_autolink_email(&subj->input, subj->pos);
+ if (matchlen > 0) {
+ contents = cmark_chunk_dup(&subj->input, subj->pos, matchlen - 1);
+ subj->pos += matchlen;
+
+ return make_autolink(subj, subj->pos - 1 - matchlen, subj->pos - 1, contents, 1);
+ }
+
+ // finally, try to match an html tag
+ matchlen = scan_html_tag(&subj->input, subj->pos);
+ if (matchlen > 0) {
+ contents = cmark_chunk_dup(&subj->input, subj->pos - 1, matchlen + 1);
+ subj->pos += matchlen;
+ cmark_node *node = make_raw_html(subj, subj->pos - matchlen - 1, subj->pos - 1, contents);
+ adjust_subj_node_newlines(subj, node, matchlen, 1, options);
+ return node;
+ }
+
+ // if nothing matches, just return the opening <:
+ return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("<"));
+}
+
+// Parse a link label. Returns 1 if successful.
+// Note: unescaped brackets are not allowed in labels.
+// The label begins with `[` and ends with the first `]` character
+// encountered. Backticks in labels do not start code spans.
+static int link_label(subject *subj, cmark_chunk *raw_label) {
+ bufsize_t startpos = subj->pos;
+ int length = 0;
+ unsigned char c;
+
+ // advance past [
+ if (peek_char(subj) == '[') {
+ advance(subj);
+ } else {
+ return 0;
+ }
+
+ while ((c = peek_char(subj)) && c != '[' && c != ']') {
+ if (c == '\\') {
+ advance(subj);
+ length++;
+ if (cmark_ispunct(peek_char(subj))) {
+ advance(subj);
+ length++;
+ }
+ } else {
+ advance(subj);
+ length++;
+ }
+ if (length > MAX_LINK_LABEL_LENGTH) {
+ goto noMatch;
+ }
+ }
+
+ if (c == ']') { // match found
+ *raw_label =
+ cmark_chunk_dup(&subj->input, startpos + 1, subj->pos - (startpos + 1));
+ cmark_chunk_trim(raw_label);
+ advance(subj); // advance past ]
+ return 1;
+ }
+
+noMatch:
+ subj->pos = startpos; // rewind
+ return 0;
+}
+
+static bufsize_t manual_scan_link_url_2(cmark_chunk *input, bufsize_t offset,
+ cmark_chunk *output) {
+ bufsize_t i = offset;
+ size_t nb_p = 0;
+
+ while (i < input->len) {
+ if (input->data[i] == '\\' &&
+ i + 1 < input-> len &&
+ cmark_ispunct(input->data[i+1]))
+ i += 2;
+ else if (input->data[i] == '(') {
+ ++nb_p;
+ ++i;
+ if (nb_p > 32)
+ return -1;
+ } else if (input->data[i] == ')') {
+ if (nb_p == 0)
+ break;
+ --nb_p;
+ ++i;
+ } else if (cmark_isspace(input->data[i]))
+ break;
+ else
+ ++i;
+ }
+
+ if (i >= input->len)
+ return -1;
+
+ {
+ cmark_chunk result = {input->data + offset, i - offset, 0};
+ *output = result;
+ }
+ return i - offset;
+}
+
+static bufsize_t manual_scan_link_url(cmark_chunk *input, bufsize_t offset,
+ cmark_chunk *output) {
+ bufsize_t i = offset;
+
+ if (i < input->len && input->data[i] == '<') {
+ ++i;
+ while (i < input->len) {
+ if (input->data[i] == '>') {
+ ++i;
+ break;
+ } else if (input->data[i] == '\\')
+ i += 2;
+ else if (input->data[i] == '\n' || input->data[i] == '<')
+ return manual_scan_link_url_2(input, offset, output);
+ else
+ ++i;
+ }
+ } else {
+ return manual_scan_link_url_2(input, offset, output);
+ }
+
+ if (i >= input->len)
+ return -1;
+
+ {
+ cmark_chunk result = {input->data + offset + 1, i - 2 - offset, 0};
+ *output = result;
+ }
+ return i - offset;
+}
+
+// Return a link, an image, or a literal close bracket.
+static cmark_node *handle_close_bracket(subject *subj) {
+ bufsize_t initial_pos, after_link_text_pos;
+ bufsize_t endurl, starttitle, endtitle, endall;
+ bufsize_t sps, n;
+ cmark_reference *ref = NULL;
+ cmark_chunk url_chunk, title_chunk;
+ cmark_chunk url, title;
+ bracket *opener;
+ cmark_node *inl;
+ cmark_chunk raw_label;
+ int found_label;
+ cmark_node *tmp, *tmpnext;
+ bool is_image;
+
+ advance(subj); // advance past ]
+ initial_pos = subj->pos;
+
+ // get last [ or ![
+ opener = subj->last_bracket;
+
+ if (opener == NULL) {
+ return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]"));
+ }
+
+ if (!opener->active) {
+ // take delimiter off stack
+ pop_bracket(subj);
+ return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]"));
+ }
+
+ // If we got here, we matched a potential link/image text.
+ // Now we check to see if it's a link/image.
+ is_image = opener->image;
+
+ after_link_text_pos = subj->pos;
+
+ // First, look for an inline link.
+ if (peek_char(subj) == '(' &&
+ ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) &&
+ ((n = manual_scan_link_url(&subj->input, subj->pos + 1 + sps,
+ &url_chunk)) > -1)) {
+
+ // try to parse an explicit link:
+ endurl = subj->pos + 1 + sps + n;
+ starttitle = endurl + scan_spacechars(&subj->input, endurl);
+
+ // ensure there are spaces btw url and title
+ endtitle = (starttitle == endurl)
+ ? starttitle
+ : starttitle + scan_link_title(&subj->input, starttitle);
+
+ endall = endtitle + scan_spacechars(&subj->input, endtitle);
+
+ if (peek_at(subj, endall) == ')') {
+ subj->pos = endall + 1;
+
+ title_chunk =
+ cmark_chunk_dup(&subj->input, starttitle, endtitle - starttitle);
+ url = cmark_clean_url(subj->mem, &url_chunk);
+ title = cmark_clean_title(subj->mem, &title_chunk);
+ cmark_chunk_free(subj->mem, &url_chunk);
+ cmark_chunk_free(subj->mem, &title_chunk);
+ goto match;
+
+ } else {
+ // it could still be a shortcut reference link
+ subj->pos = after_link_text_pos;
+ }
+ }
+
+ // Next, look for a following [link label] that matches in refmap.
+ // skip spaces
+ raw_label = cmark_chunk_literal("");
+ found_label = link_label(subj, &raw_label);
+ if (!found_label) {
+ // If we have a shortcut reference link, back up
+ // to before the spacse we skipped.
+ subj->pos = initial_pos;
+ }
+
+ if ((!found_label || raw_label.len == 0) && !opener->bracket_after) {
+ cmark_chunk_free(subj->mem, &raw_label);
+ raw_label = cmark_chunk_dup(&subj->input, opener->position,
+ initial_pos - opener->position - 1);
+ found_label = true;
+ }
+
+ if (found_label) {
+ ref = cmark_reference_lookup(subj->refmap, &raw_label);
+ cmark_chunk_free(subj->mem, &raw_label);
+ }
+
+ if (ref != NULL) { // found
+ url = chunk_clone(subj->mem, &ref->url);
+ title = chunk_clone(subj->mem, &ref->title);
+ goto match;
+ } else {
+ goto noMatch;
+ }
+
+noMatch:
+ // If we fall through to here, it means we didn't match a link:
+ pop_bracket(subj); // remove this opener from delimiter list
+ subj->pos = initial_pos;
+ return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]"));
+
+match:
+ inl = make_simple(subj->mem, is_image ? CMARK_NODE_IMAGE : CMARK_NODE_LINK);
+ inl->as.link.url = url;
+ inl->as.link.title = title;
+ inl->start_line = inl->end_line = subj->line;
+ inl->start_column = opener->inl_text->start_column;
+ inl->end_column = subj->pos + subj->column_offset + subj->block_offset;
+ cmark_node_insert_before(opener->inl_text, inl);
+ // Add link text:
+ tmp = opener->inl_text->next;
+ while (tmp) {
+ tmpnext = tmp->next;
+ cmark_node_append_child(inl, tmp);
+ tmp = tmpnext;
+ }
+
+ // Free the bracket [:
+ cmark_node_free(opener->inl_text);
+
+ process_emphasis(subj, opener->previous_delimiter);
+ pop_bracket(subj);
+
+ // Now, if we have a link, we also want to deactivate earlier link
+ // delimiters. (This code can be removed if we decide to allow links
+ // inside links.)
+ if (!is_image) {
+ opener = subj->last_bracket;
+ while (opener != NULL) {
+ if (!opener->image) {
+ if (!opener->active) {
+ break;
+ } else {
+ opener->active = false;
+ }
+ }
+ opener = opener->previous;
+ }
+ }
+
+ return NULL;
+}
+
+// Parse a hard or soft linebreak, returning an inline.
+// Assumes the subject has a cr or newline at the current position.
+static cmark_node *handle_newline(subject *subj) {
+ bufsize_t nlpos = subj->pos;
+ // skip over cr, crlf, or lf:
+ if (peek_at(subj, subj->pos) == '\r') {
+ advance(subj);
+ }
+ if (peek_at(subj, subj->pos) == '\n') {
+ advance(subj);
+ }
+ ++subj->line;
+ subj->column_offset = -subj->pos;
+ // skip spaces at beginning of line
+ skip_spaces(subj);
+ if (nlpos > 1 && peek_at(subj, nlpos - 1) == ' ' &&
+ peek_at(subj, nlpos - 2) == ' ') {
+ return make_linebreak(subj->mem);
+ } else {
+ return make_softbreak(subj->mem);
+ }
+}
+
+static bufsize_t subject_find_special_char(subject *subj, int options) {
+ // "\r\n\\`&_*[]pos + 1;
+
+ while (n < subj->input.len) {
+ if (SPECIAL_CHARS[subj->input.data[n]])
+ return n;
+ if (options & CMARK_OPT_SMART && SMART_PUNCT_CHARS[subj->input.data[n]])
+ return n;
+ n++;
+ }
+
+ return subj->input.len;
+}
+
+// Parse an inline, advancing subject, and add it as a child of parent.
+// Return 0 if no inline can be parsed, 1 otherwise.
+static int parse_inline(subject *subj, cmark_node *parent, int options) {
+ cmark_node *new_inl = NULL;
+ cmark_chunk contents;
+ unsigned char c;
+ bufsize_t startpos, endpos;
+ c = peek_char(subj);
+ if (c == 0) {
+ return 0;
+ }
+ switch (c) {
+ case '\r':
+ case '\n':
+ new_inl = handle_newline(subj);
+ break;
+ case '`':
+ new_inl = handle_backticks(subj, options);
+ break;
+ case '\\':
+ new_inl = handle_backslash(subj);
+ break;
+ case '&':
+ new_inl = handle_entity(subj);
+ break;
+ case '<':
+ new_inl = handle_pointy_brace(subj, options);
+ break;
+ case '*':
+ case '_':
+ case '\'':
+ case '"':
+ new_inl = handle_delim(subj, c, (options & CMARK_OPT_SMART) != 0);
+ break;
+ case '-':
+ new_inl = handle_hyphen(subj, (options & CMARK_OPT_SMART) != 0);
+ break;
+ case '.':
+ new_inl = handle_period(subj, (options & CMARK_OPT_SMART) != 0);
+ break;
+ case '[':
+ advance(subj);
+ new_inl = make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("["));
+ push_bracket(subj, false, new_inl);
+ break;
+ case ']':
+ new_inl = handle_close_bracket(subj);
+ break;
+ case '!':
+ advance(subj);
+ if (peek_char(subj) == '[') {
+ advance(subj);
+ new_inl = make_str(subj, subj->pos - 2, subj->pos - 1, cmark_chunk_literal("!["));
+ push_bracket(subj, true, new_inl);
+ } else {
+ new_inl = make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("!"));
+ }
+ break;
+ default:
+ endpos = subject_find_special_char(subj, options);
+ contents = cmark_chunk_dup(&subj->input, subj->pos, endpos - subj->pos);
+ startpos = subj->pos;
+ subj->pos = endpos;
+
+ // if we're at a newline, strip trailing spaces.
+ if (S_is_line_end_char(peek_char(subj))) {
+ cmark_chunk_rtrim(&contents);
+ }
+
+ new_inl = make_str(subj, startpos, endpos - 1, contents);
+ }
+ if (new_inl != NULL) {
+ cmark_node_append_child(parent, new_inl);
+ }
+
+ return 1;
+}
+
+// Parse inlines from parent's string_content, adding as children of parent.
+extern void cmark_parse_inlines(cmark_mem *mem, cmark_node *parent,
+ cmark_reference_map *refmap, int options) {
+ subject subj;
+ cmark_chunk content = {parent->content.ptr, parent->content.size, 0};
+ subject_from_buf(mem, parent->start_line, parent->start_column - 1 + parent->internal_offset, &subj, &content, refmap);
+ cmark_chunk_rtrim(&subj.input);
+
+ while (!is_eof(&subj) && parse_inline(&subj, parent, options))
+ ;
+
+ process_emphasis(&subj, NULL);
+ // free bracket and delim stack
+ while (subj.last_delim) {
+ remove_delimiter(&subj, subj.last_delim);
+ }
+ while (subj.last_bracket) {
+ pop_bracket(&subj);
+ }
+}
+
+// Parse zero or more space characters, including at most one newline.
+static void spnl(subject *subj) {
+ skip_spaces(subj);
+ if (skip_line_end(subj)) {
+ skip_spaces(subj);
+ }
+}
+
+// Parse reference. Assumes string begins with '[' character.
+// Modify refmap if a reference is encountered.
+// Return 0 if no reference found, otherwise position of subject
+// after reference is parsed.
+bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input,
+ cmark_reference_map *refmap) {
+ subject subj;
+
+ cmark_chunk lab;
+ cmark_chunk url;
+ cmark_chunk title;
+
+ bufsize_t matchlen = 0;
+ bufsize_t beforetitle;
+
+ subject_from_buf(mem, -1, 0, &subj, input, NULL);
+
+ // parse label:
+ if (!link_label(&subj, &lab) || lab.len == 0)
+ return 0;
+
+ // colon:
+ if (peek_char(&subj) == ':') {
+ advance(&subj);
+ } else {
+ return 0;
+ }
+
+ // parse link url:
+ spnl(&subj);
+ if ((matchlen = manual_scan_link_url(&subj.input, subj.pos, &url)) > -1 &&
+ url.len > 0) {
+ subj.pos += matchlen;
+ } else {
+ return 0;
+ }
+
+ // parse optional link_title
+ beforetitle = subj.pos;
+ spnl(&subj);
+ matchlen = subj.pos == beforetitle ? 0 : scan_link_title(&subj.input, subj.pos);
+ if (matchlen) {
+ title = cmark_chunk_dup(&subj.input, subj.pos, matchlen);
+ subj.pos += matchlen;
+ } else {
+ subj.pos = beforetitle;
+ title = cmark_chunk_literal("");
+ }
+
+ // parse final spaces and newline:
+ skip_spaces(&subj);
+ if (!skip_line_end(&subj)) {
+ if (matchlen) { // try rewinding before title
+ subj.pos = beforetitle;
+ skip_spaces(&subj);
+ if (!skip_line_end(&subj)) {
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+ }
+ // insert reference into refmap
+ cmark_reference_create(refmap, &lab, &url, &title);
+ return subj.pos;
+}
diff --git a/include/cmark/inlines.h b/include/cmark/inlines.h
new file mode 100644
index 0000000..39d3363
--- /dev/null
+++ b/include/cmark/inlines.h
@@ -0,0 +1,21 @@
+#ifndef CMARK_INLINES_H
+#define CMARK_INLINES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cmark_chunk cmark_clean_url(cmark_mem *mem, cmark_chunk *url);
+cmark_chunk cmark_clean_title(cmark_mem *mem, cmark_chunk *title);
+
+void cmark_parse_inlines(cmark_mem *mem, cmark_node *parent,
+ cmark_reference_map *refmap, int options);
+
+bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input,
+ cmark_reference_map *refmap);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cmark/iterator.c b/include/cmark/iterator.c
new file mode 100644
index 0000000..f5cd802
--- /dev/null
+++ b/include/cmark/iterator.c
@@ -0,0 +1,121 @@
+#include
+#include
+
+#include "config.h"
+#include "node.h"
+#include "cmark.h"
+#include "iterator.h"
+
+static const int S_leaf_mask =
+ (1 << CMARK_NODE_HTML_BLOCK) | (1 << CMARK_NODE_THEMATIC_BREAK) |
+ (1 << CMARK_NODE_CODE_BLOCK) | (1 << CMARK_NODE_TEXT) |
+ (1 << CMARK_NODE_SOFTBREAK) | (1 << CMARK_NODE_LINEBREAK) |
+ (1 << CMARK_NODE_CODE) | (1 << CMARK_NODE_HTML_INLINE);
+
+cmark_iter *cmark_iter_new(cmark_node *root) {
+ if (root == NULL) {
+ return NULL;
+ }
+ cmark_mem *mem = root->content.mem;
+ cmark_iter *iter = (cmark_iter *)mem->calloc(1, sizeof(cmark_iter));
+ iter->mem = mem;
+ iter->root = root;
+ iter->cur.ev_type = CMARK_EVENT_NONE;
+ iter->cur.node = NULL;
+ iter->next.ev_type = CMARK_EVENT_ENTER;
+ iter->next.node = root;
+ return iter;
+}
+
+void cmark_iter_free(cmark_iter *iter) { iter->mem->free(iter); }
+
+static bool S_is_leaf(cmark_node *node) {
+ return ((1 << node->type) & S_leaf_mask) != 0;
+}
+
+cmark_event_type cmark_iter_next(cmark_iter *iter) {
+ cmark_event_type ev_type = iter->next.ev_type;
+ cmark_node *node = iter->next.node;
+
+ iter->cur.ev_type = ev_type;
+ iter->cur.node = node;
+
+ if (ev_type == CMARK_EVENT_DONE) {
+ return ev_type;
+ }
+
+ /* roll forward to next item, setting both fields */
+ if (ev_type == CMARK_EVENT_ENTER && !S_is_leaf(node)) {
+ if (node->first_child == NULL) {
+ /* stay on this node but exit */
+ iter->next.ev_type = CMARK_EVENT_EXIT;
+ } else {
+ iter->next.ev_type = CMARK_EVENT_ENTER;
+ iter->next.node = node->first_child;
+ }
+ } else if (node == iter->root) {
+ /* don't move past root */
+ iter->next.ev_type = CMARK_EVENT_DONE;
+ iter->next.node = NULL;
+ } else if (node->next) {
+ iter->next.ev_type = CMARK_EVENT_ENTER;
+ iter->next.node = node->next;
+ } else if (node->parent) {
+ iter->next.ev_type = CMARK_EVENT_EXIT;
+ iter->next.node = node->parent;
+ } else {
+ assert(false);
+ iter->next.ev_type = CMARK_EVENT_DONE;
+ iter->next.node = NULL;
+ }
+
+ return ev_type;
+}
+
+void cmark_iter_reset(cmark_iter *iter, cmark_node *current,
+ cmark_event_type event_type) {
+ iter->next.ev_type = event_type;
+ iter->next.node = current;
+ cmark_iter_next(iter);
+}
+
+cmark_node *cmark_iter_get_node(cmark_iter *iter) { return iter->cur.node; }
+
+cmark_event_type cmark_iter_get_event_type(cmark_iter *iter) {
+ return iter->cur.ev_type;
+}
+
+cmark_node *cmark_iter_get_root(cmark_iter *iter) { return iter->root; }
+
+void cmark_consolidate_text_nodes(cmark_node *root) {
+ if (root == NULL) {
+ return;
+ }
+ cmark_iter *iter = cmark_iter_new(root);
+ cmark_strbuf buf = CMARK_BUF_INIT(iter->mem);
+ cmark_event_type ev_type;
+ cmark_node *cur, *tmp, *next;
+
+ while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
+ cur = cmark_iter_get_node(iter);
+ if (ev_type == CMARK_EVENT_ENTER && cur->type == CMARK_NODE_TEXT &&
+ cur->next && cur->next->type == CMARK_NODE_TEXT) {
+ cmark_strbuf_clear(&buf);
+ cmark_strbuf_put(&buf, cur->as.literal.data, cur->as.literal.len);
+ tmp = cur->next;
+ while (tmp && tmp->type == CMARK_NODE_TEXT) {
+ cmark_iter_next(iter); // advance pointer
+ cmark_strbuf_put(&buf, tmp->as.literal.data, tmp->as.literal.len);
+ cur->end_column = tmp->end_column;
+ next = tmp->next;
+ cmark_node_free(tmp);
+ tmp = next;
+ }
+ cmark_chunk_free(iter->mem, &cur->as.literal);
+ cur->as.literal = cmark_chunk_buf_detach(&buf);
+ }
+ }
+
+ cmark_strbuf_free(&buf);
+ cmark_iter_free(iter);
+}
diff --git a/include/cmark/iterator.h b/include/cmark/iterator.h
new file mode 100644
index 0000000..fc745df
--- /dev/null
+++ b/include/cmark/iterator.h
@@ -0,0 +1,27 @@
+#ifndef CMARK_ITERATOR_H
+#define CMARK_ITERATOR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "cmark.h"
+#include "memory.h"
+
+typedef struct {
+ cmark_event_type ev_type;
+ cmark_node *node;
+} cmark_iter_state;
+
+struct cmark_iter {
+ cmark_mem *mem;
+ cmark_node *root;
+ cmark_iter_state cur;
+ cmark_iter_state next;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cmark/latex.c b/include/cmark/latex.c
new file mode 100644
index 0000000..0d9517d
--- /dev/null
+++ b/include/cmark/latex.c
@@ -0,0 +1,453 @@
+#include
+#include
+#include
+#include
+
+#include "config.h"
+#include "cmark.h"
+#include "node.h"
+#include "buffer.h"
+#include "utf8.h"
+#include "scanners.h"
+#include "render.h"
+
+#define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping)
+#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 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);
+ return;
+ }
+
+ switch (c) {
+ case 123: // '{'
+ case 125: // '}'
+ case 35: // '#'
+ case 37: // '%'
+ case 38: // '&'
+ cmark_render_ascii(renderer, "\\");
+ cmark_render_code_point(renderer, c);
+ break;
+ case 36: // '$'
+ case 95: // '_'
+ if (escape == NORMAL) {
+ cmark_render_ascii(renderer, "\\");
+ }
+ cmark_render_code_point(renderer, c);
+ break;
+ case 45: // '-'
+ if (nextc == 45) { // prevent ligature
+ cmark_render_ascii(renderer, "-{}");
+ } else {
+ cmark_render_ascii(renderer, "-");
+ }
+ break;
+ case 126: // '~'
+ if (escape == NORMAL) {
+ cmark_render_ascii(renderer, "\\textasciitilde{}");
+ } else {
+ cmark_render_code_point(renderer, c);
+ }
+ break;
+ case 94: // '^'
+ cmark_render_ascii(renderer, "\\^{}");
+ break;
+ case 92: // '\\'
+ if (escape == URL) {
+ // / acts as path sep even on windows:
+ cmark_render_ascii(renderer, "/");
+ } else {
+ cmark_render_ascii(renderer, "\\textbackslash{}");
+ }
+ break;
+ case 124: // '|'
+ cmark_render_ascii(renderer, "\\textbar{}");
+ break;
+ case 60: // '<'
+ cmark_render_ascii(renderer, "\\textless{}");
+ break;
+ case 62: // '>'
+ cmark_render_ascii(renderer, "\\textgreater{}");
+ break;
+ case 91: // '['
+ case 93: // ']'
+ cmark_render_ascii(renderer, "{");
+ cmark_render_code_point(renderer, c);
+ cmark_render_ascii(renderer, "}");
+ break;
+ case 34: // '"'
+ cmark_render_ascii(renderer, "\\textquotedbl{}");
+ // requires \usepackage[T1]{fontenc}
+ break;
+ case 39: // '\''
+ cmark_render_ascii(renderer, "\\textquotesingle{}");
+ // requires \usepackage{textcomp}
+ break;
+ case 160: // nbsp
+ cmark_render_ascii(renderer, "~");
+ break;
+ case 8230: // hellip
+ cmark_render_ascii(renderer, "\\ldots{}");
+ break;
+ case 8216: // lsquo
+ if (escape == NORMAL) {
+ cmark_render_ascii(renderer, "`");
+ } else {
+ cmark_render_code_point(renderer, c);
+ }
+ break;
+ case 8217: // rsquo
+ if (escape == NORMAL) {
+ cmark_render_ascii(renderer, "\'");
+ } else {
+ cmark_render_code_point(renderer, c);
+ }
+ break;
+ case 8220: // ldquo
+ if (escape == NORMAL) {
+ cmark_render_ascii(renderer, "``");
+ } else {
+ cmark_render_code_point(renderer, c);
+ }
+ break;
+ case 8221: // rdquo
+ if (escape == NORMAL) {
+ cmark_render_ascii(renderer, "''");
+ } else {
+ cmark_render_code_point(renderer, c);
+ }
+ break;
+ case 8212: // emdash
+ if (escape == NORMAL) {
+ cmark_render_ascii(renderer, "---");
+ } else {
+ cmark_render_code_point(renderer, c);
+ }
+ break;
+ case 8211: // endash
+ if (escape == NORMAL) {
+ cmark_render_ascii(renderer, "--");
+ } else {
+ cmark_render_code_point(renderer, c);
+ }
+ break;
+ default:
+ cmark_render_code_point(renderer, c);
+ }
+}
+
+typedef enum {
+ NO_LINK,
+ URL_AUTOLINK,
+ EMAIL_AUTOLINK,
+ NORMAL_LINK,
+ INTERNAL_LINK
+} link_type;
+
+static link_type get_link_type(cmark_node *node) {
+ size_t title_len, url_len;
+ cmark_node *link_text;
+ char *realurl;
+ int realurllen;
+ bool isemail = false;
+
+ if (node->type != CMARK_NODE_LINK) {
+ return NO_LINK;
+ }
+
+ const char *url = cmark_node_get_url(node);
+ cmark_chunk url_chunk = cmark_chunk_literal(url);
+
+ if (url && *url == '#') {
+ return INTERNAL_LINK;
+ }
+
+ url_len = strlen(url);
+ if (url_len == 0 || scan_scheme(&url_chunk, 0) == 0) {
+ return NO_LINK;
+ }
+
+ const char *title = cmark_node_get_title(node);
+ title_len = strlen(title);
+ // if it has a title, we can't treat it as an autolink:
+ if (title_len == 0) {
+
+ link_text = node->first_child;
+ cmark_consolidate_text_nodes(link_text);
+
+ if (!link_text)
+ return NO_LINK;
+
+ realurl = (char *)url;
+ realurllen = (int)url_len;
+ if (strncmp(realurl, "mailto:", 7) == 0) {
+ realurl += 7;
+ realurllen -= 7;
+ isemail = true;
+ }
+ if (realurllen == link_text->as.literal.len &&
+ strncmp(realurl, (char *)link_text->as.literal.data,
+ link_text->as.literal.len) == 0) {
+ if (isemail) {
+ return EMAIL_AUTOLINK;
+ } else {
+ return URL_AUTOLINK;
+ }
+ }
+ }
+
+ return NORMAL_LINK;
+}
+
+static int S_get_enumlevel(cmark_node *node) {
+ int enumlevel = 0;
+ cmark_node *tmp = node;
+ while (tmp) {
+ if (tmp->type == CMARK_NODE_LIST &&
+ cmark_node_get_list_type(node) == CMARK_ORDERED_LIST) {
+ enumlevel++;
+ }
+ tmp = tmp->parent;
+ }
+ return enumlevel;
+}
+
+static int S_render_node(cmark_renderer *renderer, cmark_node *node,
+ cmark_event_type ev_type, int options) {
+ int list_number;
+ int enumlevel;
+ char list_number_string[LIST_NUMBER_STRING_SIZE];
+ bool entering = (ev_type == CMARK_EVENT_ENTER);
+ cmark_list_type list_type;
+ bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);
+
+ // avoid warning about unused parameter:
+ (void)(options);
+
+ switch (node->type) {
+ case CMARK_NODE_DOCUMENT:
+ break;
+
+ case CMARK_NODE_BLOCK_QUOTE:
+ if (entering) {
+ LIT("\\begin{quote}");
+ CR();
+ } else {
+ LIT("\\end{quote}");
+ BLANKLINE();
+ }
+ break;
+
+ case CMARK_NODE_LIST:
+ list_type = cmark_node_get_list_type(node);
+ if (entering) {
+ LIT("\\begin{");
+ LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize");
+ LIT("}");
+ CR();
+ list_number = cmark_node_get_list_start(node);
+ if (list_number > 1) {
+ enumlevel = S_get_enumlevel(node);
+ // latex normally supports only five levels
+ if (enumlevel >= 1 && enumlevel <= 5) {
+ snprintf(list_number_string, LIST_NUMBER_STRING_SIZE, "%d",
+ list_number);
+ LIT("\\setcounter{enum");
+ switch (enumlevel) {
+ case 1: LIT("i"); break;
+ case 2: LIT("ii"); break;
+ case 3: LIT("iii"); break;
+ case 4: LIT("iv"); break;
+ case 5: LIT("v"); break;
+ default: LIT("i"); break;
+ }
+ LIT("}{");
+ OUT(list_number_string, false, NORMAL);
+ LIT("}");
+ }
+ CR();
+ }
+ } else {
+ LIT("\\end{");
+ LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize");
+ LIT("}");
+ BLANKLINE();
+ }
+ break;
+
+ case CMARK_NODE_ITEM:
+ if (entering) {
+ LIT("\\item ");
+ } else {
+ CR();
+ }
+ break;
+
+ case CMARK_NODE_HEADING:
+ if (entering) {
+ switch (cmark_node_get_heading_level(node)) {
+ case 1:
+ LIT("\\section");
+ break;
+ case 2:
+ LIT("\\subsection");
+ break;
+ case 3:
+ LIT("\\subsubsection");
+ break;
+ case 4:
+ LIT("\\paragraph");
+ break;
+ case 5:
+ LIT("\\subparagraph");
+ break;
+ }
+ LIT("{");
+ } else {
+ LIT("}");
+ BLANKLINE();
+ }
+ break;
+
+ case CMARK_NODE_CODE_BLOCK:
+ CR();
+ LIT("\\begin{verbatim}");
+ CR();
+ OUT(cmark_node_get_literal(node), false, LITERAL);
+ CR();
+ LIT("\\end{verbatim}");
+ BLANKLINE();
+ break;
+
+ case CMARK_NODE_HTML_BLOCK:
+ break;
+
+ case CMARK_NODE_CUSTOM_BLOCK:
+ CR();
+ OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
+ false, LITERAL);
+ CR();
+ break;
+
+ case CMARK_NODE_THEMATIC_BREAK:
+ BLANKLINE();
+ LIT("\\begin{center}\\rule{0.5\\linewidth}{\\linethickness}\\end{center}");
+ BLANKLINE();
+ break;
+
+ case CMARK_NODE_PARAGRAPH:
+ if (!entering) {
+ BLANKLINE();
+ }
+ break;
+
+ case CMARK_NODE_TEXT:
+ OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
+ break;
+
+ case CMARK_NODE_LINEBREAK:
+ LIT("\\\\");
+ CR();
+ break;
+
+ case CMARK_NODE_SOFTBREAK:
+ if (options & CMARK_OPT_HARDBREAKS) {
+ LIT("\\\\");
+ CR();
+ } else if (renderer->width == 0 && !(CMARK_OPT_NOBREAKS & options)) {
+ CR();
+ } else {
+ OUT(" ", allow_wrap, NORMAL);
+ }
+ break;
+
+ case CMARK_NODE_CODE:
+ LIT("\\texttt{");
+ OUT(cmark_node_get_literal(node), false, NORMAL);
+ LIT("}");
+ break;
+
+ case CMARK_NODE_HTML_INLINE:
+ break;
+
+ case CMARK_NODE_CUSTOM_INLINE:
+ OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
+ false, LITERAL);
+ break;
+
+ case CMARK_NODE_STRONG:
+ if (entering) {
+ LIT("\\textbf{");
+ } else {
+ LIT("}");
+ }
+ break;
+
+ case CMARK_NODE_EMPH:
+ if (entering) {
+ LIT("\\emph{");
+ } else {
+ LIT("}");
+ }
+ break;
+
+ case CMARK_NODE_LINK:
+ if (entering) {
+ const char *url = cmark_node_get_url(node);
+ // requires \usepackage{hyperref}
+ switch (get_link_type(node)) {
+ case URL_AUTOLINK:
+ LIT("\\url{");
+ OUT(url, false, URL);
+ LIT("}");
+ return 0; // Don't process further nodes to avoid double-rendering artefacts
+ case EMAIL_AUTOLINK:
+ LIT("\\href{");
+ OUT(url, false, URL);
+ LIT("}\\nolinkurl{");
+ break;
+ case NORMAL_LINK:
+ LIT("\\href{");
+ OUT(url, false, URL);
+ LIT("}{");
+ break;
+ case INTERNAL_LINK:
+ LIT("\\protect\\hyperlink{");
+ OUT(url + 1, false, URL);
+ LIT("}{");
+ break;
+ case NO_LINK:
+ LIT("{"); // error?
+ }
+ } else {
+ LIT("}");
+ }
+
+ break;
+
+ case CMARK_NODE_IMAGE:
+ if (entering) {
+ LIT("\\protect\\includegraphics{");
+ // requires \include{graphicx}
+ OUT(cmark_node_get_url(node), false, URL);
+ LIT("}");
+ return 0;
+ }
+ break;
+
+ default:
+ assert(false);
+ break;
+ }
+
+ return 1;
+}
+
+char *cmark_render_latex(cmark_node *root, int options, int width) {
+ return cmark_render(root, options, width, outc, S_render_node);
+}
diff --git a/include/cmark/main.c b/include/cmark/main.c
new file mode 100644
index 0000000..1094fee
--- /dev/null
+++ b/include/cmark/main.c
@@ -0,0 +1,211 @@
+#include
+#include
+#include
+#include
+#include "config.h"
+#include "memory.h"
+#include "cmark.h"
+#include "node.h"
+
+#if defined(__OpenBSD__)
+# include
+# if OpenBSD >= 201605
+# define USE_PLEDGE
+# include
+# endif
+#endif
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include
+#include
+#endif
+
+typedef enum {
+ FORMAT_NONE,
+ FORMAT_HTML,
+ FORMAT_XML,
+ FORMAT_MAN,
+ FORMAT_COMMONMARK,
+ FORMAT_LATEX
+} writer_format;
+
+void print_usage() {
+ printf("Usage: cmark [FILE*]\n");
+ printf("Options:\n");
+ printf(" --to, -t FORMAT Specify output format (html, xml, man, "
+ "commonmark, latex)\n");
+ printf(" --width WIDTH Specify wrap width (default 0 = nowrap)\n");
+ printf(" --sourcepos Include source position attribute\n");
+ printf(" --hardbreaks Treat newlines as hard line breaks\n");
+ printf(" --nobreaks Render soft line breaks as spaces\n");
+ printf(" --safe Suppress raw HTML and dangerous URLs\n");
+ printf(" --smart Use smart punctuation\n");
+ printf(" --validate-utf8 Replace UTF-8 invalid sequences with U+FFFD\n");
+ printf(" --help, -h Print usage information\n");
+ printf(" --version Print version\n");
+}
+
+static void print_document(cmark_node *document, writer_format writer,
+ int options, int width) {
+ char *result;
+
+ switch (writer) {
+ case FORMAT_HTML:
+ result = cmark_render_html(document, options);
+ break;
+ case FORMAT_XML:
+ result = cmark_render_xml(document, options);
+ break;
+ case FORMAT_MAN:
+ result = cmark_render_man(document, options, width);
+ break;
+ case FORMAT_COMMONMARK:
+ result = cmark_render_commonmark(document, options, width);
+ break;
+ case FORMAT_LATEX:
+ result = cmark_render_latex(document, options, width);
+ break;
+ default:
+ fprintf(stderr, "Unknown format %d\n", writer);
+ exit(1);
+ }
+ printf("%s", result);
+ cmark_node_mem(document)->free(result);
+}
+
+int main(int argc, char *argv[]) {
+ int i, numfps = 0;
+ int *files;
+ char buffer[4096];
+ cmark_parser *parser;
+ size_t bytes;
+ cmark_node *document;
+ int width = 0;
+ char *unparsed;
+ writer_format writer = FORMAT_HTML;
+ int options = CMARK_OPT_DEFAULT;
+
+#ifdef USE_PLEDGE
+ if (pledge("stdio rpath", NULL) != 0) {
+ perror("pledge");
+ return 1;
+ }
+#endif
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ _setmode(_fileno(stdin), _O_BINARY);
+ _setmode(_fileno(stdout), _O_BINARY);
+#endif
+
+ files = (int *)calloc(argc, sizeof(*files));
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "--version") == 0) {
+ printf("cmark %s", CMARK_VERSION_STRING);
+ printf(" - CommonMark converter\n(C) 2014-2016 John MacFarlane\n");
+ exit(0);
+ } else if (strcmp(argv[i], "--sourcepos") == 0) {
+ options |= CMARK_OPT_SOURCEPOS;
+ } else if (strcmp(argv[i], "--hardbreaks") == 0) {
+ options |= CMARK_OPT_HARDBREAKS;
+ } else if (strcmp(argv[i], "--nobreaks") == 0) {
+ options |= CMARK_OPT_NOBREAKS;
+ } else if (strcmp(argv[i], "--smart") == 0) {
+ options |= CMARK_OPT_SMART;
+ } else if (strcmp(argv[i], "--safe") == 0) {
+ options |= CMARK_OPT_SAFE;
+ } else if (strcmp(argv[i], "--validate-utf8") == 0) {
+ options |= CMARK_OPT_VALIDATE_UTF8;
+ } else if ((strcmp(argv[i], "--help") == 0) ||
+ (strcmp(argv[i], "-h") == 0)) {
+ print_usage();
+ exit(0);
+ } else if (strcmp(argv[i], "--width") == 0) {
+ i += 1;
+ if (i < argc) {
+ width = (int)strtol(argv[i], &unparsed, 10);
+ if (unparsed && strlen(unparsed) > 0) {
+ fprintf(stderr, "failed parsing width '%s' at '%s'\n", argv[i],
+ unparsed);
+ exit(1);
+ }
+ } else {
+ fprintf(stderr, "--width requires an argument\n");
+ exit(1);
+ }
+ } else if ((strcmp(argv[i], "-t") == 0) || (strcmp(argv[i], "--to") == 0)) {
+ i += 1;
+ if (i < argc) {
+ if (strcmp(argv[i], "man") == 0) {
+ writer = FORMAT_MAN;
+ } else if (strcmp(argv[i], "html") == 0) {
+ writer = FORMAT_HTML;
+ } else if (strcmp(argv[i], "xml") == 0) {
+ writer = FORMAT_XML;
+ } else if (strcmp(argv[i], "commonmark") == 0) {
+ writer = FORMAT_COMMONMARK;
+ } else if (strcmp(argv[i], "latex") == 0) {
+ writer = FORMAT_LATEX;
+ } else {
+ fprintf(stderr, "Unknown format %s\n", argv[i]);
+ exit(1);
+ }
+ } else {
+ fprintf(stderr, "No argument provided for %s\n", argv[i - 1]);
+ exit(1);
+ }
+ } else if (*argv[i] == '-') {
+ print_usage();
+ exit(1);
+ } else { // treat as file argument
+ files[numfps++] = i;
+ }
+ }
+
+ parser = cmark_parser_new(options);
+ for (i = 0; i < numfps; i++) {
+ FILE *fp = fopen(argv[files[i]], "rb");
+ if (fp == NULL) {
+ fprintf(stderr, "Error opening file %s: %s\n", argv[files[i]],
+ strerror(errno));
+ exit(1);
+ }
+
+ while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
+ cmark_parser_feed(parser, buffer, bytes);
+ if (bytes < sizeof(buffer)) {
+ break;
+ }
+ }
+
+ fclose(fp);
+ }
+
+ if (numfps == 0) {
+
+ while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) {
+ cmark_parser_feed(parser, buffer, bytes);
+ if (bytes < sizeof(buffer)) {
+ break;
+ }
+ }
+ }
+
+#ifdef USE_PLEDGE
+ if (pledge("stdio", NULL) != 0) {
+ perror("pledge");
+ return 1;
+ }
+#endif
+
+ document = cmark_parser_finish(parser);
+ cmark_parser_free(parser);
+
+ print_document(document, writer, options, width);
+
+ cmark_node_free(document);
+
+ free(files);
+
+ return 0;
+}
diff --git a/include/cmark/man.c b/include/cmark/man.c
new file mode 100644
index 0000000..1c76f68
--- /dev/null
+++ b/include/cmark/man.c
@@ -0,0 +1,252 @@
+#include
+#include
+#include
+#include
+
+#include "config.h"
+#include "cmark.h"
+#include "node.h"
+#include "buffer.h"
+#include "utf8.h"
+#include "render.h"
+
+#define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping)
+#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,
+ unsigned char nextc) {
+ (void)(nextc);
+
+ if (escape == LITERAL) {
+ cmark_render_code_point(renderer, c);
+ return;
+ }
+
+ switch (c) {
+ case 46:
+ if (renderer->begin_line) {
+ cmark_render_ascii(renderer, "\\&.");
+ } else {
+ cmark_render_code_point(renderer, c);
+ }
+ break;
+ case 39:
+ if (renderer->begin_line) {
+ cmark_render_ascii(renderer, "\\&'");
+ } else {
+ cmark_render_code_point(renderer, c);
+ }
+ break;
+ case 45:
+ cmark_render_ascii(renderer, "\\-");
+ break;
+ case 92:
+ cmark_render_ascii(renderer, "\\e");
+ break;
+ case 8216: // left single quote
+ cmark_render_ascii(renderer, "\\[oq]");
+ break;
+ case 8217: // right single quote
+ cmark_render_ascii(renderer, "\\[cq]");
+ break;
+ case 8220: // left double quote
+ cmark_render_ascii(renderer, "\\[lq]");
+ break;
+ case 8221: // right double quote
+ cmark_render_ascii(renderer, "\\[rq]");
+ break;
+ case 8212: // em dash
+ cmark_render_ascii(renderer, "\\[em]");
+ break;
+ case 8211: // en dash
+ cmark_render_ascii(renderer, "\\[en]");
+ break;
+ default:
+ cmark_render_code_point(renderer, c);
+ }
+}
+
+static int S_render_node(cmark_renderer *renderer, cmark_node *node,
+ cmark_event_type ev_type, int options) {
+ cmark_node *tmp;
+ int list_number;
+ bool entering = (ev_type == CMARK_EVENT_ENTER);
+ bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);
+
+ // avoid unused parameter error:
+ (void)(options);
+
+ switch (node->type) {
+ case CMARK_NODE_DOCUMENT:
+ break;
+
+ case CMARK_NODE_BLOCK_QUOTE:
+ if (entering) {
+ CR();
+ LIT(".RS");
+ CR();
+ } else {
+ CR();
+ LIT(".RE");
+ CR();
+ }
+ break;
+
+ case CMARK_NODE_LIST:
+ break;
+
+ case CMARK_NODE_ITEM:
+ if (entering) {
+ CR();
+ LIT(".IP ");
+ if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
+ LIT("\\[bu] 2");
+ } else {
+ list_number = cmark_node_get_list_start(node->parent);
+ tmp = node;
+ while (tmp->prev) {
+ tmp = tmp->prev;
+ list_number += 1;
+ }
+ char list_number_s[LIST_NUMBER_SIZE];
+ snprintf(list_number_s, LIST_NUMBER_SIZE, "\"%d.\" 4", list_number);
+ LIT(list_number_s);
+ }
+ CR();
+ } else {
+ CR();
+ }
+ break;
+
+ case CMARK_NODE_HEADING:
+ if (entering) {
+ CR();
+ LIT(cmark_node_get_heading_level(node) == 1 ? ".SH" : ".SS");
+ CR();
+ } else {
+ CR();
+ }
+ break;
+
+ case CMARK_NODE_CODE_BLOCK:
+ CR();
+ LIT(".IP\n.nf\n\\f[C]\n");
+ OUT(cmark_node_get_literal(node), false, NORMAL);
+ CR();
+ LIT("\\f[]\n.fi");
+ CR();
+ break;
+
+ case CMARK_NODE_HTML_BLOCK:
+ break;
+
+ case CMARK_NODE_CUSTOM_BLOCK:
+ CR();
+ OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
+ false, LITERAL);
+ CR();
+ break;
+
+ case CMARK_NODE_THEMATIC_BREAK:
+ CR();
+ LIT(".PP\n * * * * *");
+ CR();
+ break;
+
+ case CMARK_NODE_PARAGRAPH:
+ if (entering) {
+ // no blank line if first paragraph in list:
+ if (node->parent && node->parent->type == CMARK_NODE_ITEM &&
+ node->prev == NULL) {
+ // no blank line or .PP
+ } else {
+ CR();
+ LIT(".PP");
+ CR();
+ }
+ } else {
+ CR();
+ }
+ break;
+
+ case CMARK_NODE_TEXT:
+ OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
+ break;
+
+ case CMARK_NODE_LINEBREAK:
+ LIT(".PD 0\n.P\n.PD");
+ CR();
+ break;
+
+ case CMARK_NODE_SOFTBREAK:
+ if (options & CMARK_OPT_HARDBREAKS) {
+ LIT(".PD 0\n.P\n.PD");
+ CR();
+ } else if (renderer->width == 0 && !(CMARK_OPT_NOBREAKS & options)) {
+ CR();
+ } else {
+ OUT(" ", allow_wrap, LITERAL);
+ }
+ break;
+
+ case CMARK_NODE_CODE:
+ LIT("\\f[C]");
+ OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
+ LIT("\\f[]");
+ break;
+
+ case CMARK_NODE_HTML_INLINE:
+ break;
+
+ case CMARK_NODE_CUSTOM_INLINE:
+ OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
+ false, LITERAL);
+ break;
+
+ case CMARK_NODE_STRONG:
+ if (entering) {
+ LIT("\\f[B]");
+ } else {
+ LIT("\\f[]");
+ }
+ break;
+
+ case CMARK_NODE_EMPH:
+ if (entering) {
+ LIT("\\f[I]");
+ } else {
+ LIT("\\f[]");
+ }
+ break;
+
+ case CMARK_NODE_LINK:
+ if (!entering) {
+ LIT(" (");
+ OUT(cmark_node_get_url(node), allow_wrap, URL);
+ LIT(")");
+ }
+ break;
+
+ case CMARK_NODE_IMAGE:
+ if (entering) {
+ LIT("[IMAGE: ");
+ } else {
+ LIT("]");
+ }
+ break;
+
+ default:
+ assert(false);
+ break;
+ }
+
+ return 1;
+}
+
+char *cmark_render_man(cmark_node *root, int options, int width) {
+ return cmark_render(root, options, width, S_outc, S_render_node);
+}
diff --git a/include/cmark/node.c b/include/cmark/node.c
new file mode 100644
index 0000000..c6c2902
--- /dev/null
+++ b/include/cmark/node.c
@@ -0,0 +1,858 @@
+#include
+#include
+
+#include "config.h"
+#include "node.h"
+
+static void S_node_unlink(cmark_node *node);
+
+#define NODE_MEM(node) cmark_node_mem(node)
+
+static CMARK_INLINE bool S_is_block(cmark_node *node) {
+ if (node == NULL) {
+ return false;
+ }
+ return node->type >= CMARK_NODE_FIRST_BLOCK &&
+ node->type <= CMARK_NODE_LAST_BLOCK;
+}
+
+static CMARK_INLINE bool S_is_inline(cmark_node *node) {
+ if (node == NULL) {
+ return false;
+ }
+ return node->type >= CMARK_NODE_FIRST_INLINE &&
+ node->type <= CMARK_NODE_LAST_INLINE;
+}
+
+static bool S_can_contain(cmark_node *node, cmark_node *child) {
+ cmark_node *cur;
+
+ if (node == NULL || child == NULL) {
+ return false;
+ }
+
+ // Verify that child is not an ancestor of node or equal to node.
+ cur = node;
+ do {
+ if (cur == child) {
+ return false;
+ }
+ cur = cur->parent;
+ } while (cur != NULL);
+
+ if (child->type == CMARK_NODE_DOCUMENT) {
+ return false;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_DOCUMENT:
+ case CMARK_NODE_BLOCK_QUOTE:
+ case CMARK_NODE_ITEM:
+ return S_is_block(child) && child->type != CMARK_NODE_ITEM;
+
+ case CMARK_NODE_LIST:
+ return child->type == CMARK_NODE_ITEM;
+
+ case CMARK_NODE_CUSTOM_BLOCK:
+ return true;
+
+ case CMARK_NODE_PARAGRAPH:
+ case CMARK_NODE_HEADING:
+ case CMARK_NODE_EMPH:
+ case CMARK_NODE_STRONG:
+ case CMARK_NODE_LINK:
+ case CMARK_NODE_IMAGE:
+ case CMARK_NODE_CUSTOM_INLINE:
+ return S_is_inline(child);
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+cmark_node *cmark_node_new_with_mem(cmark_node_type type, cmark_mem *mem) {
+ cmark_node *node = (cmark_node *)mem->calloc(1, sizeof(*node));
+ cmark_strbuf_init(mem, &node->content, 0);
+ node->type = (uint16_t)type;
+
+ switch (node->type) {
+ case CMARK_NODE_HEADING:
+ node->as.heading.level = 1;
+ break;
+
+ case CMARK_NODE_LIST: {
+ cmark_list *list = &node->as.list;
+ list->list_type = CMARK_BULLET_LIST;
+ list->start = 0;
+ list->tight = false;
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return node;
+}
+
+cmark_node *cmark_node_new(cmark_node_type type) {
+ extern cmark_mem DEFAULT_MEM_ALLOCATOR;
+ return cmark_node_new_with_mem(type, &DEFAULT_MEM_ALLOCATOR);
+}
+
+// Free a cmark_node list and any children.
+static void S_free_nodes(cmark_node *e) {
+ cmark_node *next;
+ while (e != NULL) {
+ cmark_strbuf_free(&e->content);
+ switch (e->type) {
+ case CMARK_NODE_CODE_BLOCK:
+ cmark_chunk_free(NODE_MEM(e), &e->as.code.info);
+ cmark_chunk_free(NODE_MEM(e), &e->as.code.literal);
+ break;
+ case CMARK_NODE_TEXT:
+ case CMARK_NODE_HTML_INLINE:
+ case CMARK_NODE_CODE:
+ case CMARK_NODE_HTML_BLOCK:
+ cmark_chunk_free(NODE_MEM(e), &e->as.literal);
+ break;
+ case CMARK_NODE_LINK:
+ case CMARK_NODE_IMAGE:
+ cmark_chunk_free(NODE_MEM(e), &e->as.link.url);
+ cmark_chunk_free(NODE_MEM(e), &e->as.link.title);
+ break;
+ case CMARK_NODE_CUSTOM_BLOCK:
+ case CMARK_NODE_CUSTOM_INLINE:
+ cmark_chunk_free(NODE_MEM(e), &e->as.custom.on_enter);
+ cmark_chunk_free(NODE_MEM(e), &e->as.custom.on_exit);
+ break;
+ default:
+ break;
+ }
+ if (e->last_child) {
+ // Splice children into list
+ e->last_child->next = e->next;
+ e->next = e->first_child;
+ }
+ next = e->next;
+ NODE_MEM(e)->free(e);
+ e = next;
+ }
+}
+
+void cmark_node_free(cmark_node *node) {
+ S_node_unlink(node);
+ node->next = NULL;
+ S_free_nodes(node);
+}
+
+cmark_node_type cmark_node_get_type(cmark_node *node) {
+ if (node == NULL) {
+ return CMARK_NODE_NONE;
+ } else {
+ return (cmark_node_type)node->type;
+ }
+}
+
+const char *cmark_node_get_type_string(cmark_node *node) {
+ if (node == NULL) {
+ return "NONE";
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_NONE:
+ return "none";
+ case CMARK_NODE_DOCUMENT:
+ return "document";
+ case CMARK_NODE_BLOCK_QUOTE:
+ return "block_quote";
+ case CMARK_NODE_LIST:
+ return "list";
+ case CMARK_NODE_ITEM:
+ return "item";
+ case CMARK_NODE_CODE_BLOCK:
+ return "code_block";
+ case CMARK_NODE_HTML_BLOCK:
+ return "html_block";
+ case CMARK_NODE_CUSTOM_BLOCK:
+ return "custom_block";
+ case CMARK_NODE_PARAGRAPH:
+ return "paragraph";
+ case CMARK_NODE_HEADING:
+ return "heading";
+ case CMARK_NODE_THEMATIC_BREAK:
+ return "thematic_break";
+ case CMARK_NODE_TEXT:
+ return "text";
+ case CMARK_NODE_SOFTBREAK:
+ return "softbreak";
+ case CMARK_NODE_LINEBREAK:
+ return "linebreak";
+ case CMARK_NODE_CODE:
+ return "code";
+ case CMARK_NODE_HTML_INLINE:
+ return "html_inline";
+ case CMARK_NODE_CUSTOM_INLINE:
+ return "custom_inline";
+ case CMARK_NODE_EMPH:
+ return "emph";
+ case CMARK_NODE_STRONG:
+ return "strong";
+ case CMARK_NODE_LINK:
+ return "link";
+ case CMARK_NODE_IMAGE:
+ return "image";
+ }
+
+ return "";
+}
+
+cmark_node *cmark_node_next(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ } else {
+ return node->next;
+ }
+}
+
+cmark_node *cmark_node_previous(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ } else {
+ return node->prev;
+ }
+}
+
+cmark_node *cmark_node_parent(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ } else {
+ return node->parent;
+ }
+}
+
+cmark_node *cmark_node_first_child(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ } else {
+ return node->first_child;
+ }
+}
+
+cmark_node *cmark_node_last_child(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ } else {
+ return node->last_child;
+ }
+}
+
+void *cmark_node_get_user_data(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ } else {
+ return node->user_data;
+ }
+}
+
+int cmark_node_set_user_data(cmark_node *node, void *user_data) {
+ if (node == NULL) {
+ return 0;
+ }
+ node->user_data = user_data;
+ return 1;
+}
+
+const char *cmark_node_get_literal(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_HTML_BLOCK:
+ case CMARK_NODE_TEXT:
+ case CMARK_NODE_HTML_INLINE:
+ case CMARK_NODE_CODE:
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.literal);
+
+ case CMARK_NODE_CODE_BLOCK:
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.code.literal);
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+int cmark_node_set_literal(cmark_node *node, const char *content) {
+ if (node == NULL) {
+ return 0;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_HTML_BLOCK:
+ case CMARK_NODE_TEXT:
+ case CMARK_NODE_HTML_INLINE:
+ case CMARK_NODE_CODE:
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.literal, content);
+ return 1;
+
+ case CMARK_NODE_CODE_BLOCK:
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.code.literal, content);
+ return 1;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int cmark_node_get_heading_level(cmark_node *node) {
+ if (node == NULL) {
+ return 0;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_HEADING:
+ return node->as.heading.level;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int cmark_node_set_heading_level(cmark_node *node, int level) {
+ if (node == NULL || level < 1 || level > 6) {
+ return 0;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_HEADING:
+ node->as.heading.level = level;
+ return 1;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+cmark_list_type cmark_node_get_list_type(cmark_node *node) {
+ if (node == NULL) {
+ return CMARK_NO_LIST;
+ }
+
+ if (node->type == CMARK_NODE_LIST) {
+ return node->as.list.list_type;
+ } else {
+ return CMARK_NO_LIST;
+ }
+}
+
+int cmark_node_set_list_type(cmark_node *node, cmark_list_type type) {
+ if (!(type == CMARK_BULLET_LIST || type == CMARK_ORDERED_LIST)) {
+ return 0;
+ }
+
+ if (node == NULL) {
+ return 0;
+ }
+
+ if (node->type == CMARK_NODE_LIST) {
+ node->as.list.list_type = type;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+cmark_delim_type cmark_node_get_list_delim(cmark_node *node) {
+ if (node == NULL) {
+ return CMARK_NO_DELIM;
+ }
+
+ if (node->type == CMARK_NODE_LIST) {
+ return node->as.list.delimiter;
+ } else {
+ return CMARK_NO_DELIM;
+ }
+}
+
+int cmark_node_set_list_delim(cmark_node *node, cmark_delim_type delim) {
+ if (!(delim == CMARK_PERIOD_DELIM || delim == CMARK_PAREN_DELIM)) {
+ return 0;
+ }
+
+ if (node == NULL) {
+ return 0;
+ }
+
+ if (node->type == CMARK_NODE_LIST) {
+ node->as.list.delimiter = delim;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int cmark_node_get_list_start(cmark_node *node) {
+ if (node == NULL) {
+ return 0;
+ }
+
+ if (node->type == CMARK_NODE_LIST) {
+ return node->as.list.start;
+ } else {
+ return 0;
+ }
+}
+
+int cmark_node_set_list_start(cmark_node *node, int start) {
+ if (node == NULL || start < 0) {
+ return 0;
+ }
+
+ if (node->type == CMARK_NODE_LIST) {
+ node->as.list.start = start;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int cmark_node_get_list_tight(cmark_node *node) {
+ if (node == NULL) {
+ return 0;
+ }
+
+ if (node->type == CMARK_NODE_LIST) {
+ return node->as.list.tight;
+ } else {
+ return 0;
+ }
+}
+
+int cmark_node_set_list_tight(cmark_node *node, int tight) {
+ if (node == NULL) {
+ return 0;
+ }
+
+ if (node->type == CMARK_NODE_LIST) {
+ node->as.list.tight = tight == 1;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+const char *cmark_node_get_fence_info(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ }
+
+ if (node->type == CMARK_NODE_CODE_BLOCK) {
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.code.info);
+ } else {
+ return NULL;
+ }
+}
+
+int cmark_node_set_fence_info(cmark_node *node, const char *info) {
+ if (node == NULL) {
+ return 0;
+ }
+
+ if (node->type == CMARK_NODE_CODE_BLOCK) {
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.code.info, info);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+const char *cmark_node_get_url(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_LINK:
+ case CMARK_NODE_IMAGE:
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.link.url);
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+int cmark_node_set_url(cmark_node *node, const char *url) {
+ if (node == NULL) {
+ return 0;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_LINK:
+ case CMARK_NODE_IMAGE:
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.link.url, url);
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+const char *cmark_node_get_title(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_LINK:
+ case CMARK_NODE_IMAGE:
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.link.title);
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+int cmark_node_set_title(cmark_node *node, const char *title) {
+ if (node == NULL) {
+ return 0;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_LINK:
+ case CMARK_NODE_IMAGE:
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.link.title, title);
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+const char *cmark_node_get_on_enter(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_CUSTOM_INLINE:
+ case CMARK_NODE_CUSTOM_BLOCK:
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.custom.on_enter);
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+int cmark_node_set_on_enter(cmark_node *node, const char *on_enter) {
+ if (node == NULL) {
+ return 0;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_CUSTOM_INLINE:
+ case CMARK_NODE_CUSTOM_BLOCK:
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.custom.on_enter, on_enter);
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+const char *cmark_node_get_on_exit(cmark_node *node) {
+ if (node == NULL) {
+ return NULL;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_CUSTOM_INLINE:
+ case CMARK_NODE_CUSTOM_BLOCK:
+ return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.custom.on_exit);
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+int cmark_node_set_on_exit(cmark_node *node, const char *on_exit) {
+ if (node == NULL) {
+ return 0;
+ }
+
+ switch (node->type) {
+ case CMARK_NODE_CUSTOM_INLINE:
+ case CMARK_NODE_CUSTOM_BLOCK:
+ cmark_chunk_set_cstr(NODE_MEM(node), &node->as.custom.on_exit, on_exit);
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int cmark_node_get_start_line(cmark_node *node) {
+ if (node == NULL) {
+ return 0;
+ }
+ return node->start_line;
+}
+
+int cmark_node_get_start_column(cmark_node *node) {
+ if (node == NULL) {
+ return 0;
+ }
+ return node->start_column;
+}
+
+int cmark_node_get_end_line(cmark_node *node) {
+ if (node == NULL) {
+ return 0;
+ }
+ return node->end_line;
+}
+
+int cmark_node_get_end_column(cmark_node *node) {
+ if (node == NULL) {
+ return 0;
+ }
+ return node->end_column;
+}
+
+// Unlink a node without adjusting its next, prev, and parent pointers.
+static void S_node_unlink(cmark_node *node) {
+ if (node == NULL) {
+ return;
+ }
+
+ if (node->prev) {
+ node->prev->next = node->next;
+ }
+ if (node->next) {
+ node->next->prev = node->prev;
+ }
+
+ // Adjust first_child and last_child of parent.
+ cmark_node *parent = node->parent;
+ if (parent) {
+ if (parent->first_child == node) {
+ parent->first_child = node->next;
+ }
+ if (parent->last_child == node) {
+ parent->last_child = node->prev;
+ }
+ }
+}
+
+void cmark_node_unlink(cmark_node *node) {
+ S_node_unlink(node);
+
+ node->next = NULL;
+ node->prev = NULL;
+ node->parent = NULL;
+}
+
+int cmark_node_insert_before(cmark_node *node, cmark_node *sibling) {
+ if (node == NULL || sibling == NULL) {
+ return 0;
+ }
+
+ if (!node->parent || !S_can_contain(node->parent, sibling)) {
+ return 0;
+ }
+
+ S_node_unlink(sibling);
+
+ cmark_node *old_prev = node->prev;
+
+ // Insert 'sibling' between 'old_prev' and 'node'.
+ if (old_prev) {
+ old_prev->next = sibling;
+ }
+ sibling->prev = old_prev;
+ sibling->next = node;
+ node->prev = sibling;
+
+ // Set new parent.
+ cmark_node *parent = node->parent;
+ sibling->parent = parent;
+
+ // Adjust first_child of parent if inserted as first child.
+ if (parent && !old_prev) {
+ parent->first_child = sibling;
+ }
+
+ return 1;
+}
+
+int cmark_node_insert_after(cmark_node *node, cmark_node *sibling) {
+ if (node == NULL || sibling == NULL) {
+ return 0;
+ }
+
+ if (!node->parent || !S_can_contain(node->parent, sibling)) {
+ return 0;
+ }
+
+ S_node_unlink(sibling);
+
+ cmark_node *old_next = node->next;
+
+ // Insert 'sibling' between 'node' and 'old_next'.
+ if (old_next) {
+ old_next->prev = sibling;
+ }
+ sibling->next = old_next;
+ sibling->prev = node;
+ node->next = sibling;
+
+ // Set new parent.
+ cmark_node *parent = node->parent;
+ sibling->parent = parent;
+
+ // Adjust last_child of parent if inserted as last child.
+ if (parent && !old_next) {
+ parent->last_child = sibling;
+ }
+
+ return 1;
+}
+
+int cmark_node_replace(cmark_node *oldnode, cmark_node *newnode) {
+ if (!cmark_node_insert_before(oldnode, newnode)) {
+ return 0;
+ }
+ cmark_node_unlink(oldnode);
+ return 1;
+}
+
+int cmark_node_prepend_child(cmark_node *node, cmark_node *child) {
+ if (!S_can_contain(node, child)) {
+ return 0;
+ }
+
+ S_node_unlink(child);
+
+ cmark_node *old_first_child = node->first_child;
+
+ child->next = old_first_child;
+ child->prev = NULL;
+ child->parent = node;
+ node->first_child = child;
+
+ if (old_first_child) {
+ old_first_child->prev = child;
+ } else {
+ // Also set last_child if node previously had no children.
+ node->last_child = child;
+ }
+
+ return 1;
+}
+
+int cmark_node_append_child(cmark_node *node, cmark_node *child) {
+ if (!S_can_contain(node, child)) {
+ return 0;
+ }
+
+ S_node_unlink(child);
+
+ cmark_node *old_last_child = node->last_child;
+
+ child->next = NULL;
+ child->prev = old_last_child;
+ child->parent = node;
+ node->last_child = child;
+
+ if (old_last_child) {
+ old_last_child->next = child;
+ } else {
+ // Also set first_child if node previously had no children.
+ node->first_child = child;
+ }
+
+ return 1;
+}
+
+static void S_print_error(FILE *out, cmark_node *node, const char *elem) {
+ if (out == NULL) {
+ return;
+ }
+ fprintf(out, "Invalid '%s' in node type %s at %d:%d\n", elem,
+ cmark_node_get_type_string(node), node->start_line,
+ node->start_column);
+}
+
+int cmark_node_check(cmark_node *node, FILE *out) {
+ cmark_node *cur;
+ int errors = 0;
+
+ if (!node) {
+ return 0;
+ }
+
+ cur = node;
+ for (;;) {
+ if (cur->first_child) {
+ if (cur->first_child->prev != NULL) {
+ S_print_error(out, cur->first_child, "prev");
+ cur->first_child->prev = NULL;
+ ++errors;
+ }
+ if (cur->first_child->parent != cur) {
+ S_print_error(out, cur->first_child, "parent");
+ cur->first_child->parent = cur;
+ ++errors;
+ }
+ cur = cur->first_child;
+ continue;
+ }
+
+ next_sibling:
+ if (cur == node) {
+ break;
+ }
+ if (cur->next) {
+ if (cur->next->prev != cur) {
+ S_print_error(out, cur->next, "prev");
+ cur->next->prev = cur;
+ ++errors;
+ }
+ if (cur->next->parent != cur->parent) {
+ S_print_error(out, cur->next, "parent");
+ cur->next->parent = cur->parent;
+ ++errors;
+ }
+ cur = cur->next;
+ continue;
+ }
+
+ if (cur->parent->last_child != cur) {
+ S_print_error(out, cur->parent, "last_child");
+ cur->parent->last_child = cur;
+ ++errors;
+ }
+ cur = cur->parent;
+ goto next_sibling;
+ }
+
+ return errors;
+}
diff --git a/include/cmark/node.h b/include/cmark/node.h
new file mode 100644
index 0000000..13901ba
--- /dev/null
+++ b/include/cmark/node.h
@@ -0,0 +1,93 @@
+#ifndef CMARK_NODE_H
+#define CMARK_NODE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+
+#include "cmark.h"
+#include "buffer.h"
+#include "chunk.h"
+
+typedef struct {
+ cmark_list_type list_type;
+ int marker_offset;
+ int padding;
+ int start;
+ cmark_delim_type delimiter;
+ unsigned char bullet_char;
+ bool tight;
+} cmark_list;
+
+typedef struct {
+ cmark_chunk info;
+ cmark_chunk literal;
+ uint8_t fence_length;
+ uint8_t fence_offset;
+ unsigned char fence_char;
+ int8_t fenced;
+} cmark_code;
+
+typedef struct {
+ int level;
+ bool setext;
+} cmark_heading;
+
+typedef struct {
+ cmark_chunk url;
+ cmark_chunk title;
+} cmark_link;
+
+typedef struct {
+ cmark_chunk on_enter;
+ cmark_chunk on_exit;
+} cmark_custom;
+
+enum cmark_node__internal_flags {
+ CMARK_NODE__OPEN = (1 << 0),
+ CMARK_NODE__LAST_LINE_BLANK = (1 << 1),
+};
+
+struct cmark_node {
+ cmark_strbuf content;
+
+ struct cmark_node *next;
+ struct cmark_node *prev;
+ struct cmark_node *parent;
+ struct cmark_node *first_child;
+ struct cmark_node *last_child;
+
+ void *user_data;
+
+ int start_line;
+ int start_column;
+ int end_line;
+ int end_column;
+ int internal_offset;
+ uint16_t type;
+ uint16_t flags;
+
+ union {
+ cmark_chunk literal;
+ cmark_list list;
+ cmark_code code;
+ cmark_heading heading;
+ cmark_link link;
+ cmark_custom custom;
+ int html_block_type;
+ } as;
+};
+
+static CMARK_INLINE cmark_mem *cmark_node_mem(cmark_node *node) {
+ return node->content.mem;
+}
+CMARK_EXPORT int cmark_node_check(cmark_node *node, FILE *out);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cmark/parser.h b/include/cmark/parser.h
new file mode 100644
index 0000000..0c5033b
--- /dev/null
+++ b/include/cmark/parser.h
@@ -0,0 +1,39 @@
+#ifndef CMARK_AST_H
+#define CMARK_AST_H
+
+#include
+#include "node.h"
+#include "buffer.h"
+#include "memory.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_LINK_LABEL_LENGTH 1000
+
+struct cmark_parser {
+ struct cmark_mem *mem;
+ struct cmark_reference_map *refmap;
+ struct cmark_node *root;
+ struct cmark_node *current;
+ int line_number;
+ bufsize_t offset;
+ bufsize_t column;
+ bufsize_t first_nonspace;
+ 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
+}
+#endif
+
+#endif
diff --git a/include/cmark/references.c b/include/cmark/references.c
new file mode 100644
index 0000000..89f2dc8
--- /dev/null
+++ b/include/cmark/references.c
@@ -0,0 +1,146 @@
+#include "cmark.h"
+#include "utf8.h"
+#include "parser.h"
+#include "references.h"
+#include "inlines.h"
+#include "chunk.h"
+
+static unsigned int refhash(const unsigned char *link_ref) {
+ unsigned int hash = 0;
+
+ while (*link_ref)
+ hash = (*link_ref++) + (hash << 6) + (hash << 16) - hash;
+
+ return hash;
+}
+
+static void reference_free(cmark_reference_map *map, cmark_reference *ref) {
+ cmark_mem *mem = map->mem;
+ if (ref != NULL) {
+ mem->free(ref->label);
+ cmark_chunk_free(mem, &ref->url);
+ cmark_chunk_free(mem, &ref->title);
+ mem->free(ref);
+ }
+}
+
+// normalize reference: collapse internal whitespace to single space,
+// remove leading/trailing whitespace, case fold
+// Return NULL if the reference name is actually empty (i.e. composed
+// solely from whitespace)
+static unsigned char *normalize_reference(cmark_mem *mem, cmark_chunk *ref) {
+ cmark_strbuf normalized = CMARK_BUF_INIT(mem);
+ unsigned char *result;
+
+ if (ref == NULL)
+ return NULL;
+
+ if (ref->len == 0)
+ return NULL;
+
+ cmark_utf8proc_case_fold(&normalized, ref->data, ref->len);
+ cmark_strbuf_trim(&normalized);
+ cmark_strbuf_normalize_whitespace(&normalized);
+
+ result = cmark_strbuf_detach(&normalized);
+ assert(result);
+
+ if (result[0] == '\0') {
+ mem->free(result);
+ return NULL;
+ }
+
+ return result;
+}
+
+static void add_reference(cmark_reference_map *map, cmark_reference *ref) {
+ cmark_reference *t = ref->next = map->table[ref->hash % REFMAP_SIZE];
+
+ while (t) {
+ if (t->hash == ref->hash && !strcmp((char *)t->label, (char *)ref->label)) {
+ reference_free(map, ref);
+ return;
+ }
+
+ t = t->next;
+ }
+
+ map->table[ref->hash % REFMAP_SIZE] = ref;
+}
+
+void cmark_reference_create(cmark_reference_map *map, cmark_chunk *label,
+ cmark_chunk *url, cmark_chunk *title) {
+ cmark_reference *ref;
+ unsigned char *reflabel = normalize_reference(map->mem, label);
+
+ /* empty reference name, or composed from only whitespace */
+ if (reflabel == NULL)
+ return;
+
+ ref = (cmark_reference *)map->mem->calloc(1, sizeof(*ref));
+ ref->label = reflabel;
+ ref->hash = refhash(ref->label);
+ ref->url = cmark_clean_url(map->mem, url);
+ ref->title = cmark_clean_title(map->mem, title);
+ ref->next = NULL;
+
+ add_reference(map, ref);
+}
+
+// Returns reference if refmap contains a reference with matching
+// label, otherwise NULL.
+cmark_reference *cmark_reference_lookup(cmark_reference_map *map,
+ cmark_chunk *label) {
+ cmark_reference *ref = NULL;
+ unsigned char *norm;
+ unsigned int hash;
+
+ if (label->len < 1 || label->len > MAX_LINK_LABEL_LENGTH)
+ return NULL;
+
+ if (map == NULL)
+ return NULL;
+
+ norm = normalize_reference(map->mem, label);
+ if (norm == NULL)
+ return NULL;
+
+ hash = refhash(norm);
+ ref = map->table[hash % REFMAP_SIZE];
+
+ while (ref) {
+ if (ref->hash == hash && !strcmp((char *)ref->label, (char *)norm))
+ break;
+ ref = ref->next;
+ }
+
+ map->mem->free(norm);
+ return ref;
+}
+
+void cmark_reference_map_free(cmark_reference_map *map) {
+ unsigned int i;
+
+ if (map == NULL)
+ return;
+
+ for (i = 0; i < REFMAP_SIZE; ++i) {
+ cmark_reference *ref = map->table[i];
+ cmark_reference *next;
+
+ while (ref) {
+ next = ref->next;
+ reference_free(map, ref);
+ ref = next;
+ }
+ }
+
+ map->mem->free(map);
+}
+
+cmark_reference_map *cmark_reference_map_new(cmark_mem *mem) {
+ cmark_reference_map *map =
+ (cmark_reference_map *)mem->calloc(1, sizeof(cmark_reference_map));
+ map->mem = mem;
+ return map;
+}
diff --git a/include/cmark/references.h b/include/cmark/references.h
new file mode 100644
index 0000000..f075bbb
--- /dev/null
+++ b/include/cmark/references.h
@@ -0,0 +1,41 @@
+#ifndef CMARK_REFERENCES_H
+#define CMARK_REFERENCES_H
+
+#include "memory.h"
+#include "chunk.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define REFMAP_SIZE 16
+
+struct cmark_reference {
+ struct cmark_reference *next;
+ unsigned char *label;
+ cmark_chunk url;
+ cmark_chunk title;
+ unsigned int hash;
+};
+
+typedef struct cmark_reference cmark_reference;
+
+struct cmark_reference_map {
+ cmark_mem *mem;
+ cmark_reference *table[REFMAP_SIZE];
+};
+
+typedef struct cmark_reference_map cmark_reference_map;
+
+cmark_reference_map *cmark_reference_map_new(cmark_mem *mem);
+void cmark_reference_map_free(cmark_reference_map *map);
+cmark_reference *cmark_reference_lookup(cmark_reference_map *map,
+ cmark_chunk *label);
+extern void cmark_reference_create(cmark_reference_map *map, cmark_chunk *label,
+ cmark_chunk *url, cmark_chunk *title);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cmark/render.c b/include/cmark/render.c
new file mode 100644
index 0000000..dd65d3b
--- /dev/null
+++ b/include/cmark/render.c
@@ -0,0 +1,186 @@
+#include
+#include "buffer.h"
+#include "chunk.h"
+#include "cmark.h"
+#include "utf8.h"
+#include "render.h"
+#include "node.h"
+
+static CMARK_INLINE void S_cr(cmark_renderer *renderer) {
+ if (renderer->need_cr < 1) {
+ renderer->need_cr = 1;
+ }
+}
+
+static CMARK_INLINE void S_blankline(cmark_renderer *renderer) {
+ if (renderer->need_cr < 2) {
+ renderer->need_cr = 2;
+ }
+}
+
+static void S_out(cmark_renderer *renderer, const char *source, bool wrap,
+ cmark_escaping escape) {
+ int length = strlen(source);
+ unsigned char nextc;
+ int32_t c;
+ int i = 0;
+ int last_nonspace;
+ int len;
+ cmark_chunk remainder = cmark_chunk_literal("");
+ int k = renderer->buffer->size - 1;
+
+ wrap = wrap && !renderer->no_linebreaks;
+
+ if (renderer->in_tight_list_item && renderer->need_cr > 1) {
+ renderer->need_cr = 1;
+ }
+ while (renderer->need_cr) {
+ if (k < 0 || renderer->buffer->ptr[k] == '\n') {
+ k -= 1;
+ } else {
+ cmark_strbuf_putc(renderer->buffer, '\n');
+ if (renderer->need_cr > 1) {
+ cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
+ renderer->prefix->size);
+ }
+ }
+ renderer->column = 0;
+ renderer->last_breakable = 0;
+ renderer->begin_line = true;
+ renderer->begin_content = true;
+ renderer->need_cr -= 1;
+ }
+
+ while (i < length) {
+ if (renderer->begin_line) {
+ cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
+ renderer->prefix->size);
+ // note: this assumes prefix is ascii:
+ renderer->column = renderer->prefix->size;
+ }
+
+ len = cmark_utf8proc_iterate((const uint8_t *)source + i, length - i, &c);
+ if (len == -1) { // error condition
+ return; // return without rendering rest of string
+ }
+ nextc = source[i + len];
+ if (c == 32 && wrap) {
+ if (!renderer->begin_line) {
+ last_nonspace = renderer->buffer->size;
+ cmark_strbuf_putc(renderer->buffer, ' ');
+ renderer->column += 1;
+ renderer->begin_line = false;
+ renderer->begin_content = false;
+ // skip following spaces
+ while (source[i + 1] == ' ') {
+ i++;
+ }
+ // We don't allow breaks that make a digit the first character
+ // because this causes problems with commonmark output.
+ if (!cmark_isdigit(source[i + 1])) {
+ renderer->last_breakable = last_nonspace;
+ }
+ }
+
+ } else if (c == 10) {
+ cmark_strbuf_putc(renderer->buffer, '\n');
+ renderer->column = 0;
+ renderer->begin_line = true;
+ renderer->begin_content = true;
+ renderer->last_breakable = 0;
+ } else if (escape == LITERAL) {
+ cmark_render_code_point(renderer, c);
+ renderer->begin_line = false;
+ // we don't set 'begin_content' to false til we've
+ // finished parsing a digit. Reason: in commonmark
+ // we need to escape a potential list marker after
+ // a digit:
+ renderer->begin_content =
+ renderer->begin_content && cmark_isdigit(c) == 1;
+ } else {
+ (renderer->outc)(renderer, escape, c, nextc);
+ renderer->begin_line = false;
+ renderer->begin_content =
+ renderer->begin_content && cmark_isdigit(c) == 1;
+ }
+
+ // If adding the character went beyond width, look for an
+ // earlier place where the line could be broken:
+ if (renderer->width > 0 && renderer->column > renderer->width &&
+ !renderer->begin_line && renderer->last_breakable > 0) {
+
+ // copy from last_breakable to remainder
+ cmark_chunk_set_cstr(renderer->mem, &remainder,
+ (char *)renderer->buffer->ptr +
+ renderer->last_breakable + 1);
+ // truncate at last_breakable
+ cmark_strbuf_truncate(renderer->buffer, renderer->last_breakable);
+ // add newline, prefix, and remainder
+ cmark_strbuf_putc(renderer->buffer, '\n');
+ cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
+ renderer->prefix->size);
+ cmark_strbuf_put(renderer->buffer, remainder.data, remainder.len);
+ renderer->column = renderer->prefix->size + remainder.len;
+ cmark_chunk_free(renderer->mem, &remainder);
+ renderer->last_breakable = 0;
+ renderer->begin_line = false;
+ renderer->begin_content = false;
+ }
+
+ i += len;
+ }
+}
+
+// Assumes no newlines, assumes ascii content:
+void cmark_render_ascii(cmark_renderer *renderer, const char *s) {
+ int origsize = renderer->buffer->size;
+ cmark_strbuf_puts(renderer->buffer, s);
+ renderer->column += renderer->buffer->size - origsize;
+}
+
+void cmark_render_code_point(cmark_renderer *renderer, uint32_t c) {
+ cmark_utf8proc_encode_char(c, renderer->buffer);
+ renderer->column += 1;
+}
+
+char *cmark_render(cmark_node *root, int options, int width,
+ void (*outc)(cmark_renderer *, cmark_escaping, int32_t,
+ unsigned char),
+ int (*render_node)(cmark_renderer *renderer,
+ cmark_node *node,
+ cmark_event_type ev_type, int options)) {
+ cmark_mem *mem = cmark_node_mem(root);
+ cmark_strbuf pref = CMARK_BUF_INIT(mem);
+ cmark_strbuf buf = CMARK_BUF_INIT(mem);
+ cmark_node *cur;
+ cmark_event_type ev_type;
+ char *result;
+ cmark_iter *iter = cmark_iter_new(root);
+
+ cmark_renderer renderer = {mem, &buf, &pref, 0, width,
+ 0, 0, true, true, false,
+ false, outc, S_cr, S_blankline, S_out};
+
+ while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
+ cur = cmark_iter_get_node(iter);
+ if (!render_node(&renderer, cur, ev_type, options)) {
+ // a false value causes us to skip processing
+ // the node's contents. this is used for
+ // autolinks.
+ cmark_iter_reset(iter, cur, CMARK_EVENT_EXIT);
+ }
+ }
+
+ // ensure final newline
+ if (renderer.buffer->ptr[renderer.buffer->size - 1] != '\n') {
+ cmark_strbuf_putc(renderer.buffer, '\n');
+ }
+
+ result = (char *)cmark_strbuf_detach(renderer.buffer);
+
+ cmark_iter_free(iter);
+ cmark_strbuf_free(renderer.prefix);
+ cmark_strbuf_free(renderer.buffer);
+
+ return result;
+}
diff --git a/include/cmark/render.h b/include/cmark/render.h
new file mode 100644
index 0000000..35eb0a6
--- /dev/null
+++ b/include/cmark/render.h
@@ -0,0 +1,50 @@
+#ifndef CMARK_RENDER_H
+#define CMARK_RENDER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include "buffer.h"
+#include "chunk.h"
+#include "memory.h"
+
+typedef enum { LITERAL, NORMAL, TITLE, URL } cmark_escaping;
+
+struct cmark_renderer {
+ cmark_mem *mem;
+ cmark_strbuf *buffer;
+ cmark_strbuf *prefix;
+ int column;
+ int width;
+ int need_cr;
+ bufsize_t last_breakable;
+ bool begin_line;
+ bool begin_content;
+ bool no_linebreaks;
+ bool in_tight_list_item;
+ void (*outc)(struct cmark_renderer *, cmark_escaping, int32_t, unsigned char);
+ void (*cr)(struct cmark_renderer *);
+ void (*blankline)(struct cmark_renderer *);
+ void (*out)(struct cmark_renderer *, const char *, bool, cmark_escaping);
+};
+
+typedef struct cmark_renderer cmark_renderer;
+
+void cmark_render_ascii(cmark_renderer *renderer, const char *s);
+
+void cmark_render_code_point(cmark_renderer *renderer, uint32_t c);
+
+char *cmark_render(cmark_node *root, int options, int width,
+ void (*outc)(cmark_renderer *, cmark_escaping, int32_t,
+ unsigned char),
+ int (*render_node)(cmark_renderer *renderer,
+ cmark_node *node,
+ cmark_event_type ev_type, int options));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cmark/scanners.c b/include/cmark/scanners.c
new file mode 100644
index 0000000..3ee0cfa
--- /dev/null
+++ b/include/cmark/scanners.c
@@ -0,0 +1,13190 @@
+/* Generated by re2c 1.0.2 */
+#include
+#include "chunk.h"
+#include "scanners.h"
+
+bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c,
+ bufsize_t offset) {
+ bufsize_t res;
+ unsigned char *ptr = (unsigned char *)c->data;
+
+ if (ptr == NULL || offset > c->len) {
+ return 0;
+ } else {
+ unsigned char lim = ptr[c->len];
+
+ ptr[c->len] = '\0';
+ res = scanner(ptr + offset);
+ ptr[c->len] = lim;
+ }
+
+ return res;
+}
+
+// Try to match a scheme including colon.
+bufsize_t _scan_scheme(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ yych = *p;
+ if (yych <= '@')
+ goto yy2;
+ if (yych <= 'Z')
+ goto yy4;
+ if (yych <= '`')
+ goto yy2;
+ if (yych <= 'z')
+ goto yy4;
+ yy2:
+ ++p;
+ yy3 : { return 0; }
+ yy4:
+ yych = *(marker = ++p);
+ if (yych <= '/') {
+ if (yych <= '+') {
+ if (yych <= '*')
+ goto yy3;
+ } else {
+ if (yych <= ',')
+ goto yy3;
+ if (yych >= '/')
+ goto yy3;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '9')
+ goto yy5;
+ if (yych <= '@')
+ goto yy3;
+ } else {
+ if (yych <= '`')
+ goto yy3;
+ if (yych >= '{')
+ goto yy3;
+ }
+ }
+ yy5:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych == '+')
+ goto yy7;
+ } else {
+ if (yych != '/')
+ goto yy7;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych >= 'A')
+ goto yy7;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych <= 'z')
+ goto yy7;
+ }
+ }
+ yy6:
+ p = marker;
+ goto yy3;
+ yy7:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych == '+')
+ goto yy10;
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ goto yy10;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ goto yy10;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych <= 'z')
+ goto yy10;
+ goto yy6;
+ }
+ }
+ yy8:
+ ++p;
+ { return (bufsize_t)(p - start); }
+ yy10:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy6;
+ } else {
+ if (yych == '/')
+ goto yy6;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy8;
+ if (yych <= '@')
+ goto yy6;
+ } else {
+ if (yych <= '`')
+ goto yy6;
+ if (yych >= '{')
+ goto yy6;
+ }
+ }
+ yych = *++p;
+ if (yych == ':')
+ goto yy8;
+ goto yy6;
+ }
+}
+
+// Try to match URI autolink after first <, returning number of chars matched.
+bufsize_t _scan_autolink_uri(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ static const unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 0, 128, 0, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych <= '@')
+ goto yy41;
+ if (yych <= 'Z')
+ goto yy43;
+ if (yych <= '`')
+ goto yy41;
+ if (yych <= 'z')
+ goto yy43;
+ yy41:
+ ++p;
+ yy42 : { return 0; }
+ yy43:
+ yych = *(marker = ++p);
+ if (yych <= '/') {
+ if (yych <= '+') {
+ if (yych <= '*')
+ goto yy42;
+ } else {
+ if (yych <= ',')
+ goto yy42;
+ if (yych >= '/')
+ goto yy42;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '9')
+ goto yy44;
+ if (yych <= '@')
+ goto yy42;
+ } else {
+ if (yych <= '`')
+ goto yy42;
+ if (yych >= '{')
+ goto yy42;
+ }
+ }
+ yy44:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych == '+')
+ goto yy46;
+ } else {
+ if (yych != '/')
+ goto yy46;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych >= 'A')
+ goto yy46;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych <= 'z')
+ goto yy46;
+ }
+ }
+ yy45:
+ p = marker;
+ goto yy42;
+ yy46:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych == '+')
+ goto yy49;
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ goto yy49;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ goto yy49;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych <= 'z')
+ goto yy49;
+ goto yy45;
+ }
+ }
+ yy47:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy47;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '<')
+ goto yy45;
+ if (yych <= '>')
+ goto yy50;
+ goto yy45;
+ } else {
+ if (yych <= 0xDF)
+ goto yy52;
+ if (yych <= 0xE0)
+ goto yy53;
+ goto yy54;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy55;
+ if (yych <= 0xEF)
+ goto yy54;
+ goto yy56;
+ } else {
+ if (yych <= 0xF3)
+ goto yy57;
+ if (yych <= 0xF4)
+ goto yy58;
+ goto yy45;
+ }
+ }
+ yy49:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych == '+')
+ goto yy59;
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ goto yy59;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ goto yy59;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych <= 'z')
+ goto yy59;
+ goto yy45;
+ }
+ }
+ yy50:
+ ++p;
+ { return (bufsize_t)(p - start); }
+ yy52:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy45;
+ if (yych <= 0xBF)
+ goto yy47;
+ goto yy45;
+ yy53:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy45;
+ if (yych <= 0xBF)
+ goto yy52;
+ goto yy45;
+ yy54:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy45;
+ if (yych <= 0xBF)
+ goto yy52;
+ goto yy45;
+ yy55:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy45;
+ if (yych <= 0x9F)
+ goto yy52;
+ goto yy45;
+ yy56:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy45;
+ if (yych <= 0xBF)
+ goto yy54;
+ goto yy45;
+ yy57:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy45;
+ if (yych <= 0xBF)
+ goto yy54;
+ goto yy45;
+ yy58:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy45;
+ if (yych <= 0x8F)
+ goto yy54;
+ goto yy45;
+ yy59:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych <= ',') {
+ if (yych != '+')
+ goto yy45;
+ } else {
+ if (yych == '/')
+ goto yy45;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= ':')
+ goto yy47;
+ if (yych <= '@')
+ goto yy45;
+ } else {
+ if (yych <= '`')
+ goto yy45;
+ if (yych >= '{')
+ goto yy45;
+ }
+ }
+ yych = *++p;
+ if (yych == ':')
+ goto yy47;
+ goto yy45;
+ }
+}
+
+// Try to match email autolink after first <, returning num of chars matched.
+bufsize_t _scan_autolink_email(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ static const unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 128, 0, 128, 128, 128, 128, 128, 0, 0,
+ 128, 128, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 0, 0, 0, 128, 0, 128, 0, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych <= '9') {
+ if (yych <= '\'') {
+ if (yych == '!')
+ goto yy91;
+ if (yych >= '#')
+ goto yy91;
+ } else {
+ if (yych <= ')')
+ goto yy89;
+ if (yych != ',')
+ goto yy91;
+ }
+ } else {
+ if (yych <= '?') {
+ if (yych == '=')
+ goto yy91;
+ if (yych >= '?')
+ goto yy91;
+ } else {
+ if (yych <= 'Z') {
+ if (yych >= 'A')
+ goto yy91;
+ } else {
+ if (yych <= ']')
+ goto yy89;
+ if (yych <= '~')
+ goto yy91;
+ }
+ }
+ }
+ yy89:
+ ++p;
+ yy90 : { return 0; }
+ yy91:
+ yych = *(marker = ++p);
+ if (yych <= ',') {
+ if (yych <= '"') {
+ if (yych == '!')
+ goto yy93;
+ goto yy90;
+ } else {
+ if (yych <= '\'')
+ goto yy93;
+ if (yych <= ')')
+ goto yy90;
+ if (yych <= '+')
+ goto yy93;
+ goto yy90;
+ }
+ } else {
+ if (yych <= '>') {
+ if (yych <= '9')
+ goto yy93;
+ if (yych == '=')
+ goto yy93;
+ goto yy90;
+ } else {
+ if (yych <= 'Z')
+ goto yy93;
+ if (yych <= ']')
+ goto yy90;
+ if (yych <= '~')
+ goto yy93;
+ goto yy90;
+ }
+ }
+ yy92:
+ yych = *++p;
+ yy93:
+ if (yybm[0 + yych] & 128) {
+ goto yy92;
+ }
+ if (yych <= '>')
+ goto yy94;
+ if (yych <= '@')
+ goto yy95;
+ yy94:
+ p = marker;
+ goto yy90;
+ yy95:
+ yych = *++p;
+ if (yych <= '@') {
+ if (yych <= '/')
+ goto yy94;
+ if (yych >= ':')
+ goto yy94;
+ } else {
+ if (yych <= 'Z')
+ goto yy96;
+ if (yych <= '`')
+ goto yy94;
+ if (yych >= '{')
+ goto yy94;
+ }
+ yy96:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy98;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy98;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy98;
+ goto yy94;
+ }
+ }
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy101;
+ if (yych <= '/')
+ goto yy94;
+ goto yy102;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy102;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy102;
+ goto yy94;
+ }
+ }
+ yy98:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych <= '-')
+ goto yy101;
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy102;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy102;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy102;
+ goto yy94;
+ }
+ }
+ yy99:
+ ++p;
+ { return (bufsize_t)(p - start); }
+ yy101:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy103;
+ if (yych <= '/')
+ goto yy94;
+ goto yy104;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy104;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy104;
+ goto yy94;
+ }
+ }
+ yy102:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy104;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy104;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy104;
+ goto yy94;
+ }
+ }
+ yy103:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy105;
+ if (yych <= '/')
+ goto yy94;
+ goto yy106;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy106;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy106;
+ goto yy94;
+ }
+ }
+ yy104:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy106;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy106;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy106;
+ goto yy94;
+ }
+ }
+ yy105:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy107;
+ if (yych <= '/')
+ goto yy94;
+ goto yy108;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy108;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy108;
+ goto yy94;
+ }
+ }
+ yy106:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy108;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy108;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy108;
+ goto yy94;
+ }
+ }
+ yy107:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy109;
+ if (yych <= '/')
+ goto yy94;
+ goto yy110;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy110;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy110;
+ goto yy94;
+ }
+ }
+ yy108:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy110;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy110;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy110;
+ goto yy94;
+ }
+ }
+ yy109:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy111;
+ if (yych <= '/')
+ goto yy94;
+ goto yy112;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy112;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy112;
+ goto yy94;
+ }
+ }
+ yy110:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy112;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy112;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy112;
+ goto yy94;
+ }
+ }
+ yy111:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy113;
+ if (yych <= '/')
+ goto yy94;
+ goto yy114;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy114;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy114;
+ goto yy94;
+ }
+ }
+ yy112:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy114;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy114;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy114;
+ goto yy94;
+ }
+ }
+ yy113:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy115;
+ if (yych <= '/')
+ goto yy94;
+ goto yy116;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy116;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy116;
+ goto yy94;
+ }
+ }
+ yy114:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy116;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy116;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy116;
+ goto yy94;
+ }
+ }
+ yy115:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy117;
+ if (yych <= '/')
+ goto yy94;
+ goto yy118;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy118;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy118;
+ goto yy94;
+ }
+ }
+ yy116:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy118;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy118;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy118;
+ goto yy94;
+ }
+ }
+ yy117:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy119;
+ if (yych <= '/')
+ goto yy94;
+ goto yy120;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy120;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy120;
+ goto yy94;
+ }
+ }
+ yy118:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy120;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy120;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy120;
+ goto yy94;
+ }
+ }
+ yy119:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy121;
+ if (yych <= '/')
+ goto yy94;
+ goto yy122;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy122;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy122;
+ goto yy94;
+ }
+ }
+ yy120:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy122;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy122;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy122;
+ goto yy94;
+ }
+ }
+ yy121:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy123;
+ if (yych <= '/')
+ goto yy94;
+ goto yy124;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy124;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy124;
+ goto yy94;
+ }
+ }
+ yy122:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy124;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy124;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy124;
+ goto yy94;
+ }
+ }
+ yy123:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy125;
+ if (yych <= '/')
+ goto yy94;
+ goto yy126;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy126;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy126;
+ goto yy94;
+ }
+ }
+ yy124:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy126;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy126;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy126;
+ goto yy94;
+ }
+ }
+ yy125:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy127;
+ if (yych <= '/')
+ goto yy94;
+ goto yy128;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy128;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy128;
+ goto yy94;
+ }
+ }
+ yy126:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy128;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy128;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy128;
+ goto yy94;
+ }
+ }
+ yy127:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy129;
+ if (yych <= '/')
+ goto yy94;
+ goto yy130;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy130;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy130;
+ goto yy94;
+ }
+ }
+ yy128:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy130;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy130;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy130;
+ goto yy94;
+ }
+ }
+ yy129:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy131;
+ if (yych <= '/')
+ goto yy94;
+ goto yy132;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy132;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy132;
+ goto yy94;
+ }
+ }
+ yy130:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy132;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy132;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy132;
+ goto yy94;
+ }
+ }
+ yy131:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy133;
+ if (yych <= '/')
+ goto yy94;
+ goto yy134;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy134;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy134;
+ goto yy94;
+ }
+ }
+ yy132:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy134;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy134;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy134;
+ goto yy94;
+ }
+ }
+ yy133:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy135;
+ if (yych <= '/')
+ goto yy94;
+ goto yy136;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy136;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy136;
+ goto yy94;
+ }
+ }
+ yy134:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy136;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy136;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy136;
+ goto yy94;
+ }
+ }
+ yy135:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy137;
+ if (yych <= '/')
+ goto yy94;
+ goto yy138;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy138;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy138;
+ goto yy94;
+ }
+ }
+ yy136:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy138;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy138;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy138;
+ goto yy94;
+ }
+ }
+ yy137:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy139;
+ if (yych <= '/')
+ goto yy94;
+ goto yy140;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy140;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy140;
+ goto yy94;
+ }
+ }
+ yy138:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy140;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy140;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy140;
+ goto yy94;
+ }
+ }
+ yy139:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy141;
+ if (yych <= '/')
+ goto yy94;
+ goto yy142;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy142;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy142;
+ goto yy94;
+ }
+ }
+ yy140:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy142;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy142;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy142;
+ goto yy94;
+ }
+ }
+ yy141:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy143;
+ if (yych <= '/')
+ goto yy94;
+ goto yy144;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy144;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy144;
+ goto yy94;
+ }
+ }
+ yy142:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy144;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy144;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy144;
+ goto yy94;
+ }
+ }
+ yy143:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy145;
+ if (yych <= '/')
+ goto yy94;
+ goto yy146;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy146;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy146;
+ goto yy94;
+ }
+ }
+ yy144:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy146;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy146;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy146;
+ goto yy94;
+ }
+ }
+ yy145:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy147;
+ if (yych <= '/')
+ goto yy94;
+ goto yy148;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy148;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy148;
+ goto yy94;
+ }
+ }
+ yy146:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy148;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy148;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy148;
+ goto yy94;
+ }
+ }
+ yy147:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy149;
+ if (yych <= '/')
+ goto yy94;
+ goto yy150;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy150;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy150;
+ goto yy94;
+ }
+ }
+ yy148:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy150;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy150;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy150;
+ goto yy94;
+ }
+ }
+ yy149:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy151;
+ if (yych <= '/')
+ goto yy94;
+ goto yy152;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy152;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy152;
+ goto yy94;
+ }
+ }
+ yy150:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy152;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy152;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy152;
+ goto yy94;
+ }
+ }
+ yy151:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy153;
+ if (yych <= '/')
+ goto yy94;
+ goto yy154;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy154;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy154;
+ goto yy94;
+ }
+ }
+ yy152:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy154;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy154;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy154;
+ goto yy94;
+ }
+ }
+ yy153:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy155;
+ if (yych <= '/')
+ goto yy94;
+ goto yy156;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy156;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy156;
+ goto yy94;
+ }
+ }
+ yy154:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy156;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy156;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy156;
+ goto yy94;
+ }
+ }
+ yy155:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy157;
+ if (yych <= '/')
+ goto yy94;
+ goto yy158;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy158;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy158;
+ goto yy94;
+ }
+ }
+ yy156:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy158;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy158;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy158;
+ goto yy94;
+ }
+ }
+ yy157:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy159;
+ if (yych <= '/')
+ goto yy94;
+ goto yy160;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy160;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy160;
+ goto yy94;
+ }
+ }
+ yy158:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy160;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy160;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy160;
+ goto yy94;
+ }
+ }
+ yy159:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy161;
+ if (yych <= '/')
+ goto yy94;
+ goto yy162;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy162;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy162;
+ goto yy94;
+ }
+ }
+ yy160:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy162;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy162;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy162;
+ goto yy94;
+ }
+ }
+ yy161:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy163;
+ if (yych <= '/')
+ goto yy94;
+ goto yy164;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy164;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy164;
+ goto yy94;
+ }
+ }
+ yy162:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy164;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy164;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy164;
+ goto yy94;
+ }
+ }
+ yy163:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy165;
+ if (yych <= '/')
+ goto yy94;
+ goto yy166;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy166;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy166;
+ goto yy94;
+ }
+ }
+ yy164:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy166;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy166;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy166;
+ goto yy94;
+ }
+ }
+ yy165:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy167;
+ if (yych <= '/')
+ goto yy94;
+ goto yy168;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy168;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy168;
+ goto yy94;
+ }
+ }
+ yy166:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy168;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy168;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy168;
+ goto yy94;
+ }
+ }
+ yy167:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy169;
+ if (yych <= '/')
+ goto yy94;
+ goto yy170;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy170;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy170;
+ goto yy94;
+ }
+ }
+ yy168:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy170;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy170;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy170;
+ goto yy94;
+ }
+ }
+ yy169:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy171;
+ if (yych <= '/')
+ goto yy94;
+ goto yy172;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy172;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy172;
+ goto yy94;
+ }
+ }
+ yy170:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy172;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy172;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy172;
+ goto yy94;
+ }
+ }
+ yy171:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy173;
+ if (yych <= '/')
+ goto yy94;
+ goto yy174;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy174;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy174;
+ goto yy94;
+ }
+ }
+ yy172:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy174;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy174;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy174;
+ goto yy94;
+ }
+ }
+ yy173:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy175;
+ if (yych <= '/')
+ goto yy94;
+ goto yy176;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy176;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy176;
+ goto yy94;
+ }
+ }
+ yy174:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy176;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy176;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy176;
+ goto yy94;
+ }
+ }
+ yy175:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy177;
+ if (yych <= '/')
+ goto yy94;
+ goto yy178;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy178;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy178;
+ goto yy94;
+ }
+ }
+ yy176:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy178;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy178;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy178;
+ goto yy94;
+ }
+ }
+ yy177:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy179;
+ if (yych <= '/')
+ goto yy94;
+ goto yy180;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy180;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy180;
+ goto yy94;
+ }
+ }
+ yy178:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy180;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy180;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy180;
+ goto yy94;
+ }
+ }
+ yy179:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy181;
+ if (yych <= '/')
+ goto yy94;
+ goto yy182;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy182;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy182;
+ goto yy94;
+ }
+ }
+ yy180:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy182;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy182;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy182;
+ goto yy94;
+ }
+ }
+ yy181:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy183;
+ if (yych <= '/')
+ goto yy94;
+ goto yy184;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy184;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy184;
+ goto yy94;
+ }
+ }
+ yy182:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy184;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy184;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy184;
+ goto yy94;
+ }
+ }
+ yy183:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy185;
+ if (yych <= '/')
+ goto yy94;
+ goto yy186;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy186;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy186;
+ goto yy94;
+ }
+ }
+ yy184:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy186;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy186;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy186;
+ goto yy94;
+ }
+ }
+ yy185:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy187;
+ if (yych <= '/')
+ goto yy94;
+ goto yy188;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy188;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy188;
+ goto yy94;
+ }
+ }
+ yy186:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy188;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy188;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy188;
+ goto yy94;
+ }
+ }
+ yy187:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy189;
+ if (yych <= '/')
+ goto yy94;
+ goto yy190;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy190;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy190;
+ goto yy94;
+ }
+ }
+ yy188:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy190;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy190;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy190;
+ goto yy94;
+ }
+ }
+ yy189:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy191;
+ if (yych <= '/')
+ goto yy94;
+ goto yy192;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy192;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy192;
+ goto yy94;
+ }
+ }
+ yy190:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy192;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy192;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy192;
+ goto yy94;
+ }
+ }
+ yy191:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy193;
+ if (yych <= '/')
+ goto yy94;
+ goto yy194;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy194;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy194;
+ goto yy94;
+ }
+ }
+ yy192:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy194;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy194;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy194;
+ goto yy94;
+ }
+ }
+ yy193:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy195;
+ if (yych <= '/')
+ goto yy94;
+ goto yy196;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy196;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy196;
+ goto yy94;
+ }
+ }
+ yy194:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy196;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy196;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy196;
+ goto yy94;
+ }
+ }
+ yy195:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy197;
+ if (yych <= '/')
+ goto yy94;
+ goto yy198;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy198;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy198;
+ goto yy94;
+ }
+ }
+ yy196:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy198;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy198;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy198;
+ goto yy94;
+ }
+ }
+ yy197:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy199;
+ if (yych <= '/')
+ goto yy94;
+ goto yy200;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy200;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy200;
+ goto yy94;
+ }
+ }
+ yy198:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy200;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy200;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy200;
+ goto yy94;
+ }
+ }
+ yy199:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy201;
+ if (yych <= '/')
+ goto yy94;
+ goto yy202;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy202;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy202;
+ goto yy94;
+ }
+ }
+ yy200:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy202;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy202;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy202;
+ goto yy94;
+ }
+ }
+ yy201:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy203;
+ if (yych <= '/')
+ goto yy94;
+ goto yy204;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy204;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy204;
+ goto yy94;
+ }
+ }
+ yy202:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy204;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy204;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy204;
+ goto yy94;
+ }
+ }
+ yy203:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy205;
+ if (yych <= '/')
+ goto yy94;
+ goto yy206;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy206;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy206;
+ goto yy94;
+ }
+ }
+ yy204:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy206;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy206;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy206;
+ goto yy94;
+ }
+ }
+ yy205:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy207;
+ if (yych <= '/')
+ goto yy94;
+ goto yy208;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy208;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy208;
+ goto yy94;
+ }
+ }
+ yy206:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy208;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy208;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy208;
+ goto yy94;
+ }
+ }
+ yy207:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy209;
+ if (yych <= '/')
+ goto yy94;
+ goto yy210;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy210;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy210;
+ goto yy94;
+ }
+ }
+ yy208:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy210;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy210;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy210;
+ goto yy94;
+ }
+ }
+ yy209:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy211;
+ if (yych <= '/')
+ goto yy94;
+ goto yy212;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy212;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy212;
+ goto yy94;
+ }
+ }
+ yy210:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy212;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy212;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy212;
+ goto yy94;
+ }
+ }
+ yy211:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy213;
+ if (yych <= '/')
+ goto yy94;
+ goto yy214;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy214;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy214;
+ goto yy94;
+ }
+ }
+ yy212:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy214;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy214;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy214;
+ goto yy94;
+ }
+ }
+ yy213:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy215;
+ if (yych <= '/')
+ goto yy94;
+ goto yy216;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy216;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy216;
+ goto yy94;
+ }
+ }
+ yy214:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy216;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy216;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy216;
+ goto yy94;
+ }
+ }
+ yy215:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy217;
+ if (yych <= '/')
+ goto yy94;
+ goto yy218;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy218;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy218;
+ goto yy94;
+ }
+ }
+ yy216:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy218;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy218;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy218;
+ goto yy94;
+ }
+ }
+ yy217:
+ yych = *++p;
+ if (yych <= '9') {
+ if (yych == '-')
+ goto yy219;
+ if (yych <= '/')
+ goto yy94;
+ goto yy220;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy94;
+ goto yy220;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy220;
+ goto yy94;
+ }
+ }
+ yy218:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= ',')
+ goto yy94;
+ if (yych >= '.')
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy220;
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ goto yy220;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy220;
+ goto yy94;
+ }
+ }
+ yy219:
+ yych = *++p;
+ if (yych <= '@') {
+ if (yych <= '/')
+ goto yy94;
+ if (yych <= '9')
+ goto yy221;
+ goto yy94;
+ } else {
+ if (yych <= 'Z')
+ goto yy221;
+ if (yych <= '`')
+ goto yy94;
+ if (yych <= 'z')
+ goto yy221;
+ goto yy94;
+ }
+ yy220:
+ yych = *++p;
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych <= '-')
+ goto yy94;
+ goto yy95;
+ } else {
+ if (yych <= '/')
+ goto yy94;
+ if (yych >= ':')
+ goto yy94;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy99;
+ if (yych <= '@')
+ goto yy94;
+ } else {
+ if (yych <= '`')
+ goto yy94;
+ if (yych >= '{')
+ goto yy94;
+ }
+ }
+ yy221:
+ yych = *++p;
+ if (yych == '.')
+ goto yy95;
+ if (yych == '>')
+ goto yy99;
+ goto yy94;
+ }
+}
+
+// Try to match an HTML tag after first <, returning num of chars matched.
+bufsize_t _scan_html_tag(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ static const unsigned char yybm[] = {
+ /* table 1 .. 8: 0 */
+ 0, 250, 250, 250, 250, 250, 250, 250, 250, 235, 235, 235, 235, 235, 250,
+ 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
+ 250, 250, 250, 235, 250, 202, 250, 250, 250, 250, 170, 250, 250, 250,
+ 250, 250, 246, 254, 250, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 250, 234, 234, 232, 250, 250, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 250, 250, 122, 250, 254, 234, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
+ 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 250, 250, 250, 250,
+ 250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* table 9 .. 11: 256 */
+ 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 192, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192,
+ 192, 128, 128, 128, 128, 128, 0, 128, 224, 224, 224, 224, 224, 224, 224,
+ 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
+ 224, 224, 224, 224, 224, 128, 128, 128, 128, 128, 128, 192, 192, 192,
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 128, 128, 128, 128, 128, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych <= '>') {
+ if (yych <= '!') {
+ if (yych >= '!')
+ goto yy226;
+ } else {
+ if (yych == '/')
+ goto yy227;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '?')
+ goto yy228;
+ if (yych >= 'A')
+ goto yy229;
+ } else {
+ if (yych <= '`')
+ goto yy224;
+ if (yych <= 'z')
+ goto yy229;
+ }
+ }
+ yy224:
+ ++p;
+ yy225 : { return 0; }
+ yy226:
+ yych = *(marker = ++p);
+ if (yybm[256 + yych] & 32) {
+ goto yy232;
+ }
+ if (yych == '-')
+ goto yy230;
+ if (yych <= '@')
+ goto yy225;
+ if (yych <= '[')
+ goto yy234;
+ goto yy225;
+ yy227:
+ yych = *(marker = ++p);
+ if (yych <= '@')
+ goto yy225;
+ if (yych <= 'Z')
+ goto yy235;
+ if (yych <= '`')
+ goto yy225;
+ if (yych <= 'z')
+ goto yy235;
+ goto yy225;
+ yy228:
+ yych = *(marker = ++p);
+ if (yych <= 0x00)
+ goto yy225;
+ if (yych <= 0x7F)
+ goto yy238;
+ if (yych <= 0xC1)
+ goto yy225;
+ if (yych <= 0xF4)
+ goto yy238;
+ goto yy225;
+ yy229:
+ yych = *(marker = ++p);
+ if (yych <= '.') {
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy225;
+ if (yych <= '\r')
+ goto yy250;
+ goto yy225;
+ } else {
+ if (yych <= ' ')
+ goto yy250;
+ if (yych == '-')
+ goto yy250;
+ goto yy225;
+ }
+ } else {
+ if (yych <= '@') {
+ if (yych <= '9')
+ goto yy250;
+ if (yych == '>')
+ goto yy250;
+ goto yy225;
+ } else {
+ if (yych <= 'Z')
+ goto yy250;
+ if (yych <= '`')
+ goto yy225;
+ if (yych <= 'z')
+ goto yy250;
+ goto yy225;
+ }
+ }
+ yy230:
+ yych = *++p;
+ if (yych == '-')
+ goto yy254;
+ yy231:
+ p = marker;
+ goto yy225;
+ yy232:
+ yych = *++p;
+ if (yybm[256 + yych] & 32) {
+ goto yy232;
+ }
+ if (yych <= 0x08)
+ goto yy231;
+ if (yych <= '\r')
+ goto yy255;
+ if (yych == ' ')
+ goto yy255;
+ goto yy231;
+ yy234:
+ yych = *++p;
+ if (yych == 'C')
+ goto yy257;
+ if (yych == 'c')
+ goto yy257;
+ goto yy231;
+ yy235:
+ yych = *++p;
+ if (yybm[256 + yych] & 64) {
+ goto yy235;
+ }
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy231;
+ if (yych <= '\r')
+ goto yy258;
+ goto yy231;
+ } else {
+ if (yych <= ' ')
+ goto yy258;
+ if (yych == '>')
+ goto yy252;
+ goto yy231;
+ }
+ yy237:
+ yych = *++p;
+ yy238:
+ if (yybm[256 + yych] & 128) {
+ goto yy237;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych >= '@')
+ goto yy231;
+ } else {
+ if (yych <= 0xDF)
+ goto yy240;
+ if (yych <= 0xE0)
+ goto yy241;
+ goto yy242;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy243;
+ if (yych <= 0xEF)
+ goto yy242;
+ goto yy244;
+ } else {
+ if (yych <= 0xF3)
+ goto yy245;
+ if (yych <= 0xF4)
+ goto yy246;
+ goto yy231;
+ }
+ }
+ yych = *++p;
+ if (yych <= 0xE0) {
+ if (yych <= '>') {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych <= '=')
+ goto yy237;
+ goto yy252;
+ } else {
+ if (yych <= 0x7F)
+ goto yy237;
+ if (yych <= 0xC1)
+ goto yy231;
+ if (yych >= 0xE0)
+ goto yy241;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy243;
+ goto yy242;
+ } else {
+ if (yych <= 0xF0)
+ goto yy244;
+ if (yych <= 0xF3)
+ goto yy245;
+ if (yych <= 0xF4)
+ goto yy246;
+ goto yy231;
+ }
+ }
+ yy240:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy237;
+ goto yy231;
+ yy241:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy240;
+ goto yy231;
+ yy242:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy240;
+ goto yy231;
+ yy243:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x9F)
+ goto yy240;
+ goto yy231;
+ yy244:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy242;
+ goto yy231;
+ yy245:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy242;
+ goto yy231;
+ yy246:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x8F)
+ goto yy242;
+ goto yy231;
+ yy247:
+ yych = *++p;
+ if (yybm[0 + yych] & 1) {
+ goto yy247;
+ }
+ if (yych <= '>') {
+ if (yych <= '9') {
+ if (yych == '/')
+ goto yy251;
+ goto yy231;
+ } else {
+ if (yych <= ':')
+ goto yy260;
+ if (yych <= '=')
+ goto yy231;
+ goto yy252;
+ }
+ } else {
+ if (yych <= '^') {
+ if (yych <= '@')
+ goto yy231;
+ if (yych <= 'Z')
+ goto yy260;
+ goto yy231;
+ } else {
+ if (yych == '`')
+ goto yy231;
+ if (yych <= 'z')
+ goto yy260;
+ goto yy231;
+ }
+ }
+ yy249:
+ yych = *++p;
+ yy250:
+ if (yybm[0 + yych] & 1) {
+ goto yy247;
+ }
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych == '-')
+ goto yy249;
+ goto yy231;
+ } else {
+ if (yych <= '/')
+ goto yy251;
+ if (yych <= '9')
+ goto yy249;
+ goto yy231;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy252;
+ if (yych <= '@')
+ goto yy231;
+ goto yy249;
+ } else {
+ if (yych <= '`')
+ goto yy231;
+ if (yych <= 'z')
+ goto yy249;
+ goto yy231;
+ }
+ }
+ yy251:
+ yych = *++p;
+ if (yych != '>')
+ goto yy231;
+ yy252:
+ ++p;
+ { return (bufsize_t)(p - start); }
+ yy254:
+ yych = *++p;
+ if (yych == '-')
+ goto yy264;
+ if (yych == '>')
+ goto yy231;
+ goto yy263;
+ yy255:
+ yych = *++p;
+ if (yybm[0 + yych] & 2) {
+ goto yy255;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych <= '>')
+ goto yy252;
+ goto yy231;
+ } else {
+ if (yych <= 0xDF)
+ goto yy272;
+ if (yych <= 0xE0)
+ goto yy273;
+ goto yy274;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy275;
+ if (yych <= 0xEF)
+ goto yy274;
+ goto yy276;
+ } else {
+ if (yych <= 0xF3)
+ goto yy277;
+ if (yych <= 0xF4)
+ goto yy278;
+ goto yy231;
+ }
+ }
+ yy257:
+ yych = *++p;
+ if (yych == 'D')
+ goto yy279;
+ if (yych == 'd')
+ goto yy279;
+ goto yy231;
+ yy258:
+ yych = *++p;
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy231;
+ if (yych <= '\r')
+ goto yy258;
+ goto yy231;
+ } else {
+ if (yych <= ' ')
+ goto yy258;
+ if (yych == '>')
+ goto yy252;
+ goto yy231;
+ }
+ yy260:
+ yych = *++p;
+ if (yybm[0 + yych] & 4) {
+ goto yy260;
+ }
+ if (yych <= ',') {
+ if (yych <= '\r') {
+ if (yych <= 0x08)
+ goto yy231;
+ goto yy280;
+ } else {
+ if (yych == ' ')
+ goto yy280;
+ goto yy231;
+ }
+ } else {
+ if (yych <= '<') {
+ if (yych <= '/')
+ goto yy251;
+ goto yy231;
+ } else {
+ if (yych <= '=')
+ goto yy282;
+ if (yych <= '>')
+ goto yy252;
+ goto yy231;
+ }
+ }
+ yy262:
+ yych = *++p;
+ yy263:
+ if (yybm[0 + yych] & 8) {
+ goto yy262;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych <= '-')
+ goto yy284;
+ goto yy231;
+ } else {
+ if (yych <= 0xDF)
+ goto yy265;
+ if (yych <= 0xE0)
+ goto yy266;
+ goto yy267;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy268;
+ if (yych <= 0xEF)
+ goto yy267;
+ goto yy269;
+ } else {
+ if (yych <= 0xF3)
+ goto yy270;
+ if (yych <= 0xF4)
+ goto yy271;
+ goto yy231;
+ }
+ }
+ yy264:
+ yych = *++p;
+ if (yych == '-')
+ goto yy251;
+ if (yych == '>')
+ goto yy231;
+ goto yy263;
+ yy265:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy262;
+ goto yy231;
+ yy266:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy265;
+ goto yy231;
+ yy267:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy265;
+ goto yy231;
+ yy268:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x9F)
+ goto yy265;
+ goto yy231;
+ yy269:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy267;
+ goto yy231;
+ yy270:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy267;
+ goto yy231;
+ yy271:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x8F)
+ goto yy267;
+ goto yy231;
+ yy272:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy255;
+ goto yy231;
+ yy273:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy272;
+ goto yy231;
+ yy274:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy272;
+ goto yy231;
+ yy275:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x9F)
+ goto yy272;
+ goto yy231;
+ yy276:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy274;
+ goto yy231;
+ yy277:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy274;
+ goto yy231;
+ yy278:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x8F)
+ goto yy274;
+ goto yy231;
+ yy279:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy285;
+ if (yych == 'a')
+ goto yy285;
+ goto yy231;
+ yy280:
+ yych = *++p;
+ if (yych <= '<') {
+ if (yych <= ' ') {
+ if (yych <= 0x08)
+ goto yy231;
+ if (yych <= '\r')
+ goto yy280;
+ if (yych <= 0x1F)
+ goto yy231;
+ goto yy280;
+ } else {
+ if (yych <= '/') {
+ if (yych <= '.')
+ goto yy231;
+ goto yy251;
+ } else {
+ if (yych == ':')
+ goto yy260;
+ goto yy231;
+ }
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '=')
+ goto yy282;
+ if (yych <= '>')
+ goto yy252;
+ if (yych <= '@')
+ goto yy231;
+ goto yy260;
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^')
+ goto yy231;
+ goto yy260;
+ } else {
+ if (yych <= '`')
+ goto yy231;
+ if (yych <= 'z')
+ goto yy260;
+ goto yy231;
+ }
+ }
+ }
+ yy282:
+ yych = *++p;
+ if (yybm[0 + yych] & 16) {
+ goto yy286;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '"') {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych <= ' ')
+ goto yy282;
+ goto yy288;
+ } else {
+ if (yych <= '\'')
+ goto yy290;
+ if (yych <= 0xC1)
+ goto yy231;
+ if (yych <= 0xDF)
+ goto yy292;
+ goto yy293;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy295;
+ goto yy294;
+ } else {
+ if (yych <= 0xF0)
+ goto yy296;
+ if (yych <= 0xF3)
+ goto yy297;
+ if (yych <= 0xF4)
+ goto yy298;
+ goto yy231;
+ }
+ }
+ yy284:
+ yych = *++p;
+ if (yybm[0 + yych] & 8) {
+ goto yy262;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych <= '-')
+ goto yy251;
+ goto yy231;
+ } else {
+ if (yych <= 0xDF)
+ goto yy265;
+ if (yych <= 0xE0)
+ goto yy266;
+ goto yy267;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy268;
+ if (yych <= 0xEF)
+ goto yy267;
+ goto yy269;
+ } else {
+ if (yych <= 0xF3)
+ goto yy270;
+ if (yych <= 0xF4)
+ goto yy271;
+ goto yy231;
+ }
+ }
+ yy285:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy299;
+ if (yych == 't')
+ goto yy299;
+ goto yy231;
+ yy286:
+ yych = *++p;
+ if (yybm[0 + yych] & 16) {
+ goto yy286;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '=') {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych <= ' ')
+ goto yy247;
+ goto yy231;
+ } else {
+ if (yych <= '>')
+ goto yy252;
+ if (yych <= 0xC1)
+ goto yy231;
+ if (yych <= 0xDF)
+ goto yy292;
+ goto yy293;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy295;
+ goto yy294;
+ } else {
+ if (yych <= 0xF0)
+ goto yy296;
+ if (yych <= 0xF3)
+ goto yy297;
+ if (yych <= 0xF4)
+ goto yy298;
+ goto yy231;
+ }
+ }
+ yy288:
+ yych = *++p;
+ if (yybm[0 + yych] & 32) {
+ goto yy288;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych <= '"')
+ goto yy300;
+ goto yy231;
+ } else {
+ if (yych <= 0xDF)
+ goto yy301;
+ if (yych <= 0xE0)
+ goto yy302;
+ goto yy303;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy304;
+ if (yych <= 0xEF)
+ goto yy303;
+ goto yy305;
+ } else {
+ if (yych <= 0xF3)
+ goto yy306;
+ if (yych <= 0xF4)
+ goto yy307;
+ goto yy231;
+ }
+ }
+ yy290:
+ yych = *++p;
+ if (yybm[0 + yych] & 64) {
+ goto yy290;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych <= '\'')
+ goto yy300;
+ goto yy231;
+ } else {
+ if (yych <= 0xDF)
+ goto yy308;
+ if (yych <= 0xE0)
+ goto yy309;
+ goto yy310;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy311;
+ if (yych <= 0xEF)
+ goto yy310;
+ goto yy312;
+ } else {
+ if (yych <= 0xF3)
+ goto yy313;
+ if (yych <= 0xF4)
+ goto yy314;
+ goto yy231;
+ }
+ }
+ yy292:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy286;
+ goto yy231;
+ yy293:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy292;
+ goto yy231;
+ yy294:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy292;
+ goto yy231;
+ yy295:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x9F)
+ goto yy292;
+ goto yy231;
+ yy296:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy294;
+ goto yy231;
+ yy297:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy294;
+ goto yy231;
+ yy298:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x8F)
+ goto yy294;
+ goto yy231;
+ yy299:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy315;
+ if (yych == 'a')
+ goto yy315;
+ goto yy231;
+ yy300:
+ yych = *++p;
+ if (yybm[0 + yych] & 1) {
+ goto yy247;
+ }
+ if (yych == '/')
+ goto yy251;
+ if (yych == '>')
+ goto yy252;
+ goto yy231;
+ yy301:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy288;
+ goto yy231;
+ yy302:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy301;
+ goto yy231;
+ yy303:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy301;
+ goto yy231;
+ yy304:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x9F)
+ goto yy301;
+ goto yy231;
+ yy305:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy303;
+ goto yy231;
+ yy306:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy303;
+ goto yy231;
+ yy307:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x8F)
+ goto yy303;
+ goto yy231;
+ yy308:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy290;
+ goto yy231;
+ yy309:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy308;
+ goto yy231;
+ yy310:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy308;
+ goto yy231;
+ yy311:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x9F)
+ goto yy308;
+ goto yy231;
+ yy312:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy310;
+ goto yy231;
+ yy313:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy310;
+ goto yy231;
+ yy314:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x8F)
+ goto yy310;
+ goto yy231;
+ yy315:
+ yych = *++p;
+ if (yych != '[')
+ goto yy231;
+ yy316:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy316;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych >= '^')
+ goto yy231;
+ } else {
+ if (yych <= 0xDF)
+ goto yy319;
+ if (yych <= 0xE0)
+ goto yy320;
+ goto yy321;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy322;
+ if (yych <= 0xEF)
+ goto yy321;
+ goto yy323;
+ } else {
+ if (yych <= 0xF3)
+ goto yy324;
+ if (yych <= 0xF4)
+ goto yy325;
+ goto yy231;
+ }
+ }
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy316;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych <= ']')
+ goto yy326;
+ goto yy231;
+ } else {
+ if (yych <= 0xDF)
+ goto yy319;
+ if (yych <= 0xE0)
+ goto yy320;
+ goto yy321;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy322;
+ if (yych <= 0xEF)
+ goto yy321;
+ goto yy323;
+ } else {
+ if (yych <= 0xF3)
+ goto yy324;
+ if (yych <= 0xF4)
+ goto yy325;
+ goto yy231;
+ }
+ }
+ yy319:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy316;
+ goto yy231;
+ yy320:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy319;
+ goto yy231;
+ yy321:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy319;
+ goto yy231;
+ yy322:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x9F)
+ goto yy319;
+ goto yy231;
+ yy323:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy321;
+ goto yy231;
+ yy324:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0xBF)
+ goto yy321;
+ goto yy231;
+ yy325:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy231;
+ if (yych <= 0x8F)
+ goto yy321;
+ goto yy231;
+ yy326:
+ yych = *++p;
+ if (yych <= 0xE0) {
+ if (yych <= '>') {
+ if (yych <= 0x00)
+ goto yy231;
+ if (yych <= '=')
+ goto yy316;
+ goto yy252;
+ } else {
+ if (yych <= 0x7F)
+ goto yy316;
+ if (yych <= 0xC1)
+ goto yy231;
+ if (yych <= 0xDF)
+ goto yy319;
+ goto yy320;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy322;
+ goto yy321;
+ } else {
+ if (yych <= 0xF0)
+ goto yy323;
+ if (yych <= 0xF3)
+ goto yy324;
+ if (yych <= 0xF4)
+ goto yy325;
+ goto yy231;
+ }
+ }
+ }
+}
+
+// Try to match an HTML block tag start line, returning
+// an integer code for the type of block (1-6, matching the spec).
+// #7 is handled by a separate function, below.
+bufsize_t _scan_html_block_start(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+
+ {
+ unsigned char yych;
+ yych = *p;
+ if (yych == '<')
+ goto yy331;
+ ++p;
+ yy330 : { return 0; }
+ yy331:
+ yych = *(marker = ++p);
+ switch (yych) {
+ case '!':
+ goto yy332;
+ case '/':
+ goto yy334;
+ case '?':
+ goto yy335;
+ case 'A':
+ case 'a':
+ goto yy337;
+ case 'B':
+ case 'b':
+ goto yy338;
+ case 'C':
+ case 'c':
+ goto yy339;
+ case 'D':
+ case 'd':
+ goto yy340;
+ case 'F':
+ case 'f':
+ goto yy341;
+ case 'H':
+ case 'h':
+ goto yy342;
+ case 'I':
+ case 'i':
+ goto yy343;
+ case 'L':
+ case 'l':
+ goto yy344;
+ case 'M':
+ case 'm':
+ goto yy345;
+ case 'N':
+ case 'n':
+ goto yy346;
+ case 'O':
+ case 'o':
+ goto yy347;
+ case 'P':
+ case 'p':
+ goto yy348;
+ case 'S':
+ case 's':
+ goto yy349;
+ case 'T':
+ case 't':
+ goto yy350;
+ case 'U':
+ case 'u':
+ goto yy351;
+ default:
+ goto yy330;
+ }
+ yy332:
+ yych = *++p;
+ if (yych <= '@') {
+ if (yych == '-')
+ goto yy352;
+ } else {
+ if (yych <= 'Z')
+ goto yy353;
+ if (yych <= '[')
+ goto yy355;
+ }
+ yy333:
+ p = marker;
+ goto yy330;
+ yy334:
+ yych = *++p;
+ switch (yych) {
+ case 'A':
+ case 'a':
+ goto yy337;
+ case 'B':
+ case 'b':
+ goto yy338;
+ case 'C':
+ case 'c':
+ goto yy339;
+ case 'D':
+ case 'd':
+ goto yy340;
+ case 'F':
+ case 'f':
+ goto yy341;
+ case 'H':
+ case 'h':
+ goto yy342;
+ case 'I':
+ case 'i':
+ goto yy343;
+ case 'L':
+ case 'l':
+ goto yy344;
+ case 'M':
+ case 'm':
+ goto yy345;
+ case 'N':
+ case 'n':
+ goto yy346;
+ case 'O':
+ case 'o':
+ goto yy347;
+ case 'P':
+ case 'p':
+ goto yy356;
+ case 'S':
+ case 's':
+ goto yy357;
+ case 'T':
+ case 't':
+ goto yy350;
+ case 'U':
+ case 'u':
+ goto yy351;
+ default:
+ goto yy333;
+ }
+ yy335:
+ ++p;
+ { return 3; }
+ yy337:
+ yych = *++p;
+ if (yych <= 'S') {
+ if (yych <= 'D') {
+ if (yych <= 'C')
+ goto yy333;
+ goto yy358;
+ } else {
+ if (yych <= 'Q')
+ goto yy333;
+ if (yych <= 'R')
+ goto yy359;
+ goto yy360;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych == 'd')
+ goto yy358;
+ goto yy333;
+ } else {
+ if (yych <= 'r')
+ goto yy359;
+ if (yych <= 's')
+ goto yy360;
+ goto yy333;
+ }
+ }
+ yy338:
+ yych = *++p;
+ if (yych <= 'O') {
+ if (yych <= 'K') {
+ if (yych == 'A')
+ goto yy361;
+ goto yy333;
+ } else {
+ if (yych <= 'L')
+ goto yy362;
+ if (yych <= 'N')
+ goto yy333;
+ goto yy363;
+ }
+ } else {
+ if (yych <= 'k') {
+ if (yych == 'a')
+ goto yy361;
+ goto yy333;
+ } else {
+ if (yych <= 'l')
+ goto yy362;
+ if (yych == 'o')
+ goto yy363;
+ goto yy333;
+ }
+ }
+ yy339:
+ yych = *++p;
+ if (yych <= 'O') {
+ if (yych <= 'D') {
+ if (yych == 'A')
+ goto yy364;
+ goto yy333;
+ } else {
+ if (yych <= 'E')
+ goto yy365;
+ if (yych <= 'N')
+ goto yy333;
+ goto yy366;
+ }
+ } else {
+ if (yych <= 'd') {
+ if (yych == 'a')
+ goto yy364;
+ goto yy333;
+ } else {
+ if (yych <= 'e')
+ goto yy365;
+ if (yych == 'o')
+ goto yy366;
+ goto yy333;
+ }
+ }
+ yy340:
+ yych = *++p;
+ switch (yych) {
+ case 'D':
+ case 'L':
+ case 'T':
+ case 'd':
+ case 'l':
+ case 't':
+ goto yy367;
+ case 'E':
+ case 'e':
+ goto yy368;
+ case 'I':
+ case 'i':
+ goto yy369;
+ default:
+ goto yy333;
+ }
+ yy341:
+ yych = *++p;
+ if (yych <= 'R') {
+ if (yych <= 'N') {
+ if (yych == 'I')
+ goto yy370;
+ goto yy333;
+ } else {
+ if (yych <= 'O')
+ goto yy371;
+ if (yych <= 'Q')
+ goto yy333;
+ goto yy372;
+ }
+ } else {
+ if (yych <= 'n') {
+ if (yych == 'i')
+ goto yy370;
+ goto yy333;
+ } else {
+ if (yych <= 'o')
+ goto yy371;
+ if (yych == 'r')
+ goto yy372;
+ goto yy333;
+ }
+ }
+ yy342:
+ yych = *++p;
+ if (yych <= 'S') {
+ if (yych <= 'D') {
+ if (yych <= '0')
+ goto yy333;
+ if (yych <= '6')
+ goto yy367;
+ goto yy333;
+ } else {
+ if (yych <= 'E')
+ goto yy373;
+ if (yych == 'R')
+ goto yy367;
+ goto yy333;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych <= 'T')
+ goto yy374;
+ if (yych == 'e')
+ goto yy373;
+ goto yy333;
+ } else {
+ if (yych <= 'r')
+ goto yy367;
+ if (yych == 't')
+ goto yy374;
+ goto yy333;
+ }
+ }
+ yy343:
+ yych = *++p;
+ if (yych == 'F')
+ goto yy375;
+ if (yych == 'f')
+ goto yy375;
+ goto yy333;
+ yy344:
+ yych = *++p;
+ if (yych <= 'I') {
+ if (yych == 'E')
+ goto yy376;
+ if (yych <= 'H')
+ goto yy333;
+ goto yy377;
+ } else {
+ if (yych <= 'e') {
+ if (yych <= 'd')
+ goto yy333;
+ goto yy376;
+ } else {
+ if (yych == 'i')
+ goto yy377;
+ goto yy333;
+ }
+ }
+ yy345:
+ yych = *++p;
+ if (yych <= 'E') {
+ if (yych == 'A')
+ goto yy378;
+ if (yych <= 'D')
+ goto yy333;
+ goto yy379;
+ } else {
+ if (yych <= 'a') {
+ if (yych <= '`')
+ goto yy333;
+ goto yy378;
+ } else {
+ if (yych == 'e')
+ goto yy379;
+ goto yy333;
+ }
+ }
+ yy346:
+ yych = *++p;
+ if (yych <= 'O') {
+ if (yych == 'A')
+ goto yy380;
+ if (yych <= 'N')
+ goto yy333;
+ goto yy381;
+ } else {
+ if (yych <= 'a') {
+ if (yych <= '`')
+ goto yy333;
+ goto yy380;
+ } else {
+ if (yych == 'o')
+ goto yy381;
+ goto yy333;
+ }
+ }
+ yy347:
+ yych = *++p;
+ if (yych <= 'P') {
+ if (yych == 'L')
+ goto yy367;
+ if (yych <= 'O')
+ goto yy333;
+ goto yy382;
+ } else {
+ if (yych <= 'l') {
+ if (yych <= 'k')
+ goto yy333;
+ goto yy367;
+ } else {
+ if (yych == 'p')
+ goto yy382;
+ goto yy333;
+ }
+ }
+ yy348:
+ yych = *++p;
+ if (yych <= '>') {
+ if (yych <= ' ') {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy383;
+ if (yych <= 0x1F)
+ goto yy333;
+ goto yy383;
+ } else {
+ if (yych == '/')
+ goto yy385;
+ if (yych <= '=')
+ goto yy333;
+ goto yy383;
+ }
+ } else {
+ if (yych <= 'R') {
+ if (yych == 'A')
+ goto yy386;
+ if (yych <= 'Q')
+ goto yy333;
+ goto yy387;
+ } else {
+ if (yych <= 'a') {
+ if (yych <= '`')
+ goto yy333;
+ goto yy386;
+ } else {
+ if (yych == 'r')
+ goto yy387;
+ goto yy333;
+ }
+ }
+ }
+ yy349:
+ yych = *++p;
+ switch (yych) {
+ case 'C':
+ case 'c':
+ goto yy388;
+ case 'E':
+ case 'e':
+ goto yy389;
+ case 'O':
+ case 'o':
+ goto yy390;
+ case 'T':
+ case 't':
+ goto yy391;
+ case 'U':
+ case 'u':
+ goto yy392;
+ default:
+ goto yy333;
+ }
+ yy350:
+ yych = *++p;
+ switch (yych) {
+ case 'A':
+ case 'a':
+ goto yy393;
+ case 'B':
+ case 'b':
+ goto yy394;
+ case 'D':
+ case 'd':
+ goto yy367;
+ case 'F':
+ case 'f':
+ goto yy395;
+ case 'H':
+ case 'h':
+ goto yy396;
+ case 'I':
+ case 'i':
+ goto yy397;
+ case 'R':
+ case 'r':
+ goto yy398;
+ default:
+ goto yy333;
+ }
+ yy351:
+ yych = *++p;
+ if (yych == 'L')
+ goto yy367;
+ if (yych == 'l')
+ goto yy367;
+ goto yy333;
+ yy352:
+ yych = *++p;
+ if (yych == '-')
+ goto yy399;
+ goto yy333;
+ yy353:
+ ++p;
+ { return 4; }
+ yy355:
+ yych = *++p;
+ if (yych == 'C')
+ goto yy401;
+ if (yych == 'c')
+ goto yy401;
+ goto yy333;
+ yy356:
+ yych = *++p;
+ if (yych <= '/') {
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= ' ')
+ goto yy383;
+ if (yych <= '.')
+ goto yy333;
+ goto yy385;
+ }
+ } else {
+ if (yych <= '@') {
+ if (yych == '>')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= 'A')
+ goto yy386;
+ if (yych == 'a')
+ goto yy386;
+ goto yy333;
+ }
+ }
+ yy357:
+ yych = *++p;
+ if (yych <= 'U') {
+ if (yych <= 'N') {
+ if (yych == 'E')
+ goto yy389;
+ goto yy333;
+ } else {
+ if (yych <= 'O')
+ goto yy390;
+ if (yych <= 'T')
+ goto yy333;
+ goto yy392;
+ }
+ } else {
+ if (yych <= 'n') {
+ if (yych == 'e')
+ goto yy389;
+ goto yy333;
+ } else {
+ if (yych <= 'o')
+ goto yy390;
+ if (yych == 'u')
+ goto yy392;
+ goto yy333;
+ }
+ }
+ yy358:
+ yych = *++p;
+ if (yych == 'D')
+ goto yy402;
+ if (yych == 'd')
+ goto yy402;
+ goto yy333;
+ yy359:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy403;
+ if (yych == 't')
+ goto yy403;
+ goto yy333;
+ yy360:
+ yych = *++p;
+ if (yych == 'I')
+ goto yy404;
+ if (yych == 'i')
+ goto yy404;
+ goto yy333;
+ yy361:
+ yych = *++p;
+ if (yych == 'S')
+ goto yy405;
+ if (yych == 's')
+ goto yy405;
+ goto yy333;
+ yy362:
+ yych = *++p;
+ if (yych == 'O')
+ goto yy406;
+ if (yych == 'o')
+ goto yy406;
+ goto yy333;
+ yy363:
+ yych = *++p;
+ if (yych == 'D')
+ goto yy407;
+ if (yych == 'd')
+ goto yy407;
+ goto yy333;
+ yy364:
+ yych = *++p;
+ if (yych == 'P')
+ goto yy408;
+ if (yych == 'p')
+ goto yy408;
+ goto yy333;
+ yy365:
+ yych = *++p;
+ if (yych == 'N')
+ goto yy409;
+ if (yych == 'n')
+ goto yy409;
+ goto yy333;
+ yy366:
+ yych = *++p;
+ if (yych == 'L')
+ goto yy410;
+ if (yych == 'l')
+ goto yy410;
+ goto yy333;
+ yy367:
+ yych = *++p;
+ if (yych <= ' ') {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy383;
+ if (yych <= 0x1F)
+ goto yy333;
+ goto yy383;
+ } else {
+ if (yych <= '/') {
+ if (yych <= '.')
+ goto yy333;
+ goto yy385;
+ } else {
+ if (yych == '>')
+ goto yy383;
+ goto yy333;
+ }
+ }
+ yy368:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy411;
+ if (yych == 't')
+ goto yy411;
+ goto yy333;
+ yy369:
+ yych = *++p;
+ if (yych <= 'V') {
+ if (yych <= 'Q') {
+ if (yych == 'A')
+ goto yy412;
+ goto yy333;
+ } else {
+ if (yych <= 'R')
+ goto yy367;
+ if (yych <= 'U')
+ goto yy333;
+ goto yy367;
+ }
+ } else {
+ if (yych <= 'q') {
+ if (yych == 'a')
+ goto yy412;
+ goto yy333;
+ } else {
+ if (yych <= 'r')
+ goto yy367;
+ if (yych == 'v')
+ goto yy367;
+ goto yy333;
+ }
+ }
+ yy370:
+ yych = *++p;
+ if (yych <= 'G') {
+ if (yych == 'E')
+ goto yy413;
+ if (yych <= 'F')
+ goto yy333;
+ goto yy414;
+ } else {
+ if (yych <= 'e') {
+ if (yych <= 'd')
+ goto yy333;
+ goto yy413;
+ } else {
+ if (yych == 'g')
+ goto yy414;
+ goto yy333;
+ }
+ }
+ yy371:
+ yych = *++p;
+ if (yych <= 'R') {
+ if (yych == 'O')
+ goto yy409;
+ if (yych <= 'Q')
+ goto yy333;
+ goto yy415;
+ } else {
+ if (yych <= 'o') {
+ if (yych <= 'n')
+ goto yy333;
+ goto yy409;
+ } else {
+ if (yych == 'r')
+ goto yy415;
+ goto yy333;
+ }
+ }
+ yy372:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy416;
+ if (yych == 'a')
+ goto yy416;
+ goto yy333;
+ yy373:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy417;
+ if (yych == 'a')
+ goto yy417;
+ goto yy333;
+ yy374:
+ yych = *++p;
+ if (yych == 'M')
+ goto yy351;
+ if (yych == 'm')
+ goto yy351;
+ goto yy333;
+ yy375:
+ yych = *++p;
+ if (yych == 'R')
+ goto yy418;
+ if (yych == 'r')
+ goto yy418;
+ goto yy333;
+ yy376:
+ yych = *++p;
+ if (yych == 'G')
+ goto yy419;
+ if (yych == 'g')
+ goto yy419;
+ goto yy333;
+ yy377:
+ yych = *++p;
+ if (yych <= '/') {
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= ' ')
+ goto yy383;
+ if (yych <= '.')
+ goto yy333;
+ goto yy385;
+ }
+ } else {
+ if (yych <= 'M') {
+ if (yych == '>')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= 'N')
+ goto yy420;
+ if (yych == 'n')
+ goto yy420;
+ goto yy333;
+ }
+ }
+ yy378:
+ yych = *++p;
+ if (yych == 'I')
+ goto yy421;
+ if (yych == 'i')
+ goto yy421;
+ goto yy333;
+ yy379:
+ yych = *++p;
+ if (yych == 'N')
+ goto yy422;
+ if (yych == 'n')
+ goto yy422;
+ goto yy333;
+ yy380:
+ yych = *++p;
+ if (yych == 'V')
+ goto yy367;
+ if (yych == 'v')
+ goto yy367;
+ goto yy333;
+ yy381:
+ yych = *++p;
+ if (yych == 'F')
+ goto yy423;
+ if (yych == 'f')
+ goto yy423;
+ goto yy333;
+ yy382:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy424;
+ if (yych == 't')
+ goto yy424;
+ goto yy333;
+ yy383:
+ ++p;
+ { return 6; }
+ yy385:
+ yych = *++p;
+ if (yych == '>')
+ goto yy383;
+ goto yy333;
+ yy386:
+ yych = *++p;
+ if (yych == 'R')
+ goto yy425;
+ if (yych == 'r')
+ goto yy425;
+ goto yy333;
+ yy387:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy426;
+ if (yych == 'e')
+ goto yy426;
+ goto yy333;
+ yy388:
+ yych = *++p;
+ if (yych == 'R')
+ goto yy427;
+ if (yych == 'r')
+ goto yy427;
+ goto yy333;
+ yy389:
+ yych = *++p;
+ if (yych == 'C')
+ goto yy408;
+ if (yych == 'c')
+ goto yy408;
+ goto yy333;
+ yy390:
+ yych = *++p;
+ if (yych == 'U')
+ goto yy428;
+ if (yych == 'u')
+ goto yy428;
+ goto yy333;
+ yy391:
+ yych = *++p;
+ if (yych == 'Y')
+ goto yy429;
+ if (yych == 'y')
+ goto yy429;
+ goto yy333;
+ yy392:
+ yych = *++p;
+ if (yych == 'M')
+ goto yy430;
+ if (yych == 'm')
+ goto yy430;
+ goto yy333;
+ yy393:
+ yych = *++p;
+ if (yych == 'B')
+ goto yy431;
+ if (yych == 'b')
+ goto yy431;
+ goto yy333;
+ yy394:
+ yych = *++p;
+ if (yych == 'O')
+ goto yy363;
+ if (yych == 'o')
+ goto yy363;
+ goto yy333;
+ yy395:
+ yych = *++p;
+ if (yych == 'O')
+ goto yy432;
+ if (yych == 'o')
+ goto yy432;
+ goto yy333;
+ yy396:
+ yych = *++p;
+ if (yych <= '/') {
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= ' ')
+ goto yy383;
+ if (yych <= '.')
+ goto yy333;
+ goto yy385;
+ }
+ } else {
+ if (yych <= 'D') {
+ if (yych == '>')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= 'E')
+ goto yy433;
+ if (yych == 'e')
+ goto yy433;
+ goto yy333;
+ }
+ }
+ yy397:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy431;
+ if (yych == 't')
+ goto yy431;
+ goto yy333;
+ yy398:
+ yych = *++p;
+ if (yych <= '/') {
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= ' ')
+ goto yy383;
+ if (yych <= '.')
+ goto yy333;
+ goto yy385;
+ }
+ } else {
+ if (yych <= '@') {
+ if (yych == '>')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= 'A')
+ goto yy434;
+ if (yych == 'a')
+ goto yy434;
+ goto yy333;
+ }
+ }
+ yy399:
+ ++p;
+ { return 2; }
+ yy401:
+ yych = *++p;
+ if (yych == 'D')
+ goto yy435;
+ if (yych == 'd')
+ goto yy435;
+ goto yy333;
+ yy402:
+ yych = *++p;
+ if (yych == 'R')
+ goto yy436;
+ if (yych == 'r')
+ goto yy436;
+ goto yy333;
+ yy403:
+ yych = *++p;
+ if (yych == 'I')
+ goto yy437;
+ if (yych == 'i')
+ goto yy437;
+ goto yy333;
+ yy404:
+ yych = *++p;
+ if (yych == 'D')
+ goto yy438;
+ if (yych == 'd')
+ goto yy438;
+ goto yy333;
+ yy405:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy439;
+ if (yych == 'e')
+ goto yy439;
+ goto yy333;
+ yy406:
+ yych = *++p;
+ if (yych == 'C')
+ goto yy440;
+ if (yych == 'c')
+ goto yy440;
+ goto yy333;
+ yy407:
+ yych = *++p;
+ if (yych == 'Y')
+ goto yy367;
+ if (yych == 'y')
+ goto yy367;
+ goto yy333;
+ yy408:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy441;
+ if (yych == 't')
+ goto yy441;
+ goto yy333;
+ yy409:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy442;
+ if (yych == 't')
+ goto yy442;
+ goto yy333;
+ yy410:
+ yych = *++p;
+ if (yych <= '/') {
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= ' ')
+ goto yy383;
+ if (yych <= '.')
+ goto yy333;
+ goto yy385;
+ }
+ } else {
+ if (yych <= 'F') {
+ if (yych == '>')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= 'G')
+ goto yy443;
+ if (yych == 'g')
+ goto yy443;
+ goto yy333;
+ }
+ }
+ yy411:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy444;
+ if (yych == 'a')
+ goto yy444;
+ goto yy333;
+ yy412:
+ yych = *++p;
+ if (yych == 'L')
+ goto yy445;
+ if (yych == 'l')
+ goto yy445;
+ goto yy333;
+ yy413:
+ yych = *++p;
+ if (yych == 'L')
+ goto yy446;
+ if (yych == 'l')
+ goto yy446;
+ goto yy333;
+ yy414:
+ yych = *++p;
+ if (yych <= 'U') {
+ if (yych == 'C')
+ goto yy447;
+ if (yych <= 'T')
+ goto yy333;
+ goto yy448;
+ } else {
+ if (yych <= 'c') {
+ if (yych <= 'b')
+ goto yy333;
+ goto yy447;
+ } else {
+ if (yych == 'u')
+ goto yy448;
+ goto yy333;
+ }
+ }
+ yy415:
+ yych = *++p;
+ if (yych == 'M')
+ goto yy367;
+ if (yych == 'm')
+ goto yy367;
+ goto yy333;
+ yy416:
+ yych = *++p;
+ if (yych == 'M')
+ goto yy449;
+ if (yych == 'm')
+ goto yy449;
+ goto yy333;
+ yy417:
+ yych = *++p;
+ if (yych == 'D')
+ goto yy450;
+ if (yych == 'd')
+ goto yy450;
+ goto yy333;
+ yy418:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy451;
+ if (yych == 'a')
+ goto yy451;
+ goto yy333;
+ yy419:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy452;
+ if (yych == 'e')
+ goto yy452;
+ goto yy333;
+ yy420:
+ yych = *++p;
+ if (yych == 'K')
+ goto yy367;
+ if (yych == 'k')
+ goto yy367;
+ goto yy333;
+ yy421:
+ yych = *++p;
+ if (yych == 'N')
+ goto yy367;
+ if (yych == 'n')
+ goto yy367;
+ goto yy333;
+ yy422:
+ yych = *++p;
+ if (yych == 'U')
+ goto yy453;
+ if (yych == 'u')
+ goto yy453;
+ goto yy333;
+ yy423:
+ yych = *++p;
+ if (yych == 'R')
+ goto yy454;
+ if (yych == 'r')
+ goto yy454;
+ goto yy333;
+ yy424:
+ yych = *++p;
+ if (yych <= 'I') {
+ if (yych == 'G')
+ goto yy443;
+ if (yych <= 'H')
+ goto yy333;
+ goto yy455;
+ } else {
+ if (yych <= 'g') {
+ if (yych <= 'f')
+ goto yy333;
+ goto yy443;
+ } else {
+ if (yych == 'i')
+ goto yy455;
+ goto yy333;
+ }
+ }
+ yy425:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy415;
+ if (yych == 'a')
+ goto yy415;
+ goto yy333;
+ yy426:
+ yych = *++p;
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy456;
+ goto yy333;
+ } else {
+ if (yych <= ' ')
+ goto yy456;
+ if (yych == '>')
+ goto yy456;
+ goto yy333;
+ }
+ yy427:
+ yych = *++p;
+ if (yych == 'I')
+ goto yy458;
+ if (yych == 'i')
+ goto yy458;
+ goto yy333;
+ yy428:
+ yych = *++p;
+ if (yych == 'R')
+ goto yy459;
+ if (yych == 'r')
+ goto yy459;
+ goto yy333;
+ yy429:
+ yych = *++p;
+ if (yych == 'L')
+ goto yy387;
+ if (yych == 'l')
+ goto yy387;
+ goto yy333;
+ yy430:
+ yych = *++p;
+ if (yych == 'M')
+ goto yy460;
+ if (yych == 'm')
+ goto yy460;
+ goto yy333;
+ yy431:
+ yych = *++p;
+ if (yych == 'L')
+ goto yy438;
+ if (yych == 'l')
+ goto yy438;
+ goto yy333;
+ yy432:
+ yych = *++p;
+ if (yych == 'O')
+ goto yy461;
+ if (yych == 'o')
+ goto yy461;
+ goto yy333;
+ yy433:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy462;
+ if (yych == 'a')
+ goto yy462;
+ goto yy333;
+ yy434:
+ yych = *++p;
+ if (yych == 'C')
+ goto yy420;
+ if (yych == 'c')
+ goto yy420;
+ goto yy333;
+ yy435:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy463;
+ if (yych == 'a')
+ goto yy463;
+ goto yy333;
+ yy436:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy464;
+ if (yych == 'e')
+ goto yy464;
+ goto yy333;
+ yy437:
+ yych = *++p;
+ if (yych == 'C')
+ goto yy431;
+ if (yych == 'c')
+ goto yy431;
+ goto yy333;
+ yy438:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy367;
+ if (yych == 'e')
+ goto yy367;
+ goto yy333;
+ yy439:
+ yych = *++p;
+ if (yych <= '/') {
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= ' ')
+ goto yy383;
+ if (yych <= '.')
+ goto yy333;
+ goto yy385;
+ }
+ } else {
+ if (yych <= 'E') {
+ if (yych == '>')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= 'F')
+ goto yy465;
+ if (yych == 'f')
+ goto yy465;
+ goto yy333;
+ }
+ }
+ yy440:
+ yych = *++p;
+ if (yych == 'K')
+ goto yy466;
+ if (yych == 'k')
+ goto yy466;
+ goto yy333;
+ yy441:
+ yych = *++p;
+ if (yych == 'I')
+ goto yy455;
+ if (yych == 'i')
+ goto yy455;
+ goto yy333;
+ yy442:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy467;
+ if (yych == 'e')
+ goto yy467;
+ goto yy333;
+ yy443:
+ yych = *++p;
+ if (yych == 'R')
+ goto yy468;
+ if (yych == 'r')
+ goto yy468;
+ goto yy333;
+ yy444:
+ yych = *++p;
+ if (yych == 'I')
+ goto yy469;
+ if (yych == 'i')
+ goto yy469;
+ goto yy333;
+ yy445:
+ yych = *++p;
+ if (yych == 'O')
+ goto yy470;
+ if (yych == 'o')
+ goto yy470;
+ goto yy333;
+ yy446:
+ yych = *++p;
+ if (yych == 'D')
+ goto yy471;
+ if (yych == 'd')
+ goto yy471;
+ goto yy333;
+ yy447:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy364;
+ if (yych == 'a')
+ goto yy364;
+ goto yy333;
+ yy448:
+ yych = *++p;
+ if (yych == 'R')
+ goto yy438;
+ if (yych == 'r')
+ goto yy438;
+ goto yy333;
+ yy449:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy472;
+ if (yych == 'e')
+ goto yy472;
+ goto yy333;
+ yy450:
+ yych = *++p;
+ if (yych <= '/') {
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= ' ')
+ goto yy383;
+ if (yych <= '.')
+ goto yy333;
+ goto yy385;
+ }
+ } else {
+ if (yych <= 'D') {
+ if (yych == '>')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= 'E')
+ goto yy467;
+ if (yych == 'e')
+ goto yy467;
+ goto yy333;
+ }
+ }
+ yy451:
+ yych = *++p;
+ if (yych == 'M')
+ goto yy438;
+ if (yych == 'm')
+ goto yy438;
+ goto yy333;
+ yy452:
+ yych = *++p;
+ if (yych == 'N')
+ goto yy462;
+ if (yych == 'n')
+ goto yy462;
+ goto yy333;
+ yy453:
+ yych = *++p;
+ if (yych <= '/') {
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= ' ')
+ goto yy383;
+ if (yych <= '.')
+ goto yy333;
+ goto yy385;
+ }
+ } else {
+ if (yych <= 'H') {
+ if (yych == '>')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= 'I')
+ goto yy473;
+ if (yych == 'i')
+ goto yy473;
+ goto yy333;
+ }
+ }
+ yy454:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy474;
+ if (yych == 'a')
+ goto yy474;
+ goto yy333;
+ yy455:
+ yych = *++p;
+ if (yych == 'O')
+ goto yy421;
+ if (yych == 'o')
+ goto yy421;
+ goto yy333;
+ yy456:
+ ++p;
+ { return 1; }
+ yy458:
+ yych = *++p;
+ if (yych == 'P')
+ goto yy475;
+ if (yych == 'p')
+ goto yy475;
+ goto yy333;
+ yy459:
+ yych = *++p;
+ if (yych == 'C')
+ goto yy438;
+ if (yych == 'c')
+ goto yy438;
+ goto yy333;
+ yy460:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy476;
+ if (yych == 'a')
+ goto yy476;
+ goto yy333;
+ yy461:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy367;
+ if (yych == 't')
+ goto yy367;
+ goto yy333;
+ yy462:
+ yych = *++p;
+ if (yych == 'D')
+ goto yy367;
+ if (yych == 'd')
+ goto yy367;
+ goto yy333;
+ yy463:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy477;
+ if (yych == 't')
+ goto yy477;
+ goto yy333;
+ yy464:
+ yych = *++p;
+ if (yych == 'S')
+ goto yy478;
+ if (yych == 's')
+ goto yy478;
+ goto yy333;
+ yy465:
+ yych = *++p;
+ if (yych == 'O')
+ goto yy479;
+ if (yych == 'o')
+ goto yy479;
+ goto yy333;
+ yy466:
+ yych = *++p;
+ if (yych == 'Q')
+ goto yy480;
+ if (yych == 'q')
+ goto yy480;
+ goto yy333;
+ yy467:
+ yych = *++p;
+ if (yych == 'R')
+ goto yy367;
+ if (yych == 'r')
+ goto yy367;
+ goto yy333;
+ yy468:
+ yych = *++p;
+ if (yych == 'O')
+ goto yy481;
+ if (yych == 'o')
+ goto yy481;
+ goto yy333;
+ yy469:
+ yych = *++p;
+ if (yych == 'L')
+ goto yy478;
+ if (yych == 'l')
+ goto yy478;
+ goto yy333;
+ yy470:
+ yych = *++p;
+ if (yych == 'G')
+ goto yy367;
+ if (yych == 'g')
+ goto yy367;
+ goto yy333;
+ yy471:
+ yych = *++p;
+ if (yych == 'S')
+ goto yy482;
+ if (yych == 's')
+ goto yy482;
+ goto yy333;
+ yy472:
+ yych = *++p;
+ if (yych <= '/') {
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy333;
+ if (yych <= '\r')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= ' ')
+ goto yy383;
+ if (yych <= '.')
+ goto yy333;
+ goto yy385;
+ }
+ } else {
+ if (yych <= 'R') {
+ if (yych == '>')
+ goto yy383;
+ goto yy333;
+ } else {
+ if (yych <= 'S')
+ goto yy482;
+ if (yych == 's')
+ goto yy482;
+ goto yy333;
+ }
+ }
+ yy473:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy483;
+ if (yych == 't')
+ goto yy483;
+ goto yy333;
+ yy474:
+ yych = *++p;
+ if (yych == 'M')
+ goto yy484;
+ if (yych == 'm')
+ goto yy484;
+ goto yy333;
+ yy475:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy426;
+ if (yych == 't')
+ goto yy426;
+ goto yy333;
+ yy476:
+ yych = *++p;
+ if (yych == 'R')
+ goto yy407;
+ if (yych == 'r')
+ goto yy407;
+ goto yy333;
+ yy477:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy485;
+ if (yych == 'a')
+ goto yy485;
+ goto yy333;
+ yy478:
+ yych = *++p;
+ if (yych == 'S')
+ goto yy367;
+ if (yych == 's')
+ goto yy367;
+ goto yy333;
+ yy479:
+ yych = *++p;
+ if (yych == 'N')
+ goto yy461;
+ if (yych == 'n')
+ goto yy461;
+ goto yy333;
+ yy480:
+ yych = *++p;
+ if (yych == 'U')
+ goto yy486;
+ if (yych == 'u')
+ goto yy486;
+ goto yy333;
+ yy481:
+ yych = *++p;
+ if (yych == 'U')
+ goto yy487;
+ if (yych == 'u')
+ goto yy487;
+ goto yy333;
+ yy482:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy461;
+ if (yych == 'e')
+ goto yy461;
+ goto yy333;
+ yy483:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy415;
+ if (yych == 'e')
+ goto yy415;
+ goto yy333;
+ yy484:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy478;
+ if (yych == 'e')
+ goto yy478;
+ goto yy333;
+ yy485:
+ yych = *++p;
+ if (yych == '[')
+ goto yy488;
+ goto yy333;
+ yy486:
+ yych = *++p;
+ if (yych == 'O')
+ goto yy490;
+ if (yych == 'o')
+ goto yy490;
+ goto yy333;
+ yy487:
+ yych = *++p;
+ if (yych == 'P')
+ goto yy367;
+ if (yych == 'p')
+ goto yy367;
+ goto yy333;
+ yy488:
+ ++p;
+ { return 5; }
+ yy490:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy438;
+ if (yych == 't')
+ goto yy438;
+ goto yy333;
+ }
+}
+
+// Try to match an HTML block tag start line of type 7, returning
+// 7 if successful, 0 if not.
+bufsize_t _scan_html_block_start_7(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+
+ {
+ unsigned char yych;
+ unsigned int yyaccept = 0;
+ static const unsigned char yybm[] = {
+ 0, 224, 224, 224, 224, 224, 224, 224, 224, 198, 210, 194, 198, 194,
+ 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
+ 224, 224, 224, 224, 198, 224, 128, 224, 224, 224, 224, 64, 224, 224,
+ 224, 224, 224, 233, 232, 224, 233, 233, 233, 233, 233, 233, 233, 233,
+ 233, 233, 232, 224, 192, 192, 192, 224, 224, 233, 233, 233, 233, 233,
+ 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
+ 233, 233, 233, 233, 233, 233, 233, 224, 224, 224, 224, 232, 192, 233,
+ 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
+ 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 224, 224, 224,
+ 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych == '<')
+ goto yy495;
+ ++p;
+ yy494 : { return 0; }
+ yy495:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= '@') {
+ if (yych != '/')
+ goto yy494;
+ } else {
+ if (yych <= 'Z')
+ goto yy498;
+ if (yych <= '`')
+ goto yy494;
+ if (yych <= 'z')
+ goto yy498;
+ goto yy494;
+ }
+ yych = *++p;
+ if (yych <= '@')
+ goto yy497;
+ if (yych <= 'Z')
+ goto yy500;
+ if (yych <= '`')
+ goto yy497;
+ if (yych <= 'z')
+ goto yy500;
+ yy497:
+ p = marker;
+ if (yyaccept == 0) {
+ goto yy494;
+ } else {
+ goto yy513;
+ }
+ yy498:
+ yych = *++p;
+ if (yybm[0 + yych] & 2) {
+ goto yy502;
+ }
+ if (yych <= '=') {
+ if (yych <= '.') {
+ if (yych == '-')
+ goto yy498;
+ goto yy497;
+ } else {
+ if (yych <= '/')
+ goto yy504;
+ if (yych <= '9')
+ goto yy498;
+ goto yy497;
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '>')
+ goto yy505;
+ if (yych <= '@')
+ goto yy497;
+ goto yy498;
+ } else {
+ if (yych <= '`')
+ goto yy497;
+ if (yych <= 'z')
+ goto yy498;
+ goto yy497;
+ }
+ }
+ yy500:
+ yych = *++p;
+ if (yych <= '/') {
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy497;
+ if (yych <= '\r')
+ goto yy507;
+ goto yy497;
+ } else {
+ if (yych <= ' ')
+ goto yy507;
+ if (yych == '-')
+ goto yy500;
+ goto yy497;
+ }
+ } else {
+ if (yych <= '@') {
+ if (yych <= '9')
+ goto yy500;
+ if (yych == '>')
+ goto yy505;
+ goto yy497;
+ } else {
+ if (yych <= 'Z')
+ goto yy500;
+ if (yych <= '`')
+ goto yy497;
+ if (yych <= 'z')
+ goto yy500;
+ goto yy497;
+ }
+ }
+ yy502:
+ yych = *++p;
+ if (yybm[0 + yych] & 2) {
+ goto yy502;
+ }
+ if (yych <= '>') {
+ if (yych <= '9') {
+ if (yych != '/')
+ goto yy497;
+ } else {
+ if (yych <= ':')
+ goto yy509;
+ if (yych <= '=')
+ goto yy497;
+ goto yy505;
+ }
+ } else {
+ if (yych <= '^') {
+ if (yych <= '@')
+ goto yy497;
+ if (yych <= 'Z')
+ goto yy509;
+ goto yy497;
+ } else {
+ if (yych == '`')
+ goto yy497;
+ if (yych <= 'z')
+ goto yy509;
+ goto yy497;
+ }
+ }
+ yy504:
+ yych = *++p;
+ if (yych != '>')
+ goto yy497;
+ yy505:
+ yych = *++p;
+ if (yybm[0 + yych] & 4) {
+ goto yy505;
+ }
+ if (yych <= 0x08)
+ goto yy497;
+ if (yych <= '\n')
+ goto yy511;
+ if (yych <= '\v')
+ goto yy497;
+ if (yych <= '\r')
+ goto yy514;
+ goto yy497;
+ yy507:
+ yych = *++p;
+ if (yych <= 0x1F) {
+ if (yych <= 0x08)
+ goto yy497;
+ if (yych <= '\r')
+ goto yy507;
+ goto yy497;
+ } else {
+ if (yych <= ' ')
+ goto yy507;
+ if (yych == '>')
+ goto yy505;
+ goto yy497;
+ }
+ yy509:
+ yych = *++p;
+ if (yybm[0 + yych] & 8) {
+ goto yy509;
+ }
+ if (yych <= ',') {
+ if (yych <= '\r') {
+ if (yych <= 0x08)
+ goto yy497;
+ goto yy515;
+ } else {
+ if (yych == ' ')
+ goto yy515;
+ goto yy497;
+ }
+ } else {
+ if (yych <= '<') {
+ if (yych <= '/')
+ goto yy504;
+ goto yy497;
+ } else {
+ if (yych <= '=')
+ goto yy517;
+ if (yych <= '>')
+ goto yy505;
+ goto yy497;
+ }
+ }
+ yy511:
+ yyaccept = 1;
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 4) {
+ goto yy505;
+ }
+ if (yych <= 0x08)
+ goto yy513;
+ if (yych <= '\n')
+ goto yy511;
+ if (yych <= '\v')
+ goto yy513;
+ if (yych <= '\r')
+ goto yy514;
+ yy513 : { return 7; }
+ yy514:
+ ++p;
+ goto yy513;
+ yy515:
+ yych = *++p;
+ if (yych <= '<') {
+ if (yych <= ' ') {
+ if (yych <= 0x08)
+ goto yy497;
+ if (yych <= '\r')
+ goto yy515;
+ if (yych <= 0x1F)
+ goto yy497;
+ goto yy515;
+ } else {
+ if (yych <= '/') {
+ if (yych <= '.')
+ goto yy497;
+ goto yy504;
+ } else {
+ if (yych == ':')
+ goto yy509;
+ goto yy497;
+ }
+ }
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '=')
+ goto yy517;
+ if (yych <= '>')
+ goto yy505;
+ if (yych <= '@')
+ goto yy497;
+ goto yy509;
+ } else {
+ if (yych <= '_') {
+ if (yych <= '^')
+ goto yy497;
+ goto yy509;
+ } else {
+ if (yych <= '`')
+ goto yy497;
+ if (yych <= 'z')
+ goto yy509;
+ goto yy497;
+ }
+ }
+ }
+ yy517:
+ yych = *++p;
+ if (yybm[0 + yych] & 32) {
+ goto yy519;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '"') {
+ if (yych <= 0x00)
+ goto yy497;
+ if (yych <= ' ')
+ goto yy517;
+ goto yy521;
+ } else {
+ if (yych <= '\'')
+ goto yy523;
+ if (yych <= 0xC1)
+ goto yy497;
+ if (yych <= 0xDF)
+ goto yy525;
+ goto yy526;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy528;
+ goto yy527;
+ } else {
+ if (yych <= 0xF0)
+ goto yy529;
+ if (yych <= 0xF3)
+ goto yy530;
+ if (yych <= 0xF4)
+ goto yy531;
+ goto yy497;
+ }
+ }
+ yy519:
+ yych = *++p;
+ if (yybm[0 + yych] & 32) {
+ goto yy519;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '=') {
+ if (yych <= 0x00)
+ goto yy497;
+ if (yych <= ' ')
+ goto yy502;
+ goto yy497;
+ } else {
+ if (yych <= '>')
+ goto yy505;
+ if (yych <= 0xC1)
+ goto yy497;
+ if (yych <= 0xDF)
+ goto yy525;
+ goto yy526;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy528;
+ goto yy527;
+ } else {
+ if (yych <= 0xF0)
+ goto yy529;
+ if (yych <= 0xF3)
+ goto yy530;
+ if (yych <= 0xF4)
+ goto yy531;
+ goto yy497;
+ }
+ }
+ yy521:
+ yych = *++p;
+ if (yybm[0 + yych] & 64) {
+ goto yy521;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy497;
+ if (yych <= '"')
+ goto yy532;
+ goto yy497;
+ } else {
+ if (yych <= 0xDF)
+ goto yy533;
+ if (yych <= 0xE0)
+ goto yy534;
+ goto yy535;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy536;
+ if (yych <= 0xEF)
+ goto yy535;
+ goto yy537;
+ } else {
+ if (yych <= 0xF3)
+ goto yy538;
+ if (yych <= 0xF4)
+ goto yy539;
+ goto yy497;
+ }
+ }
+ yy523:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy523;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy497;
+ if (yych <= '\'')
+ goto yy532;
+ goto yy497;
+ } else {
+ if (yych <= 0xDF)
+ goto yy540;
+ if (yych <= 0xE0)
+ goto yy541;
+ goto yy542;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy543;
+ if (yych <= 0xEF)
+ goto yy542;
+ goto yy544;
+ } else {
+ if (yych <= 0xF3)
+ goto yy545;
+ if (yych <= 0xF4)
+ goto yy546;
+ goto yy497;
+ }
+ }
+ yy525:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy519;
+ goto yy497;
+ yy526:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy525;
+ goto yy497;
+ yy527:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy525;
+ goto yy497;
+ yy528:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0x9F)
+ goto yy525;
+ goto yy497;
+ yy529:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy527;
+ goto yy497;
+ yy530:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy527;
+ goto yy497;
+ yy531:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0x8F)
+ goto yy527;
+ goto yy497;
+ yy532:
+ yych = *++p;
+ if (yybm[0 + yych] & 2) {
+ goto yy502;
+ }
+ if (yych == '/')
+ goto yy504;
+ if (yych == '>')
+ goto yy505;
+ goto yy497;
+ yy533:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy521;
+ goto yy497;
+ yy534:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy533;
+ goto yy497;
+ yy535:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy533;
+ goto yy497;
+ yy536:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0x9F)
+ goto yy533;
+ goto yy497;
+ yy537:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy535;
+ goto yy497;
+ yy538:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy535;
+ goto yy497;
+ yy539:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0x8F)
+ goto yy535;
+ goto yy497;
+ yy540:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy523;
+ goto yy497;
+ yy541:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy540;
+ goto yy497;
+ yy542:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy540;
+ goto yy497;
+ yy543:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0x9F)
+ goto yy540;
+ goto yy497;
+ yy544:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy542;
+ goto yy497;
+ yy545:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0xBF)
+ goto yy542;
+ goto yy497;
+ yy546:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy497;
+ if (yych <= 0x8F)
+ goto yy542;
+ goto yy497;
+ }
+}
+
+// Try to match an HTML block end line of type 1
+bufsize_t _scan_html_block_end_1(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ unsigned int yyaccept = 0;
+ static const unsigned char yybm[] = {
+ 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych <= 0xDF) {
+ if (yych <= ';') {
+ if (yych <= 0x00)
+ goto yy549;
+ if (yych != '\n')
+ goto yy551;
+ } else {
+ if (yych <= '<')
+ goto yy552;
+ if (yych <= 0x7F)
+ goto yy551;
+ if (yych >= 0xC2)
+ goto yy553;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych <= 0xE0)
+ goto yy554;
+ if (yych == 0xED)
+ goto yy556;
+ goto yy555;
+ } else {
+ if (yych <= 0xF0)
+ goto yy557;
+ if (yych <= 0xF3)
+ goto yy558;
+ if (yych <= 0xF4)
+ goto yy559;
+ }
+ }
+ yy549:
+ ++p;
+ yy550 : { return 0; }
+ yy551:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= '\n') {
+ if (yych <= 0x00)
+ goto yy550;
+ if (yych <= '\t')
+ goto yy561;
+ goto yy550;
+ } else {
+ if (yych <= 0x7F)
+ goto yy561;
+ if (yych <= 0xC1)
+ goto yy550;
+ if (yych <= 0xF4)
+ goto yy561;
+ goto yy550;
+ }
+ yy552:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= '.') {
+ if (yych <= 0x00)
+ goto yy550;
+ if (yych == '\n')
+ goto yy550;
+ goto yy561;
+ } else {
+ if (yych <= 0x7F) {
+ if (yych <= '/')
+ goto yy572;
+ goto yy561;
+ } else {
+ if (yych <= 0xC1)
+ goto yy550;
+ if (yych <= 0xF4)
+ goto yy561;
+ goto yy550;
+ }
+ }
+ yy553:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy550;
+ if (yych <= 0xBF)
+ goto yy560;
+ goto yy550;
+ yy554:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x9F)
+ goto yy550;
+ if (yych <= 0xBF)
+ goto yy565;
+ goto yy550;
+ yy555:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy550;
+ if (yych <= 0xBF)
+ goto yy565;
+ goto yy550;
+ yy556:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy550;
+ if (yych <= 0x9F)
+ goto yy565;
+ goto yy550;
+ yy557:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x8F)
+ goto yy550;
+ if (yych <= 0xBF)
+ goto yy567;
+ goto yy550;
+ yy558:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy550;
+ if (yych <= 0xBF)
+ goto yy567;
+ goto yy550;
+ yy559:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy550;
+ if (yych <= 0x8F)
+ goto yy567;
+ goto yy550;
+ yy560:
+ yych = *++p;
+ yy561:
+ if (yybm[0 + yych] & 64) {
+ goto yy560;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy562;
+ if (yych <= '<')
+ goto yy563;
+ } else {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ goto yy567;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy568;
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ }
+ }
+ yy562:
+ p = marker;
+ if (yyaccept == 0) {
+ goto yy550;
+ } else {
+ goto yy582;
+ }
+ yy563:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 0xDF) {
+ if (yych <= '.') {
+ if (yych <= 0x00)
+ goto yy562;
+ if (yych == '\n')
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= '/')
+ goto yy572;
+ if (yych <= 0x7F)
+ goto yy560;
+ if (yych <= 0xC1)
+ goto yy562;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych <= 0xE0)
+ goto yy566;
+ if (yych == 0xED)
+ goto yy568;
+ goto yy567;
+ } else {
+ if (yych <= 0xF0)
+ goto yy569;
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ yy565:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy562;
+ if (yych <= 0xBF)
+ goto yy560;
+ goto yy562;
+ yy566:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy562;
+ if (yych <= 0xBF)
+ goto yy565;
+ goto yy562;
+ yy567:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy562;
+ if (yych <= 0xBF)
+ goto yy565;
+ goto yy562;
+ yy568:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy562;
+ if (yych <= 0x9F)
+ goto yy565;
+ goto yy562;
+ yy569:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy562;
+ if (yych <= 0xBF)
+ goto yy567;
+ goto yy562;
+ yy570:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy562;
+ if (yych <= 0xBF)
+ goto yy567;
+ goto yy562;
+ yy571:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy562;
+ if (yych <= 0x8F)
+ goto yy567;
+ goto yy562;
+ yy572:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 's') {
+ if (yych <= 'P') {
+ if (yych <= '\t') {
+ if (yych <= 0x00)
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= '\n')
+ goto yy562;
+ if (yych <= 'O')
+ goto yy560;
+ }
+ } else {
+ if (yych <= 'o') {
+ if (yych == 'S')
+ goto yy574;
+ goto yy560;
+ } else {
+ if (yych <= 'p')
+ goto yy573;
+ if (yych <= 'r')
+ goto yy560;
+ goto yy574;
+ }
+ }
+ } else {
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x7F)
+ goto yy560;
+ goto yy562;
+ } else {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ goto yy567;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy568;
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ }
+ yy573:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 0xC1) {
+ if (yych <= 'Q') {
+ if (yych <= 0x00)
+ goto yy562;
+ if (yych == '\n')
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= 'q') {
+ if (yych <= 'R')
+ goto yy575;
+ goto yy560;
+ } else {
+ if (yych <= 'r')
+ goto yy575;
+ if (yych <= 0x7F)
+ goto yy560;
+ goto yy562;
+ }
+ }
+ } else {
+ if (yych <= 0xED) {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ if (yych <= 0xEC)
+ goto yy567;
+ goto yy568;
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ }
+ yy574:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 't') {
+ if (yych <= 'C') {
+ if (yych <= '\t') {
+ if (yych <= 0x00)
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= '\n')
+ goto yy562;
+ if (yych <= 'B')
+ goto yy560;
+ goto yy576;
+ }
+ } else {
+ if (yych <= 'b') {
+ if (yych == 'T')
+ goto yy577;
+ goto yy560;
+ } else {
+ if (yych <= 'c')
+ goto yy576;
+ if (yych <= 's')
+ goto yy560;
+ goto yy577;
+ }
+ }
+ } else {
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x7F)
+ goto yy560;
+ goto yy562;
+ } else {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ goto yy567;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy568;
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ }
+ yy575:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 0xC1) {
+ if (yych <= 'D') {
+ if (yych <= 0x00)
+ goto yy562;
+ if (yych == '\n')
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= 'd') {
+ if (yych <= 'E')
+ goto yy578;
+ goto yy560;
+ } else {
+ if (yych <= 'e')
+ goto yy578;
+ if (yych <= 0x7F)
+ goto yy560;
+ goto yy562;
+ }
+ }
+ } else {
+ if (yych <= 0xED) {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ if (yych <= 0xEC)
+ goto yy567;
+ goto yy568;
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ }
+ yy576:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 0xC1) {
+ if (yych <= 'Q') {
+ if (yych <= 0x00)
+ goto yy562;
+ if (yych == '\n')
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= 'q') {
+ if (yych <= 'R')
+ goto yy579;
+ goto yy560;
+ } else {
+ if (yych <= 'r')
+ goto yy579;
+ if (yych <= 0x7F)
+ goto yy560;
+ goto yy562;
+ }
+ }
+ } else {
+ if (yych <= 0xED) {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ if (yych <= 0xEC)
+ goto yy567;
+ goto yy568;
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ }
+ yy577:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 0xC1) {
+ if (yych <= 'X') {
+ if (yych <= 0x00)
+ goto yy562;
+ if (yych == '\n')
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= 'x') {
+ if (yych <= 'Y')
+ goto yy580;
+ goto yy560;
+ } else {
+ if (yych <= 'y')
+ goto yy580;
+ if (yych <= 0x7F)
+ goto yy560;
+ goto yy562;
+ }
+ }
+ } else {
+ if (yych <= 0xED) {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ if (yych <= 0xEC)
+ goto yy567;
+ goto yy568;
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ }
+ yy578:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 0xDF) {
+ if (yych <= '=') {
+ if (yych <= 0x00)
+ goto yy562;
+ if (yych == '\n')
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= '>')
+ goto yy581;
+ if (yych <= 0x7F)
+ goto yy560;
+ if (yych <= 0xC1)
+ goto yy562;
+ goto yy565;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych <= 0xE0)
+ goto yy566;
+ if (yych == 0xED)
+ goto yy568;
+ goto yy567;
+ } else {
+ if (yych <= 0xF0)
+ goto yy569;
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ yy579:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 0xC1) {
+ if (yych <= 'H') {
+ if (yych <= 0x00)
+ goto yy562;
+ if (yych == '\n')
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= 'h') {
+ if (yych <= 'I')
+ goto yy583;
+ goto yy560;
+ } else {
+ if (yych <= 'i')
+ goto yy583;
+ if (yych <= 0x7F)
+ goto yy560;
+ goto yy562;
+ }
+ }
+ } else {
+ if (yych <= 0xED) {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ if (yych <= 0xEC)
+ goto yy567;
+ goto yy568;
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ }
+ yy580:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 0xC1) {
+ if (yych <= 'K') {
+ if (yych <= 0x00)
+ goto yy562;
+ if (yych == '\n')
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= 'k') {
+ if (yych <= 'L')
+ goto yy575;
+ goto yy560;
+ } else {
+ if (yych <= 'l')
+ goto yy575;
+ if (yych <= 0x7F)
+ goto yy560;
+ goto yy562;
+ }
+ }
+ } else {
+ if (yych <= 0xED) {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ if (yych <= 0xEC)
+ goto yy567;
+ goto yy568;
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ }
+ yy581:
+ yyaccept = 1;
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 64) {
+ goto yy560;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy582;
+ if (yych <= '<')
+ goto yy563;
+ } else {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ goto yy567;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy568;
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ }
+ }
+ yy582 : { return (bufsize_t)(p - start); }
+ yy583:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 0xC1) {
+ if (yych <= 'O') {
+ if (yych <= 0x00)
+ goto yy562;
+ if (yych == '\n')
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= 'o') {
+ if (yych >= 'Q')
+ goto yy560;
+ } else {
+ if (yych <= 'p')
+ goto yy584;
+ if (yych <= 0x7F)
+ goto yy560;
+ goto yy562;
+ }
+ }
+ } else {
+ if (yych <= 0xED) {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ if (yych <= 0xEC)
+ goto yy567;
+ goto yy568;
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ }
+ yy584:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy563;
+ }
+ if (yych <= 0xC1) {
+ if (yych <= 'S') {
+ if (yych <= 0x00)
+ goto yy562;
+ if (yych == '\n')
+ goto yy562;
+ goto yy560;
+ } else {
+ if (yych <= 's') {
+ if (yych <= 'T')
+ goto yy578;
+ goto yy560;
+ } else {
+ if (yych <= 't')
+ goto yy578;
+ if (yych <= 0x7F)
+ goto yy560;
+ goto yy562;
+ }
+ }
+ } else {
+ if (yych <= 0xED) {
+ if (yych <= 0xDF)
+ goto yy565;
+ if (yych <= 0xE0)
+ goto yy566;
+ if (yych <= 0xEC)
+ goto yy567;
+ goto yy568;
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xEF)
+ goto yy567;
+ goto yy569;
+ } else {
+ if (yych <= 0xF3)
+ goto yy570;
+ if (yych <= 0xF4)
+ goto yy571;
+ goto yy562;
+ }
+ }
+ }
+ }
+}
+
+// Try to match an HTML block end line of type 2
+bufsize_t _scan_html_block_end_2(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ unsigned int yyaccept = 0;
+ static const unsigned char yybm[] = {
+ 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych <= 0xDF) {
+ if (yych <= ',') {
+ if (yych <= 0x00)
+ goto yy587;
+ if (yych != '\n')
+ goto yy589;
+ } else {
+ if (yych <= '-')
+ goto yy590;
+ if (yych <= 0x7F)
+ goto yy589;
+ if (yych >= 0xC2)
+ goto yy591;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych <= 0xE0)
+ goto yy592;
+ if (yych == 0xED)
+ goto yy594;
+ goto yy593;
+ } else {
+ if (yych <= 0xF0)
+ goto yy595;
+ if (yych <= 0xF3)
+ goto yy596;
+ if (yych <= 0xF4)
+ goto yy597;
+ }
+ }
+ yy587:
+ ++p;
+ yy588 : { return 0; }
+ yy589:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= '\n') {
+ if (yych <= 0x00)
+ goto yy588;
+ if (yych <= '\t')
+ goto yy599;
+ goto yy588;
+ } else {
+ if (yych <= 0x7F)
+ goto yy599;
+ if (yych <= 0xC1)
+ goto yy588;
+ if (yych <= 0xF4)
+ goto yy599;
+ goto yy588;
+ }
+ yy590:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 128) {
+ goto yy609;
+ }
+ if (yych <= '\n') {
+ if (yych <= 0x00)
+ goto yy588;
+ if (yych <= '\t')
+ goto yy599;
+ goto yy588;
+ } else {
+ if (yych <= 0x7F)
+ goto yy599;
+ if (yych <= 0xC1)
+ goto yy588;
+ if (yych <= 0xF4)
+ goto yy599;
+ goto yy588;
+ }
+ yy591:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy588;
+ if (yych <= 0xBF)
+ goto yy598;
+ goto yy588;
+ yy592:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x9F)
+ goto yy588;
+ if (yych <= 0xBF)
+ goto yy602;
+ goto yy588;
+ yy593:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy588;
+ if (yych <= 0xBF)
+ goto yy602;
+ goto yy588;
+ yy594:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy588;
+ if (yych <= 0x9F)
+ goto yy602;
+ goto yy588;
+ yy595:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x8F)
+ goto yy588;
+ if (yych <= 0xBF)
+ goto yy604;
+ goto yy588;
+ yy596:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy588;
+ if (yych <= 0xBF)
+ goto yy604;
+ goto yy588;
+ yy597:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy588;
+ if (yych <= 0x8F)
+ goto yy604;
+ goto yy588;
+ yy598:
+ yych = *++p;
+ yy599:
+ if (yybm[0 + yych] & 64) {
+ goto yy598;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy600;
+ if (yych <= '-')
+ goto yy601;
+ } else {
+ if (yych <= 0xDF)
+ goto yy602;
+ if (yych <= 0xE0)
+ goto yy603;
+ goto yy604;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy605;
+ if (yych <= 0xEF)
+ goto yy604;
+ goto yy606;
+ } else {
+ if (yych <= 0xF3)
+ goto yy607;
+ if (yych <= 0xF4)
+ goto yy608;
+ }
+ }
+ yy600:
+ p = marker;
+ if (yyaccept == 0) {
+ goto yy588;
+ } else {
+ goto yy612;
+ }
+ yy601:
+ yych = *++p;
+ if (yybm[0 + yych] & 64) {
+ goto yy598;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy600;
+ if (yych <= '-')
+ goto yy609;
+ goto yy600;
+ } else {
+ if (yych <= 0xDF)
+ goto yy602;
+ if (yych <= 0xE0)
+ goto yy603;
+ goto yy604;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy605;
+ if (yych <= 0xEF)
+ goto yy604;
+ goto yy606;
+ } else {
+ if (yych <= 0xF3)
+ goto yy607;
+ if (yych <= 0xF4)
+ goto yy608;
+ goto yy600;
+ }
+ }
+ yy602:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy600;
+ if (yych <= 0xBF)
+ goto yy598;
+ goto yy600;
+ yy603:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy600;
+ if (yych <= 0xBF)
+ goto yy602;
+ goto yy600;
+ yy604:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy600;
+ if (yych <= 0xBF)
+ goto yy602;
+ goto yy600;
+ yy605:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy600;
+ if (yych <= 0x9F)
+ goto yy602;
+ goto yy600;
+ yy606:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy600;
+ if (yych <= 0xBF)
+ goto yy604;
+ goto yy600;
+ yy607:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy600;
+ if (yych <= 0xBF)
+ goto yy604;
+ goto yy600;
+ yy608:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy600;
+ if (yych <= 0x8F)
+ goto yy604;
+ goto yy600;
+ yy609:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy609;
+ }
+ if (yych <= 0xDF) {
+ if (yych <= '=') {
+ if (yych <= 0x00)
+ goto yy600;
+ if (yych == '\n')
+ goto yy600;
+ goto yy598;
+ } else {
+ if (yych <= '>')
+ goto yy611;
+ if (yych <= 0x7F)
+ goto yy598;
+ if (yych <= 0xC1)
+ goto yy600;
+ goto yy602;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych <= 0xE0)
+ goto yy603;
+ if (yych == 0xED)
+ goto yy605;
+ goto yy604;
+ } else {
+ if (yych <= 0xF0)
+ goto yy606;
+ if (yych <= 0xF3)
+ goto yy607;
+ if (yych <= 0xF4)
+ goto yy608;
+ goto yy600;
+ }
+ }
+ yy611:
+ yyaccept = 1;
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 64) {
+ goto yy598;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy612;
+ if (yych <= '-')
+ goto yy601;
+ } else {
+ if (yych <= 0xDF)
+ goto yy602;
+ if (yych <= 0xE0)
+ goto yy603;
+ goto yy604;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy605;
+ if (yych <= 0xEF)
+ goto yy604;
+ goto yy606;
+ } else {
+ if (yych <= 0xF3)
+ goto yy607;
+ if (yych <= 0xF4)
+ goto yy608;
+ }
+ }
+ yy612 : { return (bufsize_t)(p - start); }
+ }
+}
+
+// Try to match an HTML block end line of type 3
+bufsize_t _scan_html_block_end_3(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ unsigned int yyaccept = 0;
+ static const unsigned char yybm[] = {
+ 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych <= 0xDF) {
+ if (yych <= '>') {
+ if (yych <= 0x00)
+ goto yy615;
+ if (yych != '\n')
+ goto yy617;
+ } else {
+ if (yych <= '?')
+ goto yy618;
+ if (yych <= 0x7F)
+ goto yy617;
+ if (yych >= 0xC2)
+ goto yy619;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych <= 0xE0)
+ goto yy620;
+ if (yych == 0xED)
+ goto yy622;
+ goto yy621;
+ } else {
+ if (yych <= 0xF0)
+ goto yy623;
+ if (yych <= 0xF3)
+ goto yy624;
+ if (yych <= 0xF4)
+ goto yy625;
+ }
+ }
+ yy615:
+ ++p;
+ yy616 : { return 0; }
+ yy617:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= '\n') {
+ if (yych <= 0x00)
+ goto yy616;
+ if (yych <= '\t')
+ goto yy627;
+ goto yy616;
+ } else {
+ if (yych <= 0x7F)
+ goto yy627;
+ if (yych <= 0xC1)
+ goto yy616;
+ if (yych <= 0xF4)
+ goto yy627;
+ goto yy616;
+ }
+ yy618:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= '=') {
+ if (yych <= 0x00)
+ goto yy616;
+ if (yych == '\n')
+ goto yy616;
+ goto yy627;
+ } else {
+ if (yych <= 0x7F) {
+ if (yych <= '>')
+ goto yy638;
+ goto yy627;
+ } else {
+ if (yych <= 0xC1)
+ goto yy616;
+ if (yych <= 0xF4)
+ goto yy627;
+ goto yy616;
+ }
+ }
+ yy619:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy616;
+ if (yych <= 0xBF)
+ goto yy626;
+ goto yy616;
+ yy620:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x9F)
+ goto yy616;
+ if (yych <= 0xBF)
+ goto yy631;
+ goto yy616;
+ yy621:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy616;
+ if (yych <= 0xBF)
+ goto yy631;
+ goto yy616;
+ yy622:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy616;
+ if (yych <= 0x9F)
+ goto yy631;
+ goto yy616;
+ yy623:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x8F)
+ goto yy616;
+ if (yych <= 0xBF)
+ goto yy633;
+ goto yy616;
+ yy624:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy616;
+ if (yych <= 0xBF)
+ goto yy633;
+ goto yy616;
+ yy625:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy616;
+ if (yych <= 0x8F)
+ goto yy633;
+ goto yy616;
+ yy626:
+ yych = *++p;
+ yy627:
+ if (yybm[0 + yych] & 64) {
+ goto yy626;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy628;
+ if (yych <= '?')
+ goto yy629;
+ } else {
+ if (yych <= 0xDF)
+ goto yy631;
+ if (yych <= 0xE0)
+ goto yy632;
+ goto yy633;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy634;
+ if (yych <= 0xEF)
+ goto yy633;
+ goto yy635;
+ } else {
+ if (yych <= 0xF3)
+ goto yy636;
+ if (yych <= 0xF4)
+ goto yy637;
+ }
+ }
+ yy628:
+ p = marker;
+ if (yyaccept == 0) {
+ goto yy616;
+ } else {
+ goto yy639;
+ }
+ yy629:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy629;
+ }
+ if (yych <= 0xDF) {
+ if (yych <= '=') {
+ if (yych <= 0x00)
+ goto yy628;
+ if (yych == '\n')
+ goto yy628;
+ goto yy626;
+ } else {
+ if (yych <= '>')
+ goto yy638;
+ if (yych <= 0x7F)
+ goto yy626;
+ if (yych <= 0xC1)
+ goto yy628;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych <= 0xE0)
+ goto yy632;
+ if (yych == 0xED)
+ goto yy634;
+ goto yy633;
+ } else {
+ if (yych <= 0xF0)
+ goto yy635;
+ if (yych <= 0xF3)
+ goto yy636;
+ if (yych <= 0xF4)
+ goto yy637;
+ goto yy628;
+ }
+ }
+ yy631:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy628;
+ if (yych <= 0xBF)
+ goto yy626;
+ goto yy628;
+ yy632:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy628;
+ if (yych <= 0xBF)
+ goto yy631;
+ goto yy628;
+ yy633:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy628;
+ if (yych <= 0xBF)
+ goto yy631;
+ goto yy628;
+ yy634:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy628;
+ if (yych <= 0x9F)
+ goto yy631;
+ goto yy628;
+ yy635:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy628;
+ if (yych <= 0xBF)
+ goto yy633;
+ goto yy628;
+ yy636:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy628;
+ if (yych <= 0xBF)
+ goto yy633;
+ goto yy628;
+ yy637:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy628;
+ if (yych <= 0x8F)
+ goto yy633;
+ goto yy628;
+ yy638:
+ yyaccept = 1;
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 64) {
+ goto yy626;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy639;
+ if (yych <= '?')
+ goto yy629;
+ } else {
+ if (yych <= 0xDF)
+ goto yy631;
+ if (yych <= 0xE0)
+ goto yy632;
+ goto yy633;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy634;
+ if (yych <= 0xEF)
+ goto yy633;
+ goto yy635;
+ } else {
+ if (yych <= 0xF3)
+ goto yy636;
+ if (yych <= 0xF4)
+ goto yy637;
+ }
+ }
+ yy639 : { return (bufsize_t)(p - start); }
+ }
+}
+
+// Try to match an HTML block end line of type 4
+bufsize_t _scan_html_block_end_4(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ unsigned int yyaccept = 0;
+ static const unsigned char yybm[] = {
+ 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 64, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yybm[0 + yych] & 64) {
+ goto yy645;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '\n') {
+ if (yych <= 0x00)
+ goto yy642;
+ if (yych <= '\t')
+ goto yy644;
+ } else {
+ if (yych <= 0x7F)
+ goto yy644;
+ if (yych <= 0xC1)
+ goto yy642;
+ if (yych <= 0xDF)
+ goto yy648;
+ goto yy649;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy651;
+ goto yy650;
+ } else {
+ if (yych <= 0xF0)
+ goto yy652;
+ if (yych <= 0xF3)
+ goto yy653;
+ if (yych <= 0xF4)
+ goto yy654;
+ }
+ }
+ yy642:
+ ++p;
+ yy643 : { return 0; }
+ yy644:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= '\n') {
+ if (yych <= 0x00)
+ goto yy643;
+ if (yych <= '\t')
+ goto yy656;
+ goto yy643;
+ } else {
+ if (yych <= 0x7F)
+ goto yy656;
+ if (yych <= 0xC1)
+ goto yy643;
+ if (yych <= 0xF4)
+ goto yy656;
+ goto yy643;
+ }
+ yy645:
+ yyaccept = 1;
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 128) {
+ goto yy655;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy647;
+ if (yych <= '>')
+ goto yy645;
+ } else {
+ if (yych <= 0xDF)
+ goto yy658;
+ if (yych <= 0xE0)
+ goto yy659;
+ goto yy660;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy661;
+ if (yych <= 0xEF)
+ goto yy660;
+ goto yy662;
+ } else {
+ if (yych <= 0xF3)
+ goto yy663;
+ if (yych <= 0xF4)
+ goto yy664;
+ }
+ }
+ yy647 : { return (bufsize_t)(p - start); }
+ yy648:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy643;
+ if (yych <= 0xBF)
+ goto yy655;
+ goto yy643;
+ yy649:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x9F)
+ goto yy643;
+ if (yych <= 0xBF)
+ goto yy658;
+ goto yy643;
+ yy650:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy643;
+ if (yych <= 0xBF)
+ goto yy658;
+ goto yy643;
+ yy651:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy643;
+ if (yych <= 0x9F)
+ goto yy658;
+ goto yy643;
+ yy652:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x8F)
+ goto yy643;
+ if (yych <= 0xBF)
+ goto yy660;
+ goto yy643;
+ yy653:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy643;
+ if (yych <= 0xBF)
+ goto yy660;
+ goto yy643;
+ yy654:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy643;
+ if (yych <= 0x8F)
+ goto yy660;
+ goto yy643;
+ yy655:
+ yych = *++p;
+ yy656:
+ if (yybm[0 + yych] & 128) {
+ goto yy655;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy657;
+ if (yych <= '>')
+ goto yy645;
+ } else {
+ if (yych <= 0xDF)
+ goto yy658;
+ if (yych <= 0xE0)
+ goto yy659;
+ goto yy660;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy661;
+ if (yych <= 0xEF)
+ goto yy660;
+ goto yy662;
+ } else {
+ if (yych <= 0xF3)
+ goto yy663;
+ if (yych <= 0xF4)
+ goto yy664;
+ }
+ }
+ yy657:
+ p = marker;
+ if (yyaccept == 0) {
+ goto yy643;
+ } else {
+ goto yy647;
+ }
+ yy658:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy657;
+ if (yych <= 0xBF)
+ goto yy655;
+ goto yy657;
+ yy659:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy657;
+ if (yych <= 0xBF)
+ goto yy658;
+ goto yy657;
+ yy660:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy657;
+ if (yych <= 0xBF)
+ goto yy658;
+ goto yy657;
+ yy661:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy657;
+ if (yych <= 0x9F)
+ goto yy658;
+ goto yy657;
+ yy662:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy657;
+ if (yych <= 0xBF)
+ goto yy660;
+ goto yy657;
+ yy663:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy657;
+ if (yych <= 0xBF)
+ goto yy660;
+ goto yy657;
+ yy664:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy657;
+ if (yych <= 0x8F)
+ goto yy660;
+ goto yy657;
+ }
+}
+
+// Try to match an HTML block end line of type 5
+bufsize_t _scan_html_block_end_5(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ unsigned int yyaccept = 0;
+ static const unsigned char yybm[] = {
+ 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych <= 0xDF) {
+ if (yych <= '\\') {
+ if (yych <= 0x00)
+ goto yy667;
+ if (yych != '\n')
+ goto yy669;
+ } else {
+ if (yych <= ']')
+ goto yy670;
+ if (yych <= 0x7F)
+ goto yy669;
+ if (yych >= 0xC2)
+ goto yy671;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych <= 0xE0)
+ goto yy672;
+ if (yych == 0xED)
+ goto yy674;
+ goto yy673;
+ } else {
+ if (yych <= 0xF0)
+ goto yy675;
+ if (yych <= 0xF3)
+ goto yy676;
+ if (yych <= 0xF4)
+ goto yy677;
+ }
+ }
+ yy667:
+ ++p;
+ yy668 : { return 0; }
+ yy669:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= '\n') {
+ if (yych <= 0x00)
+ goto yy668;
+ if (yych <= '\t')
+ goto yy679;
+ goto yy668;
+ } else {
+ if (yych <= 0x7F)
+ goto yy679;
+ if (yych <= 0xC1)
+ goto yy668;
+ if (yych <= 0xF4)
+ goto yy679;
+ goto yy668;
+ }
+ yy670:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 128) {
+ goto yy689;
+ }
+ if (yych <= '\n') {
+ if (yych <= 0x00)
+ goto yy668;
+ if (yych <= '\t')
+ goto yy679;
+ goto yy668;
+ } else {
+ if (yych <= 0x7F)
+ goto yy679;
+ if (yych <= 0xC1)
+ goto yy668;
+ if (yych <= 0xF4)
+ goto yy679;
+ goto yy668;
+ }
+ yy671:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy668;
+ if (yych <= 0xBF)
+ goto yy678;
+ goto yy668;
+ yy672:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x9F)
+ goto yy668;
+ if (yych <= 0xBF)
+ goto yy682;
+ goto yy668;
+ yy673:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy668;
+ if (yych <= 0xBF)
+ goto yy682;
+ goto yy668;
+ yy674:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy668;
+ if (yych <= 0x9F)
+ goto yy682;
+ goto yy668;
+ yy675:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x8F)
+ goto yy668;
+ if (yych <= 0xBF)
+ goto yy684;
+ goto yy668;
+ yy676:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy668;
+ if (yych <= 0xBF)
+ goto yy684;
+ goto yy668;
+ yy677:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x7F)
+ goto yy668;
+ if (yych <= 0x8F)
+ goto yy684;
+ goto yy668;
+ yy678:
+ yych = *++p;
+ yy679:
+ if (yybm[0 + yych] & 64) {
+ goto yy678;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy680;
+ if (yych <= ']')
+ goto yy681;
+ } else {
+ if (yych <= 0xDF)
+ goto yy682;
+ if (yych <= 0xE0)
+ goto yy683;
+ goto yy684;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy685;
+ if (yych <= 0xEF)
+ goto yy684;
+ goto yy686;
+ } else {
+ if (yych <= 0xF3)
+ goto yy687;
+ if (yych <= 0xF4)
+ goto yy688;
+ }
+ }
+ yy680:
+ p = marker;
+ if (yyaccept == 0) {
+ goto yy668;
+ } else {
+ goto yy692;
+ }
+ yy681:
+ yych = *++p;
+ if (yybm[0 + yych] & 64) {
+ goto yy678;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy680;
+ if (yych <= ']')
+ goto yy689;
+ goto yy680;
+ } else {
+ if (yych <= 0xDF)
+ goto yy682;
+ if (yych <= 0xE0)
+ goto yy683;
+ goto yy684;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy685;
+ if (yych <= 0xEF)
+ goto yy684;
+ goto yy686;
+ } else {
+ if (yych <= 0xF3)
+ goto yy687;
+ if (yych <= 0xF4)
+ goto yy688;
+ goto yy680;
+ }
+ }
+ yy682:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy680;
+ if (yych <= 0xBF)
+ goto yy678;
+ goto yy680;
+ yy683:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy680;
+ if (yych <= 0xBF)
+ goto yy682;
+ goto yy680;
+ yy684:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy680;
+ if (yych <= 0xBF)
+ goto yy682;
+ goto yy680;
+ yy685:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy680;
+ if (yych <= 0x9F)
+ goto yy682;
+ goto yy680;
+ yy686:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy680;
+ if (yych <= 0xBF)
+ goto yy684;
+ goto yy680;
+ yy687:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy680;
+ if (yych <= 0xBF)
+ goto yy684;
+ goto yy680;
+ yy688:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy680;
+ if (yych <= 0x8F)
+ goto yy684;
+ goto yy680;
+ yy689:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy689;
+ }
+ if (yych <= 0xDF) {
+ if (yych <= '=') {
+ if (yych <= 0x00)
+ goto yy680;
+ if (yych == '\n')
+ goto yy680;
+ goto yy678;
+ } else {
+ if (yych <= '>')
+ goto yy691;
+ if (yych <= 0x7F)
+ goto yy678;
+ if (yych <= 0xC1)
+ goto yy680;
+ goto yy682;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych <= 0xE0)
+ goto yy683;
+ if (yych == 0xED)
+ goto yy685;
+ goto yy684;
+ } else {
+ if (yych <= 0xF0)
+ goto yy686;
+ if (yych <= 0xF3)
+ goto yy687;
+ if (yych <= 0xF4)
+ goto yy688;
+ goto yy680;
+ }
+ }
+ yy691:
+ yyaccept = 1;
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 64) {
+ goto yy678;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= '\n')
+ goto yy692;
+ if (yych <= ']')
+ goto yy681;
+ } else {
+ if (yych <= 0xDF)
+ goto yy682;
+ if (yych <= 0xE0)
+ goto yy683;
+ goto yy684;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy685;
+ if (yych <= 0xEF)
+ goto yy684;
+ goto yy686;
+ } else {
+ if (yych <= 0xF3)
+ goto yy687;
+ if (yych <= 0xF4)
+ goto yy688;
+ }
+ }
+ yy692 : { return (bufsize_t)(p - start); }
+ }
+}
+
+// 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).
+bufsize_t _scan_link_title(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ unsigned int yyaccept = 0;
+ static const unsigned char yybm[] = {
+ 0, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 192, 208, 208, 208, 208, 144, 208, 80,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 32, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
+ 208, 208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych <= '&') {
+ if (yych == '"')
+ goto yy697;
+ } else {
+ if (yych <= '\'')
+ goto yy698;
+ if (yych <= '(')
+ goto yy699;
+ }
+ ++p;
+ yy696 : { return 0; }
+ yy697:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x00)
+ goto yy696;
+ if (yych <= 0x7F)
+ goto yy701;
+ if (yych <= 0xC1)
+ goto yy696;
+ if (yych <= 0xF4)
+ goto yy701;
+ goto yy696;
+ yy698:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x00)
+ goto yy696;
+ if (yych <= 0x7F)
+ goto yy715;
+ if (yych <= 0xC1)
+ goto yy696;
+ if (yych <= 0xF4)
+ goto yy715;
+ goto yy696;
+ yy699:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych <= 0x00)
+ goto yy696;
+ if (yych <= 0x7F)
+ goto yy728;
+ if (yych <= 0xC1)
+ goto yy696;
+ if (yych <= 0xF4)
+ goto yy728;
+ goto yy696;
+ yy700:
+ yych = *++p;
+ yy701:
+ if (yybm[0 + yych] & 16) {
+ goto yy700;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '\\') {
+ if (yych <= 0x00)
+ goto yy702;
+ if (yych <= '"')
+ goto yy703;
+ goto yy705;
+ } else {
+ if (yych <= 0xC1)
+ goto yy702;
+ if (yych <= 0xDF)
+ goto yy707;
+ goto yy708;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy710;
+ goto yy709;
+ } else {
+ if (yych <= 0xF0)
+ goto yy711;
+ if (yych <= 0xF3)
+ goto yy712;
+ if (yych <= 0xF4)
+ goto yy713;
+ }
+ }
+ yy702:
+ p = marker;
+ if (yyaccept <= 1) {
+ if (yyaccept == 0) {
+ goto yy696;
+ } else {
+ goto yy704;
+ }
+ } else {
+ if (yyaccept == 2) {
+ goto yy717;
+ } else {
+ goto yy730;
+ }
+ }
+ yy703:
+ ++p;
+ yy704 : { return (bufsize_t)(p - start); }
+ yy705:
+ yych = *++p;
+ if (yybm[0 + yych] & 16) {
+ goto yy700;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '\\') {
+ if (yych <= 0x00)
+ goto yy702;
+ if (yych <= '"')
+ goto yy740;
+ goto yy705;
+ } else {
+ if (yych <= 0xC1)
+ goto yy702;
+ if (yych >= 0xE0)
+ goto yy708;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy710;
+ goto yy709;
+ } else {
+ if (yych <= 0xF0)
+ goto yy711;
+ if (yych <= 0xF3)
+ goto yy712;
+ if (yych <= 0xF4)
+ goto yy713;
+ goto yy702;
+ }
+ }
+ yy707:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy700;
+ goto yy702;
+ yy708:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy707;
+ goto yy702;
+ yy709:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy707;
+ goto yy702;
+ yy710:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0x9F)
+ goto yy707;
+ goto yy702;
+ yy711:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy709;
+ goto yy702;
+ yy712:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy709;
+ goto yy702;
+ yy713:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0x8F)
+ goto yy709;
+ goto yy702;
+ yy714:
+ yych = *++p;
+ yy715:
+ if (yybm[0 + yych] & 64) {
+ goto yy714;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '\\') {
+ if (yych <= 0x00)
+ goto yy702;
+ if (yych >= '(')
+ goto yy718;
+ } else {
+ if (yych <= 0xC1)
+ goto yy702;
+ if (yych <= 0xDF)
+ goto yy720;
+ goto yy721;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy723;
+ goto yy722;
+ } else {
+ if (yych <= 0xF0)
+ goto yy724;
+ if (yych <= 0xF3)
+ goto yy725;
+ if (yych <= 0xF4)
+ goto yy726;
+ goto yy702;
+ }
+ }
+ yy716:
+ ++p;
+ yy717 : { return (bufsize_t)(p - start); }
+ yy718:
+ yych = *++p;
+ if (yybm[0 + yych] & 64) {
+ goto yy714;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '\\') {
+ if (yych <= 0x00)
+ goto yy702;
+ if (yych <= '\'')
+ goto yy741;
+ goto yy718;
+ } else {
+ if (yych <= 0xC1)
+ goto yy702;
+ if (yych >= 0xE0)
+ goto yy721;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy723;
+ goto yy722;
+ } else {
+ if (yych <= 0xF0)
+ goto yy724;
+ if (yych <= 0xF3)
+ goto yy725;
+ if (yych <= 0xF4)
+ goto yy726;
+ goto yy702;
+ }
+ }
+ yy720:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy714;
+ goto yy702;
+ yy721:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy720;
+ goto yy702;
+ yy722:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy720;
+ goto yy702;
+ yy723:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0x9F)
+ goto yy720;
+ goto yy702;
+ yy724:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy722;
+ goto yy702;
+ yy725:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy722;
+ goto yy702;
+ yy726:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0x8F)
+ goto yy722;
+ goto yy702;
+ yy727:
+ yych = *++p;
+ yy728:
+ if (yybm[0 + yych] & 128) {
+ goto yy727;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '\\') {
+ if (yych <= 0x00)
+ goto yy702;
+ if (yych >= '*')
+ goto yy731;
+ } else {
+ if (yych <= 0xC1)
+ goto yy702;
+ if (yych <= 0xDF)
+ goto yy733;
+ goto yy734;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy736;
+ goto yy735;
+ } else {
+ if (yych <= 0xF0)
+ goto yy737;
+ if (yych <= 0xF3)
+ goto yy738;
+ if (yych <= 0xF4)
+ goto yy739;
+ goto yy702;
+ }
+ }
+ yy729:
+ ++p;
+ yy730 : { return (bufsize_t)(p - start); }
+ yy731:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy727;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '\\') {
+ if (yych <= 0x00)
+ goto yy702;
+ if (yych <= ')')
+ goto yy742;
+ goto yy731;
+ } else {
+ if (yych <= 0xC1)
+ goto yy702;
+ if (yych >= 0xE0)
+ goto yy734;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy736;
+ goto yy735;
+ } else {
+ if (yych <= 0xF0)
+ goto yy737;
+ if (yych <= 0xF3)
+ goto yy738;
+ if (yych <= 0xF4)
+ goto yy739;
+ goto yy702;
+ }
+ }
+ yy733:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy727;
+ goto yy702;
+ yy734:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy733;
+ goto yy702;
+ yy735:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy733;
+ goto yy702;
+ yy736:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0x9F)
+ goto yy733;
+ goto yy702;
+ yy737:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy735;
+ goto yy702;
+ yy738:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0xBF)
+ goto yy735;
+ goto yy702;
+ yy739:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy702;
+ if (yych <= 0x8F)
+ goto yy735;
+ goto yy702;
+ yy740:
+ yyaccept = 1;
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 16) {
+ goto yy700;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '\\') {
+ if (yych <= 0x00)
+ goto yy704;
+ if (yych <= '"')
+ goto yy703;
+ goto yy705;
+ } else {
+ if (yych <= 0xC1)
+ goto yy704;
+ if (yych <= 0xDF)
+ goto yy707;
+ goto yy708;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy710;
+ goto yy709;
+ } else {
+ if (yych <= 0xF0)
+ goto yy711;
+ if (yych <= 0xF3)
+ goto yy712;
+ if (yych <= 0xF4)
+ goto yy713;
+ goto yy704;
+ }
+ }
+ yy741:
+ yyaccept = 2;
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 64) {
+ goto yy714;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '\\') {
+ if (yych <= 0x00)
+ goto yy717;
+ if (yych <= '\'')
+ goto yy716;
+ goto yy718;
+ } else {
+ if (yych <= 0xC1)
+ goto yy717;
+ if (yych <= 0xDF)
+ goto yy720;
+ goto yy721;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy723;
+ goto yy722;
+ } else {
+ if (yych <= 0xF0)
+ goto yy724;
+ if (yych <= 0xF3)
+ goto yy725;
+ if (yych <= 0xF4)
+ goto yy726;
+ goto yy717;
+ }
+ }
+ yy742:
+ yyaccept = 3;
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 128) {
+ goto yy727;
+ }
+ if (yych <= 0xE0) {
+ if (yych <= '\\') {
+ if (yych <= 0x00)
+ goto yy730;
+ if (yych <= ')')
+ goto yy729;
+ goto yy731;
+ } else {
+ if (yych <= 0xC1)
+ goto yy730;
+ if (yych <= 0xDF)
+ goto yy733;
+ goto yy734;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych == 0xED)
+ goto yy736;
+ goto yy735;
+ } else {
+ if (yych <= 0xF0)
+ goto yy737;
+ if (yych <= 0xF3)
+ goto yy738;
+ if (yych <= 0xF4)
+ goto yy739;
+ goto yy730;
+ }
+ }
+ }
+}
+
+// Match space characters, including newlines.
+bufsize_t _scan_spacechars(const unsigned char *p) {
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ static const unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yybm[0 + yych] & 128) {
+ goto yy747;
+ }
+ ++p;
+ { return 0; }
+ yy747:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy747;
+ }
+ { return (bufsize_t)(p - start); }
+ }
+}
+
+// Match ATX heading start.
+bufsize_t _scan_atx_heading_start(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ static const unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych == '#')
+ goto yy754;
+ ++p;
+ yy753 : { return 0; }
+ yy754:
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 128) {
+ goto yy755;
+ }
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy753;
+ if (yych <= '\n')
+ goto yy758;
+ goto yy753;
+ } else {
+ if (yych <= '\r')
+ goto yy758;
+ if (yych == '#')
+ goto yy759;
+ goto yy753;
+ }
+ yy755:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy755;
+ }
+ yy757 : { return (bufsize_t)(p - start); }
+ yy758:
+ ++p;
+ goto yy757;
+ yy759:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy755;
+ }
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy760;
+ if (yych <= '\n')
+ goto yy758;
+ } else {
+ if (yych <= '\r')
+ goto yy758;
+ if (yych == '#')
+ goto yy761;
+ }
+ yy760:
+ p = marker;
+ goto yy753;
+ yy761:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy755;
+ }
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy760;
+ if (yych <= '\n')
+ goto yy758;
+ goto yy760;
+ } else {
+ if (yych <= '\r')
+ goto yy758;
+ if (yych != '#')
+ goto yy760;
+ }
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy755;
+ }
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy760;
+ if (yych <= '\n')
+ goto yy758;
+ goto yy760;
+ } else {
+ if (yych <= '\r')
+ goto yy758;
+ if (yych != '#')
+ goto yy760;
+ }
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy755;
+ }
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy760;
+ if (yych <= '\n')
+ goto yy758;
+ goto yy760;
+ } else {
+ if (yych <= '\r')
+ goto yy758;
+ if (yych != '#')
+ goto yy760;
+ }
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy755;
+ }
+ if (yych <= 0x08)
+ goto yy760;
+ if (yych <= '\n')
+ goto yy758;
+ if (yych == '\r')
+ goto yy758;
+ goto yy760;
+ }
+}
+
+// Match setext heading line. Return 1 for level-1 heading,
+// 2 for level-2, 0 for no match.
+bufsize_t _scan_setext_heading_line(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+
+ {
+ unsigned char yych;
+ static const unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych == '-')
+ goto yy769;
+ if (yych == '=')
+ goto yy770;
+ ++p;
+ yy768 : { return 0; }
+ yy769:
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 64) {
+ goto yy776;
+ }
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy768;
+ if (yych <= '\n')
+ goto yy772;
+ goto yy768;
+ } else {
+ if (yych <= '\r')
+ goto yy772;
+ if (yych == ' ')
+ goto yy772;
+ goto yy768;
+ }
+ yy770:
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 128) {
+ goto yy782;
+ }
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy768;
+ if (yych <= '\n')
+ goto yy779;
+ goto yy768;
+ } else {
+ if (yych <= '\r')
+ goto yy779;
+ if (yych == ' ')
+ goto yy779;
+ goto yy768;
+ }
+ yy771:
+ yych = *++p;
+ yy772:
+ if (yybm[0 + yych] & 32) {
+ goto yy771;
+ }
+ if (yych <= 0x08)
+ goto yy773;
+ if (yych <= '\n')
+ goto yy774;
+ if (yych == '\r')
+ goto yy774;
+ yy773:
+ p = marker;
+ goto yy768;
+ yy774:
+ ++p;
+ { return 2; }
+ yy776:
+ yych = *++p;
+ if (yybm[0 + yych] & 32) {
+ goto yy771;
+ }
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy773;
+ if (yych <= '\n')
+ goto yy774;
+ goto yy773;
+ } else {
+ if (yych <= '\r')
+ goto yy774;
+ if (yych == '-')
+ goto yy776;
+ goto yy773;
+ }
+ yy778:
+ yych = *++p;
+ yy779:
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy773;
+ if (yych <= '\t')
+ goto yy778;
+ if (yych >= '\v')
+ goto yy773;
+ } else {
+ if (yych <= '\r')
+ goto yy780;
+ if (yych == ' ')
+ goto yy778;
+ goto yy773;
+ }
+ yy780:
+ ++p;
+ { return 1; }
+ yy782:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy782;
+ }
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy773;
+ if (yych <= '\t')
+ goto yy778;
+ if (yych <= '\n')
+ goto yy780;
+ goto yy773;
+ } else {
+ if (yych <= '\r')
+ goto yy780;
+ if (yych == ' ')
+ goto yy778;
+ goto yy773;
+ }
+ }
+}
+
+// Scan a thematic break 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."
+bufsize_t _scan_thematic_break(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ static const unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 32, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych <= ',') {
+ if (yych == '*')
+ goto yy788;
+ } else {
+ if (yych <= '-')
+ goto yy789;
+ if (yych == '_')
+ goto yy790;
+ }
+ ++p;
+ yy787 : { return 0; }
+ yy788:
+ yych = *(marker = ++p);
+ if (yybm[0 + yych] & 16) {
+ goto yy791;
+ }
+ if (yych == '*')
+ goto yy794;
+ goto yy787;
+ yy789:
+ yych = *(marker = ++p);
+ if (yych <= 0x1F) {
+ if (yych == '\t')
+ goto yy796;
+ goto yy787;
+ } else {
+ if (yych <= ' ')
+ goto yy796;
+ if (yych == '-')
+ goto yy798;
+ goto yy787;
+ }
+ yy790:
+ yych = *(marker = ++p);
+ if (yych <= 0x1F) {
+ if (yych == '\t')
+ goto yy800;
+ goto yy787;
+ } else {
+ if (yych <= ' ')
+ goto yy800;
+ if (yych == '_')
+ goto yy802;
+ goto yy787;
+ }
+ yy791:
+ yych = *++p;
+ if (yybm[0 + yych] & 16) {
+ goto yy791;
+ }
+ if (yych == '*')
+ goto yy794;
+ yy793:
+ p = marker;
+ goto yy787;
+ yy794:
+ yych = *++p;
+ if (yych <= 0x1F) {
+ if (yych == '\t')
+ goto yy794;
+ goto yy793;
+ } else {
+ if (yych <= ' ')
+ goto yy794;
+ if (yych == '*')
+ goto yy804;
+ goto yy793;
+ }
+ yy796:
+ yych = *++p;
+ if (yych <= 0x1F) {
+ if (yych == '\t')
+ goto yy796;
+ goto yy793;
+ } else {
+ if (yych <= ' ')
+ goto yy796;
+ if (yych != '-')
+ goto yy793;
+ }
+ yy798:
+ yych = *++p;
+ if (yych <= 0x1F) {
+ if (yych == '\t')
+ goto yy798;
+ goto yy793;
+ } else {
+ if (yych <= ' ')
+ goto yy798;
+ if (yych == '-')
+ goto yy806;
+ goto yy793;
+ }
+ yy800:
+ yych = *++p;
+ if (yych <= 0x1F) {
+ if (yych == '\t')
+ goto yy800;
+ goto yy793;
+ } else {
+ if (yych <= ' ')
+ goto yy800;
+ if (yych != '_')
+ goto yy793;
+ }
+ yy802:
+ yych = *++p;
+ if (yych <= 0x1F) {
+ if (yych == '\t')
+ goto yy802;
+ goto yy793;
+ } else {
+ if (yych <= ' ')
+ goto yy802;
+ if (yych == '_')
+ goto yy808;
+ goto yy793;
+ }
+ yy804:
+ yych = *++p;
+ if (yybm[0 + yych] & 32) {
+ goto yy804;
+ }
+ if (yych <= 0x08)
+ goto yy793;
+ if (yych <= '\n')
+ goto yy810;
+ if (yych == '\r')
+ goto yy810;
+ goto yy793;
+ yy806:
+ yych = *++p;
+ if (yybm[0 + yych] & 64) {
+ goto yy806;
+ }
+ if (yych <= 0x08)
+ goto yy793;
+ if (yych <= '\n')
+ goto yy812;
+ if (yych == '\r')
+ goto yy812;
+ goto yy793;
+ yy808:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy808;
+ }
+ if (yych <= 0x08)
+ goto yy793;
+ if (yych <= '\n')
+ goto yy814;
+ if (yych == '\r')
+ goto yy814;
+ goto yy793;
+ yy810:
+ ++p;
+ { return (bufsize_t)(p - start); }
+ yy812:
+ ++p;
+ { return (bufsize_t)(p - start); }
+ yy814:
+ ++p;
+ { return (bufsize_t)(p - start); }
+ }
+}
+
+// Scan an opening code fence.
+bufsize_t _scan_open_code_fence(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ static const unsigned char yybm[] = {
+ 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 192, 192, 0,
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 144, 192,
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
+ 224, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych == '`')
+ goto yy820;
+ if (yych == '~')
+ goto yy821;
+ ++p;
+ yy819 : { return 0; }
+ yy820:
+ yych = *(marker = ++p);
+ if (yych == '`')
+ goto yy822;
+ goto yy819;
+ yy821:
+ yych = *(marker = ++p);
+ if (yych == '~')
+ goto yy824;
+ goto yy819;
+ yy822:
+ yych = *++p;
+ if (yybm[0 + yych] & 16) {
+ goto yy825;
+ }
+ yy823:
+ p = marker;
+ goto yy819;
+ yy824:
+ yych = *++p;
+ if (yybm[0 + yych] & 32) {
+ goto yy827;
+ }
+ goto yy823;
+ yy825:
+ yych = *++p;
+ if (yybm[0 + yych] & 16) {
+ goto yy825;
+ }
+ if (yych <= 0xDF) {
+ if (yych <= '\f') {
+ if (yych <= 0x00)
+ goto yy823;
+ if (yych == '\n') {
+ marker = p;
+ goto yy831;
+ }
+ marker = p;
+ goto yy829;
+ } else {
+ if (yych <= '\r') {
+ marker = p;
+ goto yy831;
+ }
+ if (yych <= 0x7F) {
+ marker = p;
+ goto yy829;
+ }
+ if (yych <= 0xC1)
+ goto yy823;
+ marker = p;
+ goto yy833;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych <= 0xE0) {
+ marker = p;
+ goto yy834;
+ }
+ if (yych == 0xED) {
+ marker = p;
+ goto yy836;
+ }
+ marker = p;
+ goto yy835;
+ } else {
+ if (yych <= 0xF0) {
+ marker = p;
+ goto yy837;
+ }
+ if (yych <= 0xF3) {
+ marker = p;
+ goto yy838;
+ }
+ if (yych <= 0xF4) {
+ marker = p;
+ goto yy839;
+ }
+ goto yy823;
+ }
+ }
+ yy827:
+ yych = *++p;
+ if (yybm[0 + yych] & 32) {
+ goto yy827;
+ }
+ if (yych <= 0xDF) {
+ if (yych <= '\f') {
+ if (yych <= 0x00)
+ goto yy823;
+ if (yych == '\n') {
+ marker = p;
+ goto yy842;
+ }
+ marker = p;
+ goto yy840;
+ } else {
+ if (yych <= '\r') {
+ marker = p;
+ goto yy842;
+ }
+ if (yych <= 0x7F) {
+ marker = p;
+ goto yy840;
+ }
+ if (yych <= 0xC1)
+ goto yy823;
+ marker = p;
+ goto yy844;
+ }
+ } else {
+ if (yych <= 0xEF) {
+ if (yych <= 0xE0) {
+ marker = p;
+ goto yy845;
+ }
+ if (yych == 0xED) {
+ marker = p;
+ goto yy847;
+ }
+ marker = p;
+ goto yy846;
+ } else {
+ if (yych <= 0xF0) {
+ marker = p;
+ goto yy848;
+ }
+ if (yych <= 0xF3) {
+ marker = p;
+ goto yy849;
+ }
+ if (yych <= 0xF4) {
+ marker = p;
+ goto yy850;
+ }
+ goto yy823;
+ }
+ }
+ yy829:
+ yych = *++p;
+ if (yybm[0 + yych] & 64) {
+ goto yy829;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy823;
+ if (yych >= 0x0E)
+ goto yy823;
+ } else {
+ if (yych <= 0xDF)
+ goto yy833;
+ if (yych <= 0xE0)
+ goto yy834;
+ goto yy835;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy836;
+ if (yych <= 0xEF)
+ goto yy835;
+ goto yy837;
+ } else {
+ if (yych <= 0xF3)
+ goto yy838;
+ if (yych <= 0xF4)
+ goto yy839;
+ goto yy823;
+ }
+ }
+ yy831:
+ ++p;
+ p = marker;
+ { return (bufsize_t)(p - start); }
+ yy833:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy823;
+ if (yych <= 0xBF)
+ goto yy829;
+ goto yy823;
+ yy834:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy823;
+ if (yych <= 0xBF)
+ goto yy833;
+ goto yy823;
+ yy835:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy823;
+ if (yych <= 0xBF)
+ goto yy833;
+ goto yy823;
+ yy836:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy823;
+ if (yych <= 0x9F)
+ goto yy833;
+ goto yy823;
+ yy837:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy823;
+ if (yych <= 0xBF)
+ goto yy835;
+ goto yy823;
+ yy838:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy823;
+ if (yych <= 0xBF)
+ goto yy835;
+ goto yy823;
+ yy839:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy823;
+ if (yych <= 0x8F)
+ goto yy835;
+ goto yy823;
+ yy840:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy840;
+ }
+ if (yych <= 0xEC) {
+ if (yych <= 0xC1) {
+ if (yych <= 0x00)
+ goto yy823;
+ if (yych >= 0x0E)
+ goto yy823;
+ } else {
+ if (yych <= 0xDF)
+ goto yy844;
+ if (yych <= 0xE0)
+ goto yy845;
+ goto yy846;
+ }
+ } else {
+ if (yych <= 0xF0) {
+ if (yych <= 0xED)
+ goto yy847;
+ if (yych <= 0xEF)
+ goto yy846;
+ goto yy848;
+ } else {
+ if (yych <= 0xF3)
+ goto yy849;
+ if (yych <= 0xF4)
+ goto yy850;
+ goto yy823;
+ }
+ }
+ yy842:
+ ++p;
+ p = marker;
+ { return (bufsize_t)(p - start); }
+ yy844:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy823;
+ if (yych <= 0xBF)
+ goto yy840;
+ goto yy823;
+ yy845:
+ yych = *++p;
+ if (yych <= 0x9F)
+ goto yy823;
+ if (yych <= 0xBF)
+ goto yy844;
+ goto yy823;
+ yy846:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy823;
+ if (yych <= 0xBF)
+ goto yy844;
+ goto yy823;
+ yy847:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy823;
+ if (yych <= 0x9F)
+ goto yy844;
+ goto yy823;
+ yy848:
+ yych = *++p;
+ if (yych <= 0x8F)
+ goto yy823;
+ if (yych <= 0xBF)
+ goto yy846;
+ goto yy823;
+ yy849:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy823;
+ if (yych <= 0xBF)
+ goto yy846;
+ goto yy823;
+ yy850:
+ yych = *++p;
+ if (yych <= 0x7F)
+ goto yy823;
+ if (yych <= 0x8F)
+ goto yy846;
+ goto yy823;
+ }
+}
+
+// Scan a closing code fence with length at least len.
+bufsize_t _scan_close_code_fence(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ static const unsigned char yybm[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+ yych = *p;
+ if (yych == '`')
+ goto yy855;
+ if (yych == '~')
+ goto yy856;
+ ++p;
+ yy854 : { return 0; }
+ yy855:
+ yych = *(marker = ++p);
+ if (yych == '`')
+ goto yy857;
+ goto yy854;
+ yy856:
+ yych = *(marker = ++p);
+ if (yych == '~')
+ goto yy859;
+ goto yy854;
+ yy857:
+ yych = *++p;
+ if (yybm[0 + yych] & 32) {
+ goto yy860;
+ }
+ yy858:
+ p = marker;
+ goto yy854;
+ yy859:
+ yych = *++p;
+ if (yybm[0 + yych] & 64) {
+ goto yy862;
+ }
+ goto yy858;
+ yy860:
+ yych = *++p;
+ if (yybm[0 + yych] & 32) {
+ goto yy860;
+ }
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy858;
+ if (yych <= '\t') {
+ marker = p;
+ goto yy864;
+ }
+ if (yych <= '\n') {
+ marker = p;
+ goto yy866;
+ }
+ goto yy858;
+ } else {
+ if (yych <= '\r') {
+ marker = p;
+ goto yy866;
+ }
+ if (yych == ' ') {
+ marker = p;
+ goto yy864;
+ }
+ goto yy858;
+ }
+ yy862:
+ yych = *++p;
+ if (yybm[0 + yych] & 64) {
+ goto yy862;
+ }
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy858;
+ if (yych <= '\t') {
+ marker = p;
+ goto yy868;
+ }
+ if (yych <= '\n') {
+ marker = p;
+ goto yy870;
+ }
+ goto yy858;
+ } else {
+ if (yych <= '\r') {
+ marker = p;
+ goto yy870;
+ }
+ if (yych == ' ') {
+ marker = p;
+ goto yy868;
+ }
+ goto yy858;
+ }
+ yy864:
+ yych = *++p;
+ if (yybm[0 + yych] & 128) {
+ goto yy864;
+ }
+ if (yych <= 0x08)
+ goto yy858;
+ if (yych <= '\n')
+ goto yy866;
+ if (yych != '\r')
+ goto yy858;
+ yy866:
+ ++p;
+ p = marker;
+ { return (bufsize_t)(p - start); }
+ yy868:
+ yych = *++p;
+ if (yych <= '\f') {
+ if (yych <= 0x08)
+ goto yy858;
+ if (yych <= '\t')
+ goto yy868;
+ if (yych >= '\v')
+ goto yy858;
+ } else {
+ if (yych <= '\r')
+ goto yy870;
+ if (yych == ' ')
+ goto yy868;
+ goto yy858;
+ }
+ yy870:
+ ++p;
+ p = marker;
+ { return (bufsize_t)(p - start); }
+ }
+}
+
+// Scans an entity.
+// Returns number of chars matched.
+bufsize_t _scan_entity(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ yych = *p;
+ if (yych == '&')
+ goto yy876;
+ ++p;
+ yy875 : { return 0; }
+ yy876:
+ yych = *(marker = ++p);
+ if (yych <= '@') {
+ if (yych != '#')
+ goto yy875;
+ } else {
+ if (yych <= 'Z')
+ goto yy879;
+ if (yych <= '`')
+ goto yy875;
+ if (yych <= 'z')
+ goto yy879;
+ goto yy875;
+ }
+ yych = *++p;
+ if (yych <= 'W') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy880;
+ } else {
+ if (yych <= 'X')
+ goto yy881;
+ if (yych == 'x')
+ goto yy881;
+ }
+ yy878:
+ p = marker;
+ goto yy875;
+ yy879:
+ yych = *++p;
+ if (yych <= '@') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy882;
+ goto yy878;
+ } else {
+ if (yych <= 'Z')
+ goto yy882;
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'z')
+ goto yy882;
+ goto yy878;
+ }
+ yy880:
+ yych = *++p;
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy883;
+ if (yych == ';')
+ goto yy884;
+ goto yy878;
+ yy881:
+ yych = *++p;
+ if (yych <= '@') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy886;
+ goto yy878;
+ } else {
+ if (yych <= 'F')
+ goto yy886;
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'f')
+ goto yy886;
+ goto yy878;
+ }
+ yy882:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy887;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy887;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'z')
+ goto yy887;
+ goto yy878;
+ }
+ }
+ yy883:
+ yych = *++p;
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy888;
+ if (yych != ';')
+ goto yy878;
+ yy884:
+ ++p;
+ { return (bufsize_t)(p - start); }
+ yy886:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy889;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'F') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy889;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'f')
+ goto yy889;
+ goto yy878;
+ }
+ }
+ yy887:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy890;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy890;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'z')
+ goto yy890;
+ goto yy878;
+ }
+ }
+ yy888:
+ yych = *++p;
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy891;
+ if (yych == ';')
+ goto yy884;
+ goto yy878;
+ yy889:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy892;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'F') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy892;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'f')
+ goto yy892;
+ goto yy878;
+ }
+ }
+ yy890:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy893;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy893;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'z')
+ goto yy893;
+ goto yy878;
+ }
+ }
+ yy891:
+ yych = *++p;
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy894;
+ if (yych == ';')
+ goto yy884;
+ goto yy878;
+ yy892:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy895;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'F') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy895;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'f')
+ goto yy895;
+ goto yy878;
+ }
+ }
+ yy893:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy896;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy896;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'z')
+ goto yy896;
+ goto yy878;
+ }
+ }
+ yy894:
+ yych = *++p;
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy897;
+ if (yych == ';')
+ goto yy884;
+ goto yy878;
+ yy895:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy898;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'F') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy898;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'f')
+ goto yy898;
+ goto yy878;
+ }
+ }
+ yy896:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy899;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy899;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'z')
+ goto yy899;
+ goto yy878;
+ }
+ }
+ yy897:
+ yych = *++p;
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy900;
+ if (yych == ';')
+ goto yy884;
+ goto yy878;
+ yy898:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy900;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'F') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy900;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'f')
+ goto yy900;
+ goto yy878;
+ }
+ }
+ yy899:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy901;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy901;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'z')
+ goto yy901;
+ goto yy878;
+ }
+ }
+ yy900:
+ yych = *++p;
+ if (yych == ';')
+ goto yy884;
+ goto yy878;
+ yy901:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy902;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy902:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy903;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy903:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy904;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy904:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy905;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy905:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy906;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy906:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy907;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy907:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy908;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy908:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy909;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy909:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy910;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy910:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy911;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy911:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy912;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy912:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy913;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy913:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy914;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy914:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy915;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy915:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy916;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy916:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy917;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy917:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy918;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy918:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy919;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy919:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy920;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy920:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy921;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy921:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy922;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy922:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy923;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy923:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy924;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych >= '{')
+ goto yy878;
+ }
+ }
+ yy924:
+ yych = *++p;
+ if (yych <= ';') {
+ if (yych <= '/')
+ goto yy878;
+ if (yych <= '9')
+ goto yy900;
+ if (yych <= ':')
+ goto yy878;
+ goto yy884;
+ } else {
+ if (yych <= 'Z') {
+ if (yych <= '@')
+ goto yy878;
+ goto yy900;
+ } else {
+ if (yych <= '`')
+ goto yy878;
+ if (yych <= 'z')
+ goto yy900;
+ goto yy878;
+ }
+ }
+ }
+}
+
+// Returns positive value if a URL begins in a way that is potentially
+// dangerous, with javascript:, vbscript:, file:, or data:, otherwise 0.
+bufsize_t _scan_dangerous_url(const unsigned char *p) {
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+
+ {
+ unsigned char yych;
+ unsigned int yyaccept = 0;
+ yych = *p;
+ if (yych <= 'V') {
+ if (yych <= 'F') {
+ if (yych == 'D')
+ goto yy929;
+ if (yych >= 'F')
+ goto yy930;
+ } else {
+ if (yych == 'J')
+ goto yy931;
+ if (yych >= 'V')
+ goto yy932;
+ }
+ } else {
+ if (yych <= 'f') {
+ if (yych == 'd')
+ goto yy929;
+ if (yych >= 'f')
+ goto yy930;
+ } else {
+ if (yych <= 'j') {
+ if (yych >= 'j')
+ goto yy931;
+ } else {
+ if (yych == 'v')
+ goto yy932;
+ }
+ }
+ }
+ ++p;
+ yy928 : { return 0; }
+ yy929:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych == 'A')
+ goto yy933;
+ if (yych == 'a')
+ goto yy933;
+ goto yy928;
+ yy930:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych == 'I')
+ goto yy935;
+ if (yych == 'i')
+ goto yy935;
+ goto yy928;
+ yy931:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych == 'A')
+ goto yy936;
+ if (yych == 'a')
+ goto yy936;
+ goto yy928;
+ yy932:
+ yyaccept = 0;
+ yych = *(marker = ++p);
+ if (yych == 'B')
+ goto yy937;
+ if (yych == 'b')
+ goto yy937;
+ goto yy928;
+ yy933:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy938;
+ if (yych == 't')
+ goto yy938;
+ yy934:
+ p = marker;
+ if (yyaccept == 0) {
+ goto yy928;
+ } else {
+ goto yy946;
+ }
+ yy935:
+ yych = *++p;
+ if (yych == 'L')
+ goto yy939;
+ if (yych == 'l')
+ goto yy939;
+ goto yy934;
+ yy936:
+ yych = *++p;
+ if (yych == 'V')
+ goto yy940;
+ if (yych == 'v')
+ goto yy940;
+ goto yy934;
+ yy937:
+ yych = *++p;
+ if (yych == 'S')
+ goto yy941;
+ if (yych == 's')
+ goto yy941;
+ goto yy934;
+ yy938:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy942;
+ if (yych == 'a')
+ goto yy942;
+ goto yy934;
+ yy939:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy943;
+ if (yych == 'e')
+ goto yy943;
+ goto yy934;
+ yy940:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy937;
+ if (yych == 'a')
+ goto yy937;
+ goto yy934;
+ yy941:
+ yych = *++p;
+ if (yych == 'C')
+ goto yy944;
+ if (yych == 'c')
+ goto yy944;
+ goto yy934;
+ yy942:
+ yych = *++p;
+ if (yych == ':')
+ goto yy945;
+ goto yy934;
+ yy943:
+ yych = *++p;
+ if (yych == ':')
+ goto yy947;
+ goto yy934;
+ yy944:
+ yych = *++p;
+ if (yych == 'R')
+ goto yy948;
+ if (yych == 'r')
+ goto yy948;
+ goto yy934;
+ yy945:
+ yyaccept = 1;
+ yych = *(marker = ++p);
+ if (yych == 'I')
+ goto yy949;
+ if (yych == 'i')
+ goto yy949;
+ yy946 : { return (bufsize_t)(p - start); }
+ yy947:
+ ++p;
+ goto yy946;
+ yy948:
+ yych = *++p;
+ if (yych == 'I')
+ goto yy950;
+ if (yych == 'i')
+ goto yy950;
+ goto yy934;
+ yy949:
+ yych = *++p;
+ if (yych == 'M')
+ goto yy951;
+ if (yych == 'm')
+ goto yy951;
+ goto yy934;
+ yy950:
+ yych = *++p;
+ if (yych == 'P')
+ goto yy952;
+ if (yych == 'p')
+ goto yy952;
+ goto yy934;
+ yy951:
+ yych = *++p;
+ if (yych == 'A')
+ goto yy953;
+ if (yych == 'a')
+ goto yy953;
+ goto yy934;
+ yy952:
+ yych = *++p;
+ if (yych == 'T')
+ goto yy943;
+ if (yych == 't')
+ goto yy943;
+ goto yy934;
+ yy953:
+ yych = *++p;
+ if (yych == 'G')
+ goto yy954;
+ if (yych != 'g')
+ goto yy934;
+ yy954:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy955;
+ if (yych != 'e')
+ goto yy934;
+ yy955:
+ yych = *++p;
+ if (yych != '/')
+ goto yy934;
+ yych = *++p;
+ if (yych <= 'W') {
+ if (yych <= 'J') {
+ if (yych == 'G')
+ goto yy957;
+ if (yych <= 'I')
+ goto yy934;
+ goto yy958;
+ } else {
+ if (yych == 'P')
+ goto yy959;
+ if (yych <= 'V')
+ goto yy934;
+ goto yy960;
+ }
+ } else {
+ if (yych <= 'j') {
+ if (yych == 'g')
+ goto yy957;
+ if (yych <= 'i')
+ goto yy934;
+ goto yy958;
+ } else {
+ if (yych <= 'p') {
+ if (yych <= 'o')
+ goto yy934;
+ goto yy959;
+ } else {
+ if (yych == 'w')
+ goto yy960;
+ goto yy934;
+ }
+ }
+ }
+ yy957:
+ yych = *++p;
+ if (yych == 'I')
+ goto yy961;
+ if (yych == 'i')
+ goto yy961;
+ goto yy934;
+ yy958:
+ yych = *++p;
+ if (yych == 'P')
+ goto yy962;
+ if (yych == 'p')
+ goto yy962;
+ goto yy934;
+ yy959:
+ yych = *++p;
+ if (yych == 'N')
+ goto yy963;
+ if (yych == 'n')
+ goto yy963;
+ goto yy934;
+ yy960:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy964;
+ if (yych == 'e')
+ goto yy964;
+ goto yy934;
+ yy961:
+ yych = *++p;
+ if (yych == 'F')
+ goto yy965;
+ if (yych == 'f')
+ goto yy965;
+ goto yy934;
+ yy962:
+ yych = *++p;
+ if (yych == 'E')
+ goto yy963;
+ if (yych != 'e')
+ goto yy934;
+ yy963:
+ yych = *++p;
+ if (yych == 'G')
+ goto yy965;
+ if (yych == 'g')
+ goto yy965;
+ goto yy934;
+ yy964:
+ yych = *++p;
+ if (yych == 'B')
+ goto yy967;
+ if (yych == 'b')
+ goto yy967;
+ goto yy934;
+ yy965:
+ ++p;
+ { return 0; }
+ yy967:
+ yych = *++p;
+ if (yych == 'P')
+ goto yy965;
+ if (yych == 'p')
+ goto yy965;
+ goto yy934;
+ }
+}
diff --git a/include/cmark/scanners.h b/include/cmark/scanners.h
new file mode 100644
index 0000000..207f91a
--- /dev/null
+++ b/include/cmark/scanners.h
@@ -0,0 +1,55 @@
+#include "cmark.h"
+#include "chunk.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c,
+ bufsize_t offset);
+bufsize_t _scan_scheme(const unsigned char *p);
+bufsize_t _scan_autolink_uri(const unsigned char *p);
+bufsize_t _scan_autolink_email(const unsigned char *p);
+bufsize_t _scan_html_tag(const unsigned char *p);
+bufsize_t _scan_html_block_start(const unsigned char *p);
+bufsize_t _scan_html_block_start_7(const unsigned char *p);
+bufsize_t _scan_html_block_end_1(const unsigned char *p);
+bufsize_t _scan_html_block_end_2(const unsigned char *p);
+bufsize_t _scan_html_block_end_3(const unsigned char *p);
+bufsize_t _scan_html_block_end_4(const unsigned char *p);
+bufsize_t _scan_html_block_end_5(const unsigned char *p);
+bufsize_t _scan_link_title(const unsigned char *p);
+bufsize_t _scan_spacechars(const unsigned char *p);
+bufsize_t _scan_atx_heading_start(const unsigned char *p);
+bufsize_t _scan_setext_heading_line(const unsigned char *p);
+bufsize_t _scan_thematic_break(const unsigned char *p);
+bufsize_t _scan_open_code_fence(const unsigned char *p);
+bufsize_t _scan_close_code_fence(const unsigned char *p);
+bufsize_t _scan_entity(const unsigned char *p);
+bufsize_t _scan_dangerous_url(const unsigned char *p);
+
+#define scan_scheme(c, n) _scan_at(&_scan_scheme, c, n)
+#define scan_autolink_uri(c, n) _scan_at(&_scan_autolink_uri, c, n)
+#define scan_autolink_email(c, n) _scan_at(&_scan_autolink_email, c, n)
+#define scan_html_tag(c, n) _scan_at(&_scan_html_tag, c, n)
+#define scan_html_block_start(c, n) _scan_at(&_scan_html_block_start, c, n)
+#define scan_html_block_start_7(c, n) _scan_at(&_scan_html_block_start_7, c, n)
+#define scan_html_block_end_1(c, n) _scan_at(&_scan_html_block_end_1, c, n)
+#define scan_html_block_end_2(c, n) _scan_at(&_scan_html_block_end_2, c, n)
+#define scan_html_block_end_3(c, n) _scan_at(&_scan_html_block_end_3, c, n)
+#define scan_html_block_end_4(c, n) _scan_at(&_scan_html_block_end_4, c, n)
+#define scan_html_block_end_5(c, n) _scan_at(&_scan_html_block_end_5, c, n)
+#define scan_link_title(c, n) _scan_at(&_scan_link_title, c, n)
+#define scan_spacechars(c, n) _scan_at(&_scan_spacechars, c, n)
+#define scan_atx_heading_start(c, n) _scan_at(&_scan_atx_heading_start, c, n)
+#define scan_setext_heading_line(c, n) \
+ _scan_at(&_scan_setext_heading_line, c, n)
+#define scan_thematic_break(c, n) _scan_at(&_scan_thematic_break, c, n)
+#define scan_open_code_fence(c, n) _scan_at(&_scan_open_code_fence, c, n)
+#define scan_close_code_fence(c, n) _scan_at(&_scan_close_code_fence, c, n)
+#define scan_entity(c, n) _scan_at(&_scan_entity, c, n)
+#define scan_dangerous_url(c, n) _scan_at(&_scan_dangerous_url, c, n)
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/cmark/scanners.re b/include/cmark/scanners.re
new file mode 100644
index 0000000..457efaf
--- /dev/null
+++ b/include/cmark/scanners.re
@@ -0,0 +1,320 @@
+#include
+#include "chunk.h"
+#include "scanners.h"
+
+bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c, bufsize_t offset)
+{
+ bufsize_t res;
+ unsigned char *ptr = (unsigned char *)c->data;
+
+ if (ptr == NULL || offset > c->len) {
+ return 0;
+ } else {
+ unsigned char lim = ptr[c->len];
+
+ ptr[c->len] = '\0';
+ res = scanner(ptr + offset);
+ ptr[c->len] = lim;
+ }
+
+ return res;
+}
+
+/*!re2c
+ re2c:define:YYCTYPE = "unsigned char";
+ re2c:define:YYCURSOR = p;
+ re2c:define:YYMARKER = marker;
+ re2c:define:YYCTXMARKER = marker;
+ re2c:yyfill:enable = 0;
+
+ wordchar = [^\x00-\x20];
+
+ spacechar = [ \t\v\f\r\n];
+
+ reg_char = [^\\()\x00-\x20];
+
+ escaped_char = [\\][!"#$%&'()*+,./:;<=>?@[\\\]^_`{|}~-];
+
+ tagname = [A-Za-z][A-Za-z0-9-]*;
+
+ blocktagname = 'address'|'article'|'aside'|'base'|'basefont'|'blockquote'|'body'|'caption'|'center'|'col'|'colgroup'|'dd'|'details'|'dialog'|'dir'|'div'|'dl'|'dt'|'fieldset'|'figcaption'|'figure'|'footer'|'form'|'frame'|'frameset'|'h1'|'h2'|'h3'|'h4'|'h5'|'h6'|'head'|'header'|'hr'|'html'|'iframe'|'legend'|'li'|'link'|'main'|'menu'|'menuitem'|'nav'|'noframes'|'ol'|'optgroup'|'option'|'p'|'param'|'section'|'source'|'title'|'summary'|'table'|'tbody'|'td'|'tfoot'|'th'|'thead'|'title'|'tr'|'track'|'ul';
+
+ attributename = [a-zA-Z_:][a-zA-Z0-9:._-]*;
+
+ unquotedvalue = [^ \t\r\n\v\f"'=<>`\x00]+;
+ singlequotedvalue = ['][^'\x00]*['];
+ doublequotedvalue = ["][^"\x00]*["];
+
+ attributevalue = unquotedvalue | singlequotedvalue | doublequotedvalue;
+
+ attributevaluespec = spacechar* [=] spacechar* attributevalue;
+
+ attribute = spacechar+ attributename attributevaluespec?;
+
+ opentag = tagname attribute* spacechar* [/]? [>];
+ closetag = [/] tagname spacechar* [>];
+
+ htmlcomment = "!---->" | ("!--" ([-]? [^\x00>-]) ([-]? [^\x00-])* "-->");
+
+ processinginstruction = "?" ([^?>\x00]+ | [?][^>\x00] | [>])* "?>";
+
+ declaration = "!" [A-Z]+ spacechar+ [^>\x00]* ">";
+
+ cdata = "![CDATA[" ([^\]\x00]+ | "]" [^\]\x00] | "]]" [^>\x00])* "]]>";
+
+ htmltag = opentag | closetag | htmlcomment | processinginstruction |
+ declaration | cdata;
+
+ in_parens_nosp = [(] (reg_char|escaped_char|[\\])* [)];
+
+ in_double_quotes = ["] (escaped_char|[^"\x00])* ["];
+ in_single_quotes = ['] (escaped_char|[^'\x00])* ['];
+ in_parens = [(] (escaped_char|[^)\x00])* [)];
+
+ scheme = [A-Za-z][A-Za-z0-9.+-]{1,31};
+*/
+
+// Try to match a scheme including colon.
+bufsize_t _scan_scheme(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ scheme [:] { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Try to match URI autolink after first <, returning number of chars matched.
+bufsize_t _scan_autolink_uri(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ scheme [:][^\x00-\x20<>]*[>] { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Try to match email autolink after first <, returning num of chars matched.
+bufsize_t _scan_autolink_email(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ [a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+
+ [@]
+ [a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?
+ ([.][a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*
+ [>] { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Try to match an HTML tag after first <, returning num of chars matched.
+bufsize_t _scan_html_tag(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ htmltag { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Try to match an HTML block tag start line, returning
+// an integer code for the type of block (1-6, matching the spec).
+// #7 is handled by a separate function, below.
+bufsize_t _scan_html_block_start(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+/*!re2c
+ [<] ('script'|'pre'|'style') (spacechar | [>]) { return 1; }
+ '' { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Try to match an HTML block end line of type 3
+bufsize_t _scan_html_block_end_3(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ [^\n\x00]* '?>' { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Try to match an HTML block end line of type 4
+bufsize_t _scan_html_block_end_4(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ [^\n\x00]* '>' { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Try to match an HTML block end line of type 5
+bufsize_t _scan_html_block_end_5(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ [^\n\x00]* ']]>' { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// 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).
+bufsize_t _scan_link_title(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ ["] (escaped_char|[^"\x00])* ["] { return (bufsize_t)(p - start); }
+ ['] (escaped_char|[^'\x00])* ['] { return (bufsize_t)(p - start); }
+ [(] (escaped_char|[^)\x00])* [)] { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Match space characters, including newlines.
+bufsize_t _scan_spacechars(const unsigned char *p)
+{
+ const unsigned char *start = p; \
+/*!re2c
+ [ \t\v\f\r\n]+ { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Match ATX heading start.
+bufsize_t _scan_atx_heading_start(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ [#]{1,6} ([ \t]+|[\r\n]) { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Match setext heading line. Return 1 for level-1 heading,
+// 2 for level-2, 0 for no match.
+bufsize_t _scan_setext_heading_line(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+/*!re2c
+ [=]+ [ \t]* [\r\n] { return 1; }
+ [-]+ [ \t]* [\r\n] { return 2; }
+ * { return 0; }
+*/
+}
+
+// Scan a thematic break 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."
+bufsize_t _scan_thematic_break(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ ([*][ \t]*){3,} [ \t]* [\r\n] { return (bufsize_t)(p - start); }
+ ([_][ \t]*){3,} [ \t]* [\r\n] { return (bufsize_t)(p - start); }
+ ([-][ \t]*){3,} [ \t]* [\r\n] { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Scan an opening code fence.
+bufsize_t _scan_open_code_fence(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ [`]{3,} / [^`\r\n\x00]*[\r\n] { return (bufsize_t)(p - start); }
+ [~]{3,} / [^\r\n\x00]*[\r\n] { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Scan a closing code fence with length at least len.
+bufsize_t _scan_close_code_fence(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ [`]{3,} / [ \t]*[\r\n] { return (bufsize_t)(p - start); }
+ [~]{3,} / [ \t]*[\r\n] { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Scans an entity.
+// Returns number of chars matched.
+bufsize_t _scan_entity(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ [&] ([#] ([Xx][A-Fa-f0-9]{1,6}|[0-9]{1,7}) |[A-Za-z][A-Za-z0-9]{1,31} ) [;]
+ { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
+// Returns positive value if a URL begins in a way that is potentially
+// dangerous, with javascript:, vbscript:, file:, or data:, otherwise 0.
+bufsize_t _scan_dangerous_url(const unsigned char *p)
+{
+ const unsigned char *marker = NULL;
+ const unsigned char *start = p;
+/*!re2c
+ 'data:image/' ('png'|'gif'|'jpeg'|'webp') { return 0; }
+ 'javascript:' | 'vbscript:' | 'file:' | 'data:' { return (bufsize_t)(p - start); }
+ * { return 0; }
+*/
+}
+
diff --git a/include/cmark/utf8.c b/include/cmark/utf8.c
new file mode 100644
index 0000000..c29bbf7
--- /dev/null
+++ b/include/cmark/utf8.c
@@ -0,0 +1,317 @@
+#include
+#include
+#include
+
+#include "cmark_ctype.h"
+#include "utf8.h"
+
+static const int8_t utf8proc_utf8class[256] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static void encode_unknown(cmark_strbuf *buf) {
+ static const uint8_t repl[] = {239, 191, 189};
+ cmark_strbuf_put(buf, repl, 3);
+}
+
+static int utf8proc_charlen(const uint8_t *str, bufsize_t str_len) {
+ int length, i;
+
+ if (!str_len)
+ return 0;
+
+ length = utf8proc_utf8class[str[0]];
+
+ if (!length)
+ return -1;
+
+ if (str_len >= 0 && (bufsize_t)length > str_len)
+ return -str_len;
+
+ for (i = 1; i < length; i++) {
+ if ((str[i] & 0xC0) != 0x80)
+ return -i;
+ }
+
+ return length;
+}
+
+// Validate a single UTF-8 character according to RFC 3629.
+static int utf8proc_valid(const uint8_t *str, bufsize_t str_len) {
+ int length = utf8proc_utf8class[str[0]];
+
+ if (!length)
+ return -1;
+
+ if ((bufsize_t)length > str_len)
+ return -str_len;
+
+ switch (length) {
+ case 2:
+ if ((str[1] & 0xC0) != 0x80)
+ return -1;
+ if (str[0] < 0xC2) {
+ // Overlong
+ return -length;
+ }
+ break;
+
+ case 3:
+ if ((str[1] & 0xC0) != 0x80)
+ return -1;
+ if ((str[2] & 0xC0) != 0x80)
+ return -2;
+ if (str[0] == 0xE0) {
+ if (str[1] < 0xA0) {
+ // Overlong
+ return -length;
+ }
+ } else if (str[0] == 0xED) {
+ if (str[1] >= 0xA0) {
+ // Surrogate
+ return -length;
+ }
+ }
+ break;
+
+ case 4:
+ if ((str[1] & 0xC0) != 0x80)
+ return -1;
+ if ((str[2] & 0xC0) != 0x80)
+ return -2;
+ if ((str[3] & 0xC0) != 0x80)
+ return -3;
+ if (str[0] == 0xF0) {
+ if (str[1] < 0x90) {
+ // Overlong
+ return -length;
+ }
+ } else if (str[0] >= 0xF4) {
+ if (str[0] > 0xF4 || str[1] >= 0x90) {
+ // Above 0x10FFFF
+ return -length;
+ }
+ }
+ break;
+ }
+
+ return length;
+}
+
+void cmark_utf8proc_check(cmark_strbuf *ob, const uint8_t *line,
+ bufsize_t size) {
+ bufsize_t i = 0;
+
+ while (i < size) {
+ bufsize_t org = i;
+ int charlen = 0;
+
+ while (i < size) {
+ if (line[i] < 0x80 && line[i] != 0) {
+ i++;
+ } else if (line[i] >= 0x80) {
+ charlen = utf8proc_valid(line + i, size - i);
+ if (charlen < 0) {
+ charlen = -charlen;
+ break;
+ }
+ i += charlen;
+ } else if (line[i] == 0) {
+ // ASCII NUL is technically valid but rejected
+ // for security reasons.
+ charlen = 1;
+ break;
+ }
+ }
+
+ if (i > org) {
+ cmark_strbuf_put(ob, line + org, i - org);
+ }
+
+ if (i >= size) {
+ break;
+ } else {
+ // Invalid UTF-8
+ encode_unknown(ob);
+ i += charlen;
+ }
+ }
+}
+
+int cmark_utf8proc_iterate(const uint8_t *str, bufsize_t str_len,
+ int32_t *dst) {
+ int length;
+ int32_t uc = -1;
+
+ *dst = -1;
+ length = utf8proc_charlen(str, str_len);
+ if (length < 0)
+ return -1;
+
+ switch (length) {
+ case 1:
+ uc = str[0];
+ break;
+ case 2:
+ uc = ((str[0] & 0x1F) << 6) + (str[1] & 0x3F);
+ if (uc < 0x80)
+ uc = -1;
+ break;
+ case 3:
+ uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) << 6) + (str[2] & 0x3F);
+ if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000))
+ uc = -1;
+ break;
+ case 4:
+ uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12) +
+ ((str[2] & 0x3F) << 6) + (str[3] & 0x3F);
+ if (uc < 0x10000 || uc >= 0x110000)
+ uc = -1;
+ break;
+ }
+
+ if (uc < 0)
+ return -1;
+
+ *dst = uc;
+ return length;
+}
+
+void cmark_utf8proc_encode_char(int32_t uc, cmark_strbuf *buf) {
+ uint8_t dst[4];
+ bufsize_t len = 0;
+
+ assert(uc >= 0);
+
+ if (uc < 0x80) {
+ dst[0] = (uint8_t)(uc);
+ len = 1;
+ } else if (uc < 0x800) {
+ dst[0] = (uint8_t)(0xC0 + (uc >> 6));
+ dst[1] = 0x80 + (uc & 0x3F);
+ len = 2;
+ } else if (uc == 0xFFFF) {
+ dst[0] = 0xFF;
+ len = 1;
+ } else if (uc == 0xFFFE) {
+ dst[0] = 0xFE;
+ len = 1;
+ } else if (uc < 0x10000) {
+ dst[0] = (uint8_t)(0xE0 + (uc >> 12));
+ dst[1] = 0x80 + ((uc >> 6) & 0x3F);
+ dst[2] = 0x80 + (uc & 0x3F);
+ len = 3;
+ } else if (uc < 0x110000) {
+ dst[0] = (uint8_t)(0xF0 + (uc >> 18));
+ dst[1] = 0x80 + ((uc >> 12) & 0x3F);
+ dst[2] = 0x80 + ((uc >> 6) & 0x3F);
+ dst[3] = 0x80 + (uc & 0x3F);
+ len = 4;
+ } else {
+ encode_unknown(buf);
+ return;
+ }
+
+ cmark_strbuf_put(buf, dst, len);
+}
+
+void cmark_utf8proc_case_fold(cmark_strbuf *dest, const uint8_t *str,
+ bufsize_t len) {
+ int32_t c;
+
+#define bufpush(x) cmark_utf8proc_encode_char(x, dest)
+
+ while (len > 0) {
+ bufsize_t char_len = cmark_utf8proc_iterate(str, len, &c);
+
+ if (char_len >= 0) {
+#include "case_fold_switch.inc"
+ } else {
+ encode_unknown(dest);
+ char_len = -char_len;
+ }
+
+ str += char_len;
+ len -= char_len;
+ }
+}
+
+// matches anything in the Zs class, plus LF, CR, TAB, FF.
+int cmark_utf8proc_is_space(int32_t uc) {
+ return (uc == 9 || uc == 10 || uc == 12 || uc == 13 || uc == 32 ||
+ uc == 160 || uc == 5760 || (uc >= 8192 && uc <= 8202) || uc == 8239 ||
+ uc == 8287 || uc == 12288);
+}
+
+// matches anything in the P[cdefios] classes.
+int cmark_utf8proc_is_punctuation(int32_t uc) {
+ return (
+ (uc < 128 && cmark_ispunct((char)uc)) || uc == 161 || uc == 167 ||
+ uc == 171 || uc == 182 || uc == 183 || uc == 187 || uc == 191 ||
+ uc == 894 || uc == 903 || (uc >= 1370 && uc <= 1375) || uc == 1417 ||
+ uc == 1418 || uc == 1470 || uc == 1472 || uc == 1475 || uc == 1478 ||
+ uc == 1523 || uc == 1524 || uc == 1545 || uc == 1546 || uc == 1548 ||
+ uc == 1549 || uc == 1563 || uc == 1566 || uc == 1567 ||
+ (uc >= 1642 && uc <= 1645) || uc == 1748 || (uc >= 1792 && uc <= 1805) ||
+ (uc >= 2039 && uc <= 2041) || (uc >= 2096 && uc <= 2110) || uc == 2142 ||
+ uc == 2404 || uc == 2405 || uc == 2416 || uc == 2800 || uc == 3572 ||
+ uc == 3663 || uc == 3674 || uc == 3675 || (uc >= 3844 && uc <= 3858) ||
+ uc == 3860 || (uc >= 3898 && uc <= 3901) || uc == 3973 ||
+ (uc >= 4048 && uc <= 4052) || uc == 4057 || uc == 4058 ||
+ (uc >= 4170 && uc <= 4175) || uc == 4347 || (uc >= 4960 && uc <= 4968) ||
+ uc == 5120 || uc == 5741 || uc == 5742 || uc == 5787 || uc == 5788 ||
+ (uc >= 5867 && uc <= 5869) || uc == 5941 || uc == 5942 ||
+ (uc >= 6100 && uc <= 6102) || (uc >= 6104 && uc <= 6106) ||
+ (uc >= 6144 && uc <= 6154) || uc == 6468 || uc == 6469 || uc == 6686 ||
+ uc == 6687 || (uc >= 6816 && uc <= 6822) || (uc >= 6824 && uc <= 6829) ||
+ (uc >= 7002 && uc <= 7008) || (uc >= 7164 && uc <= 7167) ||
+ (uc >= 7227 && uc <= 7231) || uc == 7294 || uc == 7295 ||
+ (uc >= 7360 && uc <= 7367) || uc == 7379 || (uc >= 8208 && uc <= 8231) ||
+ (uc >= 8240 && uc <= 8259) || (uc >= 8261 && uc <= 8273) ||
+ (uc >= 8275 && uc <= 8286) || uc == 8317 || uc == 8318 || uc == 8333 ||
+ uc == 8334 || (uc >= 8968 && uc <= 8971) || uc == 9001 || uc == 9002 ||
+ (uc >= 10088 && uc <= 10101) || uc == 10181 || uc == 10182 ||
+ (uc >= 10214 && uc <= 10223) || (uc >= 10627 && uc <= 10648) ||
+ (uc >= 10712 && uc <= 10715) || uc == 10748 || uc == 10749 ||
+ (uc >= 11513 && uc <= 11516) || uc == 11518 || uc == 11519 ||
+ uc == 11632 || (uc >= 11776 && uc <= 11822) ||
+ (uc >= 11824 && uc <= 11842) || (uc >= 12289 && uc <= 12291) ||
+ (uc >= 12296 && uc <= 12305) || (uc >= 12308 && uc <= 12319) ||
+ uc == 12336 || uc == 12349 || uc == 12448 || uc == 12539 || uc == 42238 ||
+ uc == 42239 || (uc >= 42509 && uc <= 42511) || uc == 42611 ||
+ uc == 42622 || (uc >= 42738 && uc <= 42743) ||
+ (uc >= 43124 && uc <= 43127) || uc == 43214 || uc == 43215 ||
+ (uc >= 43256 && uc <= 43258) || uc == 43310 || uc == 43311 ||
+ uc == 43359 || (uc >= 43457 && uc <= 43469) || uc == 43486 ||
+ uc == 43487 || (uc >= 43612 && uc <= 43615) || uc == 43742 ||
+ uc == 43743 || uc == 43760 || uc == 43761 || uc == 44011 || uc == 64830 ||
+ uc == 64831 || (uc >= 65040 && uc <= 65049) ||
+ (uc >= 65072 && uc <= 65106) || (uc >= 65108 && uc <= 65121) ||
+ uc == 65123 || uc == 65128 || uc == 65130 || uc == 65131 ||
+ (uc >= 65281 && uc <= 65283) || (uc >= 65285 && uc <= 65290) ||
+ (uc >= 65292 && uc <= 65295) || uc == 65306 || uc == 65307 ||
+ uc == 65311 || uc == 65312 || (uc >= 65339 && uc <= 65341) ||
+ uc == 65343 || uc == 65371 || uc == 65373 ||
+ (uc >= 65375 && uc <= 65381) || (uc >= 65792 && uc <= 65794) ||
+ uc == 66463 || uc == 66512 || uc == 66927 || uc == 67671 || uc == 67871 ||
+ uc == 67903 || (uc >= 68176 && uc <= 68184) || uc == 68223 ||
+ (uc >= 68336 && uc <= 68342) || (uc >= 68409 && uc <= 68415) ||
+ (uc >= 68505 && uc <= 68508) || (uc >= 69703 && uc <= 69709) ||
+ uc == 69819 || uc == 69820 || (uc >= 69822 && uc <= 69825) ||
+ (uc >= 69952 && uc <= 69955) || uc == 70004 || uc == 70005 ||
+ (uc >= 70085 && uc <= 70088) || uc == 70093 ||
+ (uc >= 70200 && uc <= 70205) || uc == 70854 ||
+ (uc >= 71105 && uc <= 71113) || (uc >= 71233 && uc <= 71235) ||
+ (uc >= 74864 && uc <= 74868) || uc == 92782 || uc == 92783 ||
+ uc == 92917 || (uc >= 92983 && uc <= 92987) || uc == 92996 ||
+ uc == 113823);
+}
diff --git a/include/cmark/utf8.h b/include/cmark/utf8.h
new file mode 100644
index 0000000..8e45714
--- /dev/null
+++ b/include/cmark/utf8.h
@@ -0,0 +1,24 @@
+#ifndef CMARK_UTF8_H
+#define CMARK_UTF8_H
+
+#include
+#include "buffer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void cmark_utf8proc_case_fold(cmark_strbuf *dest, const uint8_t *str,
+ bufsize_t len);
+void cmark_utf8proc_encode_char(int32_t uc, cmark_strbuf *buf);
+int cmark_utf8proc_iterate(const uint8_t *str, bufsize_t str_len, int32_t *dst);
+void cmark_utf8proc_check(cmark_strbuf *dest, const uint8_t *line,
+ bufsize_t size);
+int cmark_utf8proc_is_space(int32_t uc);
+int cmark_utf8proc_is_punctuation(int32_t uc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/cmark/xml.c b/include/cmark/xml.c
new file mode 100644
index 0000000..48674cc
--- /dev/null
+++ b/include/cmark/xml.c
@@ -0,0 +1,170 @@
+#include
+#include
+#include
+#include
+
+#include "config.h"
+#include "cmark.h"
+#include "node.h"
+#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,
+ bufsize_t length) {
+ houdini_escape_html0(dest, source, length, 0);
+}
+
+struct render_state {
+ cmark_strbuf *xml;
+ int indent;
+};
+
+static CMARK_INLINE void indent(struct render_state *state) {
+ int i;
+ for (i = 0; i < state->indent; i++) {
+ cmark_strbuf_putc(state->xml, ' ');
+ }
+}
+
+static int S_render_node(cmark_node *node, cmark_event_type ev_type,
+ struct render_state *state, int options) {
+ cmark_strbuf *xml = state->xml;
+ bool literal = false;
+ cmark_delim_type delim;
+ bool entering = (ev_type == CMARK_EVENT_ENTER);
+ char buffer[BUFFER_SIZE];
+
+ if (entering) {
+ indent(state);
+ cmark_strbuf_putc(xml, '<');
+ cmark_strbuf_puts(xml, cmark_node_get_type_string(node));
+
+ if (options & CMARK_OPT_SOURCEPOS && node->start_line != 0) {
+ snprintf(buffer, BUFFER_SIZE, " sourcepos=\"%d:%d-%d:%d\"",
+ node->start_line, node->start_column, node->end_line,
+ node->end_column);
+ cmark_strbuf_puts(xml, buffer);
+ }
+
+ literal = false;
+
+ switch (node->type) {
+ case CMARK_NODE_DOCUMENT:
+ cmark_strbuf_puts(xml, " xmlns=\"http://commonmark.org/xml/1.0\"");
+ break;
+ case CMARK_NODE_TEXT:
+ case CMARK_NODE_CODE:
+ case CMARK_NODE_HTML_BLOCK:
+ case CMARK_NODE_HTML_INLINE:
+ cmark_strbuf_puts(xml, " xml:space=\"preserve\">");
+ escape_xml(xml, node->as.literal.data, node->as.literal.len);
+ cmark_strbuf_puts(xml, "");
+ cmark_strbuf_puts(xml, cmark_node_get_type_string(node));
+ literal = true;
+ break;
+ case CMARK_NODE_LIST:
+ switch (cmark_node_get_list_type(node)) {
+ case CMARK_ORDERED_LIST:
+ cmark_strbuf_puts(xml, " type=\"ordered\"");
+ snprintf(buffer, BUFFER_SIZE, " start=\"%d\"",
+ cmark_node_get_list_start(node));
+ cmark_strbuf_puts(xml, buffer);
+ delim = cmark_node_get_list_delim(node);
+ if (delim == CMARK_PAREN_DELIM) {
+ cmark_strbuf_puts(xml, " delim=\"paren\"");
+ } else if (delim == CMARK_PERIOD_DELIM) {
+ cmark_strbuf_puts(xml, " delim=\"period\"");
+ }
+ break;
+ case CMARK_BULLET_LIST:
+ cmark_strbuf_puts(xml, " type=\"bullet\"");
+ break;
+ default:
+ break;
+ }
+ snprintf(buffer, BUFFER_SIZE, " tight=\"%s\"",
+ (cmark_node_get_list_tight(node) ? "true" : "false"));
+ cmark_strbuf_puts(xml, buffer);
+ break;
+ case CMARK_NODE_HEADING:
+ snprintf(buffer, BUFFER_SIZE, " level=\"%d\"", node->as.heading.level);
+ cmark_strbuf_puts(xml, buffer);
+ break;
+ case CMARK_NODE_CODE_BLOCK:
+ if (node->as.code.info.len > 0) {
+ cmark_strbuf_puts(xml, " info=\"");
+ escape_xml(xml, node->as.code.info.data, node->as.code.info.len);
+ cmark_strbuf_putc(xml, '"');
+ }
+ cmark_strbuf_puts(xml, " xml:space=\"preserve\">");
+ escape_xml(xml, node->as.code.literal.data, node->as.code.literal.len);
+ cmark_strbuf_puts(xml, "");
+ cmark_strbuf_puts(xml, cmark_node_get_type_string(node));
+ literal = true;
+ break;
+ case CMARK_NODE_CUSTOM_BLOCK:
+ case CMARK_NODE_CUSTOM_INLINE:
+ cmark_strbuf_puts(xml, " on_enter=\"");
+ escape_xml(xml, node->as.custom.on_enter.data,
+ node->as.custom.on_enter.len);
+ cmark_strbuf_putc(xml, '"');
+ cmark_strbuf_puts(xml, " on_exit=\"");
+ escape_xml(xml, node->as.custom.on_exit.data,
+ node->as.custom.on_exit.len);
+ cmark_strbuf_putc(xml, '"');
+ break;
+ case CMARK_NODE_LINK:
+ case CMARK_NODE_IMAGE:
+ cmark_strbuf_puts(xml, " destination=\"");
+ escape_xml(xml, node->as.link.url.data, node->as.link.url.len);
+ cmark_strbuf_putc(xml, '"');
+ cmark_strbuf_puts(xml, " title=\"");
+ escape_xml(xml, node->as.link.title.data, node->as.link.title.len);
+ cmark_strbuf_putc(xml, '"');
+ break;
+ default:
+ break;
+ }
+ if (node->first_child) {
+ state->indent += 2;
+ } else if (!literal) {
+ cmark_strbuf_puts(xml, " /");
+ }
+ cmark_strbuf_puts(xml, ">\n");
+
+ } else if (node->first_child) {
+ state->indent -= 2;
+ indent(state);
+ cmark_strbuf_puts(xml, "");
+ cmark_strbuf_puts(xml, cmark_node_get_type_string(node));
+ cmark_strbuf_puts(xml, ">\n");
+ }
+
+ return 1;
+}
+
+char *cmark_render_xml(cmark_node *root, int options) {
+ char *result;
+ cmark_strbuf xml = CMARK_BUF_INIT(cmark_node_mem(root));
+ cmark_event_type ev_type;
+ cmark_node *cur;
+ struct render_state state = {&xml, 0};
+
+ cmark_iter *iter = cmark_iter_new(root);
+
+ cmark_strbuf_puts(state.xml, "\n");
+ cmark_strbuf_puts(state.xml,
+ "\n");
+ while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
+ cur = cmark_iter_get_node(iter);
+ S_render_node(cur, ev_type, &state, options);
+ }
+ result = (char *)cmark_strbuf_detach(&xml);
+
+ cmark_iter_free(iter);
+ return result;
+}
diff --git a/include/libqmatrixclient b/include/libqmatrixclient
index 3478e69..23bf0e8 160000
--- a/include/libqmatrixclient
+++ b/include/libqmatrixclient
@@ -1 +1 @@
-Subproject commit 3478e691df49b9c0938220db57b03a9c6fcbec8d
+Subproject commit 23bf0e83aec1adaf81d9c50ce2385a98c20e3c93
diff --git a/js/md.js b/js/md.js
deleted file mode 100644
index ceae2ef..0000000
--- a/js/md.js
+++ /dev/null
@@ -1,90 +0,0 @@
-.pragma library
-
-var preg_replace=function(a,b,c,d){void 0===d&&(d=-1);var e=a.substr(a.lastIndexOf(a[0])+1),f=a.substr(1,a.lastIndexOf(a[0])-1),g=RegExp(f,e),i=[],j=0,k=0,l=c,m=[];if(-1===d){do m=g.exec(c),null!==m&&i.push(m);while(null!==m&&-1!==e.indexOf("g"))}else i.push(g.exec(c));for(j=i.length-1;j>-1;j--){for(m=b,k=i[j].length;k>-1;k--)m=m.replace("${"+k+"}",i[j][k]).replace("$"+k,i[j][k]).replace("\\"+k,i[j][k]);l=l.replace(i[j][0],m)}return l};
-
-var markdown_parser = function(str){
-
- var rules = [
- // headers
- ['/(#+)(.*)/g', function(chars, header){
- var level = chars.length;
- return ''+header.trim()+' ';
- }],
- // images
-// ['/\\!\\[([^\\[]+)\\]\\(([^\\(]+)\\)/g', ''],
- // link
- ['/\\[([^\\[]+)\\]\\(([^\\(]+)\\)/g', '\\1'],
- // bold
- ['/(\\*\\*|__)(.*?)\\1/g', '\\2'],
- // emphasis
- ['/(\\*|_)(.*?)\\1/g', '\\2'],
- // strike
- ['/(\\~\\~)(.*?)\\1/g', '\\2'],
- // quote
- ['/\\:\\"(.*?)\\"\\:/g', '\\1
'],
- // unordered list
-// ['/\\n\\*(.*)/g', function(item){
-// return '\n- '+item.trim()+'
\n
';
-// }],
- // ordered list
-// ['/\\n[0-9]+\\.(.*)/g', function(item){
-// return '\n- '+item.trim()+'
\n
';
-// }],
- // blockquote
- ['/\\n\\>(.*)/g', function(str){
- return ''+str.trim()+'
';
- }]
- // paragraphs
-// ['/\\n[^\\n]+\\n/g', function(line){
-// line = line.trim();
-// if(line[0] === '<'){
-// return line;
-// }
-// return '\n'+line+'
\n';
-// }]
- ], fixes = [
- ['/<\\/ul>\n/g', '\n'],
- ['/<\\/ol>\n/g', '\n'],
- ['/<\\/blockquote>\n/g', "\n"]
- ];
-
- var parse_line = function(str){
- str = "\n" + str.trim() + "\n";
- for(var i = 0, j = rules.length; i < j; i++){
- if(typeof rules[i][1] == 'function') {
- var _flag = rules[i][0].substr(rules[i][0].lastIndexOf(rules[i][0][0])+1),
- _pattern = rules[i][0].substr(1, rules[i][0].lastIndexOf(rules[i][0][0])-1),
- reg = new RegExp(_pattern, _flag);
-
- var matches = reg.exec(str);
- if(matches !== null){
- if(matches.length > 1){
- str = preg_replace(rules[i][0], rules[i][1](matches[1], matches[2]), str);
- }
- else
- {
- str = preg_replace(rules[i][0], rules[i][1](matches[0]), str);
- }
- }
- }
- else {
- str = preg_replace(rules[i][0], rules[i][1], str);
- }
- }
- return str.trim();
- };
-
- str = str.split('\n');
- var rtn = [];
- for(var i = 0, j = str.length; i < j; i++){
- rtn.push(parse_line(str[i]));
- }
-
- rtn = rtn.join('\n');
-
- for(i = 0, j = fixes.length; i < j; i++){
- rtn = preg_replace(fixes[i][0], fixes[i][1], rtn);
- }
-
- return rtn;
-};
diff --git a/js/util.js b/js/util.js
deleted file mode 100644
index 6b0ade3..0000000
--- a/js/util.js
+++ /dev/null
@@ -1,12 +0,0 @@
-.pragma library
-
-function pushToStack(stack, page) {
- if(page && stack.currentItem !== page) {
- if(stack.depth === 1) {
- stack.replace(page)
- } else {
- stack.pop(null)
- stack.replace(page)
- }
- }
-}
diff --git a/qml/main.qml b/qml/main.qml
index 216b04d..29aa113 100644
--- a/qml/main.qml
+++ b/qml/main.qml
@@ -1,20 +1,21 @@
-import QtQuick 2.9
-import QtQuick.Controls 2.2
-import QtQuick.Layouts 1.3
-import QtQuick.Controls.Material 2.2
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls.Material 2.12
import Qt.labs.settings 1.0
import Qt.labs.platform 1.0 as Platform
+import Spectral.Panel 2.0
import Spectral.Component 2.0
import Spectral.Page 2.0
+import Spectral.Effect 2.0
import Spectral 0.1
import Spectral.Setting 0.1
-import "qrc:/js/util.js" as Util
-
ApplicationWindow {
- readonly property var currentConnection: accountListView.currentConnection ? accountListView.currentConnection : null
+ Material.theme: MPalette.theme
+ Material.background: MPalette.background
width: 960
height: 640
@@ -26,9 +27,9 @@ ApplicationWindow {
visible: true
title: qsTr("Spectral")
- Material.theme: MSettings.darkTheme ? Material.Dark : Material.Light
-
- Material.accent: spectralController.color(currentConnection ? currentConnection.localUserId : "")
+ background: Rectangle {
+ color: MSettings.darkTheme ? "#303030" : "#FFFFFF"
+ }
Platform.SystemTrayIcon {
visible: MSettings.showTray
@@ -54,353 +55,147 @@ ApplicationWindow {
quitOnLastWindowClosed: !MSettings.showTray
onNotificationClicked: {
- roomPage.enteredRoom = currentConnection.room(roomId)
- roomPage.goToEvent(eventId)
+ roomListForm.enteredRoom = spectralController.connection.room(roomId)
+ roomForm.goToEvent(eventId)
showWindow()
}
onErrorOccured: {
- errorDialog.error = error
- errorDialog.detail = detail
- errorDialog.open()
+ roomListForm.errorControl.error = error
+ roomListForm.errorControl.detail = detail
+ roomListForm.errorControl.visible = true
}
+ onSyncDone: roomListForm.errorControl.visible = false
}
- AccountListModel {
- id: accountListModel
- controller: spectralController
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
}
Dialog {
- property string error
- property string detail
+ property bool busy: false
+ width: 360
x: (window.width - width) / 2
y: (window.height - height) / 2
- id: errorDialog
+ id: loginDialog
- title: error + " Error"
- contentItem: Label { text: errorDialog.detail }
- }
+ parent: ApplicationWindow.overlay
- Component {
- id: loginPage
+ title: "Login"
- Login { controller: spectralController }
- }
+ contentItem: Column {
+ AutoTextField {
+ width: parent.width
- Room {
- id: roomPage
+ id: serverField
- parent: null
+ placeholderText: "Server Address"
+ text: "https://matrix.org"
+ }
- connection: currentConnection
- }
+ AutoTextField {
+ width: parent.width
- Setting {
- id: settingPage
+ id: usernameField
- parent: null
+ placeholderText: "Username"
+ }
- listModel: accountListModel
- }
+ AutoTextField {
+ width: parent.width
- RowLayout {
- anchors.fill: parent
- spacing: 0
+ id: passwordField
- Rectangle {
- Layout.preferredWidth: 64
- Layout.fillHeight: true
-
- id: sideNav
-
- color: Material.primary
-
- ColumnLayout {
- anchors.fill: parent
- spacing: 0
-
- AutoListView {
- property var currentConnection: null
-
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- id: accountListView
-
- model: accountListModel
-
- spacing: 0
-
- clip: true
-
- delegate: Column {
- property bool expanded: accountListView.currentConnection === connection
-
- width: parent.width
-
- spacing: 0
-
- SideNavButton {
- width: parent.width
- height: width
-
- selected: stackView.currentItem === page && currentConnection === connection
-
- ImageItem {
- anchors.fill: parent
- anchors.margins: 12
-
- hint: user.displayName
- source: user.paintable
- }
-
- highlightColor: spectralController.color(user.id)
-
- page: roomPage
-
- onClicked: {
- accountListView.currentConnection = connection
- roomPage.filter = 0
- }
- }
-
- Column {
- width: parent.width
- height: expanded ? implicitHeight : 0
-
- spacing: 0
- clip: true
-
- SideNavButton {
- width: parent.width
- height: width
-
- MaterialIcon {
- anchors.fill: parent
-
- icon: "\ue7f7"
- color: "white"
- }
-
- onClicked: roomPage.filter = 1
- }
-
- SideNavButton {
- width: parent.width
- height: width
-
- MaterialIcon {
- anchors.fill: parent
-
- icon: "\ue7fd"
- color: "white"
- }
-
- onClicked: roomPage.filter = 2
- }
-
- SideNavButton {
- width: parent.width
- height: width
-
- MaterialIcon {
- anchors.fill: parent
-
- icon: "\ue7fb"
- color: "white"
- }
-
- onClicked: roomPage.filter = 3
- }
-
- Behavior on height {
- PropertyAnimation { easing.type: Easing.InOutCubic; duration: 200 }
- }
- }
- }
- }
-
- SideNavButton {
- Layout.fillWidth: true
- Layout.preferredHeight: width
-
- MaterialIcon {
- anchors.fill: parent
-
- icon: "\ue145"
- color: "white"
- }
-
- enabled: !addRoomMenu.opened
- onClicked: addRoomMenu.popup()
-
- Menu {
- id: addRoomMenu
-
- MenuItem {
- text:"New Room"
- onTriggered: addRoomDialog.open()
-
- Dialog {
- id: addRoomDialog
- parent: ApplicationWindow.overlay
-
- x: (window.width - width) / 2
- y: (window.height - height) / 2
- width: 360
-
- title: "New Room"
- modal: true
- standardButtons: Dialog.Ok | Dialog.Cancel
-
- contentItem: Column {
- AutoTextField {
- width: parent.width
-
- id: addRoomDialogNameTextField
-
- placeholderText: "Name"
- }
- AutoTextField {
- width: parent.width
-
- id: addRoomDialogTopicTextField
-
- placeholderText: "Topic"
- }
- }
-
- onAccepted: spectralController.createRoom(currentConnection, addRoomDialogNameTextField.text, addRoomDialogTopicTextField.text)
- }
- }
-
- MenuItem {
- text: "Join Room"
-
- onTriggered: joinRoomDialog.open()
-
- Dialog {
- x: (window.width - width) / 2
- y: (window.height - height) / 2
- width: 360
-
- id: joinRoomDialog
-
- parent: ApplicationWindow.overlay
-
- title: "Input Room Alias or ID"
- modal: true
- standardButtons: Dialog.Ok | Dialog.Cancel
-
- contentItem: AutoTextField {
- id: joinRoomDialogTextField
- placeholderText: "#matrix:matrix.org"
- }
-
- onAccepted: spectralController.joinRoom(currentConnection, joinRoomDialogTextField.text)
- }
- }
-
- MenuItem {
- text: "Direct Chat"
-
- onTriggered: directChatDialog.open()
-
- Dialog {
- x: (window.width - width) / 2
- y: (window.height - height) / 2
- width: 360
-
- id: directChatDialog
-
- parent: ApplicationWindow.overlay
-
- title: "Input User ID"
- modal: true
- standardButtons: Dialog.Ok | Dialog.Cancel
-
- contentItem: AutoTextField {
- id: directChatDialogTextField
- placeholderText: "@bot:matrix.org"
- }
-
- onAccepted: spectralController.createDirectChat(currentConnection, directChatDialogTextField.text)
- }
- }
- }
- }
-
- SideNavButton {
- Layout.fillWidth: true
- Layout.preferredHeight: width
-
- MaterialIcon {
- anchors.fill: parent
-
- icon: "\ue8b8"
- color: "white"
- }
- page: settingPage
- }
-
- SideNavButton {
- Layout.fillWidth: true
- Layout.preferredHeight: width
-
- MaterialIcon {
- anchors.fill: parent
-
- icon: "\ue8ac"
- color: "white"
- }
-
- onClicked: MSettings.confirmOnExit ? confirmExitDialog.open() : Qt.quit()
-
- Dialog {
- x: (window.width - width) / 2
- y: (window.height - height) / 2
- width: 360
-
- id: confirmExitDialog
-
- parent: ApplicationWindow.overlay
-
- title: "Exit"
- modal: true
- standardButtons: Dialog.Ok | Dialog.Cancel
-
- contentItem: Column {
- Label { text: "Exit?" }
- CheckBox {
- text: "Do not ask next time"
- checked: !MSettings.confirmOnExit
-
- onCheckedChanged: MSettings.confirmOnExit = !checked
- }
- }
-
- onAccepted: Qt.quit()
- }
- }
+ placeholderText: "Password"
+ echoMode: TextInput.Password
}
}
- StackView {
+ footer: DialogButtonBox {
+ Button {
+ text: "OK"
+ flat: true
+ enabled: !loginDialog.busy
+
+ onClicked: loginDialog.doLogin()
+ }
+
+ Button {
+ text: "Cancel"
+ flat: true
+ enabled: !loginDialog.busy
+
+ onClicked: loginDialog.close()
+ }
+
+ ToolTip {
+ id: loginButtonTooltip
+
+ }
+ }
+
+ onVisibleChanged: {
+ if (visible) spectralController.onErrorOccured.connect(showError)
+ else spectralController.onErrorOccured.disconnect(showError)
+ }
+
+ function showError(error, detail) {
+ loginDialog.busy = false
+ loginButtonTooltip.text = error + ": " + detail
+ loginButtonTooltip.open()
+ }
+
+ function doLogin() {
+ if (!(serverField.text.startsWith("http") && serverField.text.includes("://"))) {
+ loginButtonTooltip.text = "Server address should start with http(s)://"
+ loginButtonTooltip.open()
+ return
+ }
+
+ loginDialog.busy = true
+ spectralController.loginWithCredentials(serverField.text, usernameField.text, passwordField.text)
+
+ spectralController.connectionAdded.connect(function(conn) {
+ busy = false
+ loginDialog.close()
+ })
+ }
+ }
+
+ SplitView {
+ anchors.fill: parent
+
+ RoomListPanel {
+ width: window.width * 0.35
+ Layout.minimumWidth: 180
+
+ id: roomListForm
+
+ clip: true
+
+ controller: spectralController
+
+ onLeaveRoom: roomForm.saveReadMarker(room)
+ }
+
+ RoomPanel {
Layout.fillWidth: true
- Layout.fillHeight: true
+ Layout.minimumWidth: 480
- id: stackView
+ id: roomForm
- initialItem: roomPage
+ clip: true
+
+ currentRoom: roomListForm.enteredRoom
}
}
Binding {
target: imageProvider
property: "connection"
- value: currentConnection
+ value: spectralController.connection
}
function showWindow() {
@@ -413,9 +208,9 @@ ApplicationWindow {
window.hide()
}
- Component.onCompleted: {
- spectralController.initiated.connect(function() {
- if (spectralController.accountCount == 0) stackView.push(loginPage)
- })
- }
+ Component.onCompleted: {
+ spectralController.initiated.connect(function() {
+ if (spectralController.accountCount == 0) loginDialog.open()
+ })
+ }
}
diff --git a/qtquickcontrols2.conf b/qtquickcontrols2.conf
index 0cc5319..6db2aaf 100644
--- a/qtquickcontrols2.conf
+++ b/qtquickcontrols2.conf
@@ -7,7 +7,7 @@ Style=Material
[Material]
Theme=Light
+Variant=Dense
Primary=#344955
-Accent=#498882
-;Foreground=Black
-;Background=#161616
+Accent=#673AB7
+Font/Family="Roboto,Noto Sans,Noto Color Emoji"
diff --git a/res.qrc b/res.qrc
index 6f4daaa..d5d29dd 100644
--- a/res.qrc
+++ b/res.qrc
@@ -2,30 +2,19 @@
qtquickcontrols2.conf
qml/main.qml
- js/md.js
- js/util.js
imports/Spectral/Component/Emoji/EmojiPicker.qml
imports/Spectral/Component/Emoji/qmldir
imports/Spectral/Component/Timeline/DownloadableContent.qml
- imports/Spectral/Component/Timeline/GenericBubble.qml
imports/Spectral/Component/Timeline/MessageDelegate.qml
imports/Spectral/Component/Timeline/qmldir
imports/Spectral/Component/Timeline/StateDelegate.qml
imports/Spectral/Component/AutoMouseArea.qml
imports/Spectral/Component/MaterialIcon.qml
imports/Spectral/Component/qmldir
- imports/Spectral/Component/SideNavButton.qml
imports/Spectral/Effect/ElevationEffect.qml
imports/Spectral/Effect/qmldir
- imports/Spectral/Menu/MessageContextMenu.qml
- imports/Spectral/Menu/qmldir
- imports/Spectral/Menu/RoomContextMenu.qml
- imports/Spectral/Page/Login.qml
imports/Spectral/Page/qmldir
- imports/Spectral/Page/Room.qml
assets/font/material.ttf
- assets/img/avatar.png
- assets/img/background.jpg
assets/img/icon.icns
assets/img/icon.ico
assets/img/icon.png
@@ -33,25 +22,26 @@
imports/Spectral/Font/MaterialFont.qml
imports/Spectral/Font/qmldir
imports/Spectral/Setting/qmldir
- imports/Spectral/Page/Setting.qml
- imports/Spectral/Page/SettingForm.ui.qml
- imports/Spectral/Page/SettingCategoryDelegate.qml
- imports/Spectral/Page/SettingAccountDelegate.qml
- imports/Spectral/Page/LoginForm.ui.qml
imports/Spectral/Panel/qmldir
imports/Spectral/Panel/RoomDrawer.qml
imports/Spectral/Panel/RoomListPanel.qml
- imports/Spectral/Panel/RoomListPanelForm.ui.qml
imports/Spectral/Panel/RoomPanel.qml
- imports/Spectral/Panel/RoomPanelForm.ui.qml
imports/Spectral/Panel/RoomHeader.qml
- imports/Spectral/Panel/RoomListDelegate.qml
imports/Spectral/Component/ScrollHelper.qml
imports/Spectral/Component/AutoListView.qml
- imports/Spectral/Component/Timeline/TimelineImage.qml
- imports/Spectral/Component/Timeline/TimelineLabel.qml
imports/Spectral/Component/AutoTextField.qml
imports/Spectral/Panel/RoomPanelInput.qml
imports/Spectral/Component/SplitView.qml
+ imports/Spectral/Font/CommonFont.qml
+ imports/Spectral/Component/Timeline/SectionDelegate.qml
+ assets/img/roompanel.svg
+ assets/img/matrix.svg
+ imports/Spectral/Effect/RippleEffect.qml
+ imports/Spectral/Effect/CircleMask.qml
+ assets/img/roompanel-dark.svg
+ imports/Spectral/Component/Timeline/ImageDelegate.qml
+ imports/Spectral/Component/Avatar.qml
+ imports/Spectral/Setting/Palette.qml
+ imports/Spectral/Component/Timeline/FileDelegate.qml
diff --git a/spectral.pro b/spectral.pro
index 8c86282..1631b7b 100644
--- a/spectral.pro
+++ b/spectral.pro
@@ -20,6 +20,12 @@ isEmpty(USE_SYSTEM_SORTFILTERPROXYMODEL) {
isEmpty(USE_SYSTEM_QMATRIXCLIENT) {
USE_SYSTEM_QMATRIXCLIENT = false
}
+isEmpty(USE_SYSTEM_CMARK) {
+ USE_SYSTEM_CMARK = false
+}
+isEmpty(BUNDLE_FONT) {
+ BUNDLE_FONT = false
+}
$$USE_SYSTEM_QMATRIXCLIENT {
PKGCONFIG += QMatrixClient
@@ -33,6 +39,50 @@ $$USE_SYSTEM_SORTFILTERPROXYMODEL {
message("Falling back to built-in SortFilterProxyModel.")
include(include/SortFilterProxyModel/SortFilterProxyModel.pri)
}
+$$USE_SYSTEM_CMARK {
+ PKGCONFIG += libcmark
+} else {
+ message("Falling back to built-in CMark.")
+ INCLUDEPATH += include/cmark
+ HEADERS += \
+ include/cmark/buffer.h \
+ include/cmark/chunk.h \
+ include/cmark/cmark.h \
+ include/cmark/cmark_ctype.h \
+ include/cmark/cmark_export.h \
+ include/cmark/config.h \
+ include/cmark/houdini.h \
+ include/cmark/inlines.h \
+ include/cmark/iterator.h \
+ include/cmark/node.h \
+ include/cmark/parser.h \
+ include/cmark/references.h \
+ include/cmark/render.h \
+ include/cmark/scanners.h \
+ include/cmark/utf8.h
+
+ SOURCES += \
+ include/cmark/blocks.c \
+ include/cmark/buffer.c \
+ include/cmark/cmark.c \
+ include/cmark/cmark_ctype.c \
+ include/cmark/commonmark.c \
+ include/cmark/entities.inc \
+ include/cmark/houdini_href_e.c \
+ include/cmark/houdini_html_e.c \
+ include/cmark/houdini_html_u.c \
+ include/cmark/html.c \
+ include/cmark/inlines.c \
+ include/cmark/iterator.c \
+ include/cmark/latex.c \
+ include/cmark/man.c \
+ include/cmark/node.c \
+ include/cmark/references.c \
+ include/cmark/render.c \
+ include/cmark/scanners.c \
+ include/cmark/utf8.c \
+ include/cmark/xml.c
+}
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
@@ -45,8 +95,14 @@ DEFINES += QT_DEPRECATED_WARNINGS
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-RESOURCES += \
- res.qrc
+RESOURCES += res.qrc
+$$BUNDLE_FONT {
+ message("Bundling fonts.")
+ DEFINES += BUNDLE_FONT
+ RESOURCES += font.qrc
+} else {
+ message("Using fonts from operating system.")
+}
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH += imports/
@@ -94,12 +150,10 @@ HEADERS += \
src/emojimodel.h \
src/spectralroom.h \
src/userlistmodel.h \
- src/imageitem.h \
src/accountlistmodel.h \
src/spectraluser.h \
src/notifications/manager.h \
- src/utils.h \
- src/paintable.h
+ src/utils.h
SOURCES += src/main.cpp \
src/controller.cpp \
@@ -109,11 +163,9 @@ SOURCES += src/main.cpp \
src/emojimodel.cpp \
src/spectralroom.cpp \
src/userlistmodel.cpp \
- src/imageitem.cpp \
src/accountlistmodel.cpp \
src/spectraluser.cpp \
- src/utils.cpp \
- src/paintable.cpp
+ src/utils.cpp
unix:!mac {
SOURCES += src/notifications/managerlinux.cpp
diff --git a/src/controller.cpp b/src/controller.cpp
index 06dffed..c600a4a 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -10,6 +10,8 @@
#include "csapi/joining.h"
#include "csapi/logout.h"
+#include "utils.h"
+
#include
#include
#include
@@ -42,8 +44,8 @@ Controller::Controller(QObject* parent)
Controller::~Controller() {
for (Connection* c : m_connections) {
- c->saveState();
c->stopSync();
+ c->saveState();
}
}
@@ -58,29 +60,29 @@ inline QString accessTokenFileName(const AccountSettings& account) {
void Controller::loginWithCredentials(QString serverAddr, QString user,
QString pass) {
if (!user.isEmpty() && !pass.isEmpty()) {
- Connection* m_connection = new Connection(this);
- m_connection->setHomeserver(QUrl(serverAddr));
- m_connection->connectToServer(user, pass, "");
- connect(m_connection, &Connection::connected, [=] {
- AccountSettings account(m_connection->userId());
+ Connection* conn = new Connection(this);
+ conn->setHomeserver(QUrl(serverAddr));
+ conn->connectToServer(user, pass, "");
+ connect(conn, &Connection::connected, [=] {
+ AccountSettings account(conn->userId());
account.setKeepLoggedIn(true);
account.clearAccessToken(); // Drop the legacy - just in case
- account.setHomeserver(m_connection->homeserver());
- account.setDeviceId(m_connection->deviceId());
+ account.setHomeserver(conn->homeserver());
+ account.setDeviceId(conn->deviceId());
account.setDeviceName("Spectral");
- if (!saveAccessToken(account, m_connection->accessToken()))
+ if (!saveAccessToken(account, conn->accessToken()))
qWarning() << "Couldn't save access token";
account.sync();
- addConnection(m_connection);
+ addConnection(conn);
+ setConnection(conn);
});
- connect(m_connection, &Connection::networkError,
- [=](QString error, QByteArray detail) {
- emit errorOccured("Network", error);
- });
- connect(m_connection, &Connection::loginError,
- [=](QString error, QByteArray detail) {
- emit errorOccured("Login Failed", error);
+ connect(conn, &Connection::networkError,
+ [=](QString error, QString, int, int) {
+ emit errorOccured("Network Error", error);
});
+ connect(conn, &Connection::loginError, [=](QString error, QString) {
+ emit errorOccured("Login Failed", error);
+ });
}
}
@@ -98,6 +100,7 @@ void Controller::logout(Connection* conn) {
conn->stopSync();
emit conn->stateChanged();
emit conn->loggedOut();
+ if (!m_connections.isEmpty()) setConnection(m_connections[0]);
});
connect(job, &LogoutJob::failure, this, [=] {
emit errorOccured("Server-side Logout Failed", job->errorString());
@@ -109,11 +112,12 @@ void Controller::addConnection(Connection* c) {
m_connections.push_back(c);
- connect(c, &Connection::syncDone, this, [=] {
- c->sync(30000);
+ c->setLazyLoading(true);
- static int counter = 0;
- if (++counter % 17 == 2) c->saveState();
+ connect(c, &Connection::syncDone, this, [=] {
+ emit syncDone();
+ c->sync(30000);
+ c->saveState();
});
connect(c, &Connection::loggedOut, this, [=] { dropConnection(c); });
@@ -146,17 +150,17 @@ void Controller::invokeLogin() {
c->loadState();
addConnection(c);
});
- connect(c, &Connection::loginError,
- [=](QString error, QByteArray detail) {
- emit errorOccured("Login Failed", error);
- });
+ connect(c, &Connection::loginError, [=](QString error, QString) {
+ emit errorOccured("Login Failed", error);
+ });
connect(c, &Connection::networkError,
- [=](QString error, QByteArray detail) {
- emit errorOccured("Network", error);
+ [=](QString error, QString, int, int) {
+ emit errorOccured("Network Error", error);
});
c->connectWithToken(account.userId(), accessToken, account.deviceId());
}
}
+ if (!m_connections.isEmpty()) setConnection(m_connections[0]);
emit initiated();
}
@@ -184,7 +188,7 @@ bool Controller::saveAccessToken(const AccountSettings& account,
auto fileDir = QFileInfo(accountTokenFile).dir();
if (!((fileDir.exists() || fileDir.mkpath(".")) &&
accountTokenFile.open(QFile::WriteOnly))) {
- emit errorOccured("Token", "Cannot save access token.");
+ emit errorOccured("I/O Denied", "Cannot save access token.");
} else {
accountTokenFile.write(accessToken);
return true;
@@ -227,19 +231,22 @@ void Controller::playAudio(QUrl localFile) {
connect(player, &QMediaPlayer::stateChanged, [=] { player->deleteLater(); });
}
-QColor Controller::color(QString userId) {
- return QColor(SettingsGroup("UI/Color").value(userId, "#498882").toString());
-}
-
-void Controller::setColor(QString userId, QColor newColor) {
- SettingsGroup("UI/Color").setValue(userId, newColor.name());
-}
-
void Controller::postNotification(const QString& roomId, const QString& eventId,
const QString& roomName,
const QString& senderName,
- const QString& text, const QImage& icon,
- const QUrl& iconPath) {
+ const QString& text, const QImage& icon) {
notificationsManager.postNotification(roomId, eventId, roomName, senderName,
- text, icon, iconPath);
+ text, icon);
+}
+
+int Controller::dpi() {
+ return SettingsGroup("Interface").value("dpi", 100).toInt();
+}
+
+void Controller::setDpi(int dpi) {
+ SettingsGroup("Interface").setValue("dpi", dpi);
+}
+
+QString Controller::removeReply(const QString& text) {
+ return utils::removeReply(text);
}
diff --git a/src/controller.h b/src/controller.h
index 0234fb4..32fc031 100644
--- a/src/controller.h
+++ b/src/controller.h
@@ -20,6 +20,8 @@ class Controller : public QObject {
connectionDropped)
Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed WRITE
setQuitOnLastWindowClosed NOTIFY quitOnLastWindowClosedChanged)
+ Q_PROPERTY(Connection* connection READ connection WRITE setConnection NOTIFY
+ connectionChanged)
public:
explicit Controller(QObject* parent = nullptr);
@@ -30,6 +32,9 @@ class Controller : public QObject {
QVector connections() { return m_connections; }
+ Q_INVOKABLE int dpi();
+ Q_INVOKABLE void setDpi(int dpi);
+
// All the non-Q_INVOKABLE functions.
void addConnection(Connection* c);
void dropConnection(Connection* c);
@@ -47,13 +52,23 @@ class Controller : public QObject {
}
}
- Q_INVOKABLE QColor color(QString userId);
- Q_INVOKABLE void setColor(QString userId, QColor newColor);
+ Connection* connection() {
+ if (m_connection.isNull()) return nullptr;
+ return m_connection;
+ }
+
+ void setConnection(Connection* conn) {
+ if (!conn) return;
+ if (conn == m_connection) return;
+ m_connection = conn;
+ emit connectionChanged();
+ }
private:
QClipboard* m_clipboard = QApplication::clipboard();
NotificationsManager notificationsManager;
QVector m_connections;
+ QPointer m_connection;
QByteArray loadAccessToken(const AccountSettings& account);
bool saveAccessToken(const AccountSettings& account,
@@ -61,17 +76,21 @@ class Controller : public QObject {
void loadSettings();
void saveSettings() const;
+ Q_INVOKABLE QString removeReply(const QString& text);
+
private slots:
void invokeLogin();
signals:
void busyChanged();
void errorOccured(QString error, QString detail);
+ void syncDone();
void connectionAdded(Connection* conn);
void connectionDropped(Connection* conn);
void initiated();
void notificationClicked(const QString roomId, const QString eventId);
void quitOnLastWindowClosedChanged();
+ void connectionChanged();
public slots:
void logout(Connection* conn);
@@ -82,8 +101,7 @@ class Controller : public QObject {
void playAudio(QUrl localFile);
void postNotification(const QString& roomId, const QString& eventId,
const QString& roomName, const QString& senderName,
- const QString& text, const QImage& icon,
- const QUrl& iconPath);
+ const QString& text, const QImage& icon);
};
#endif // CONTROLLER_H
diff --git a/src/imageitem.cpp b/src/imageitem.cpp
deleted file mode 100644
index 91a397b..0000000
--- a/src/imageitem.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "imageitem.h"
-
-#include
-#include
-#include
-
-ImageItem::ImageItem(QQuickItem *parent) : QQuickPaintedItem(parent) {}
-
-inline static QString stringtoColor(QString string) {
- int hash = 0;
- for (int i = 0; i < string.length(); i++)
- hash = string.at(i).unicode() + ((hash << 5) - hash);
- QString colour = "#";
- for (int j = 0; j < 3; j++)
- colour += ("00" + QString::number((hash >> (j * 8)) & 0xFF, 16)).right(2);
- return colour;
-}
-
-inline static QImage getImageFromPaintable(QPointer p, QRectF b) {
- if (p.isNull()) return {};
- QImage image(p->image(int(b.width()), int(b.height())));
- if (image.isNull()) return {};
- return image;
-}
-
-void ImageItem::paint(QPainter *painter) {
- QRectF bounding_rect = boundingRect();
-
- painter->setRenderHint(QPainter::Antialiasing, true);
-
- QImage image(getImageFromPaintable(m_paintable, bounding_rect));
-
- if (image.isNull()) {
- painter->setPen(Qt::NoPen);
- if (m_color.isEmpty())
- painter->setBrush(QColor(stringtoColor(m_hint)));
- else
- painter->setBrush(QColor(m_color));
- if (m_round)
- painter->drawEllipse(0, 0, int(bounding_rect.width()),
- int(bounding_rect.height()));
- else
- painter->drawRect(0, 0, int(bounding_rect.width()),
- int(bounding_rect.height()));
- painter->setPen(QPen(Qt::white, 2));
- QFont font;
- font.setStyleHint(QFont::SansSerif);
-
- font.setPixelSize(int(bounding_rect.width() / 2));
- font.setBold(true);
- painter->setFont(font);
- painter->drawText(
- QRect(0, 0, int(bounding_rect.width()), int(bounding_rect.height())),
- Qt::AlignCenter, m_hint.at(0).toUpper());
- } else {
- QImage scaled = image.scaled(
- int(bounding_rect.width()) + 1, int(bounding_rect.height()) + 1,
- Qt::KeepAspectRatioByExpanding, Qt::FastTransformation);
-
- QPointF center = bounding_rect.center() - scaled.rect().center();
-
- if (m_round) {
- QPainterPath clip;
- clip.addEllipse(
- 0, 0, bounding_rect.width(),
- bounding_rect.height()); // this is the shape we want to clip to
- painter->setClipPath(clip);
- }
-
- painter->drawImage(center, scaled);
- }
-}
-
-void ImageItem::setPaintable(Paintable *paintable) {
- if (!paintable) return;
- if (!m_paintable.isNull()) m_paintable->disconnect(this);
- m_paintable = paintable;
- connect(m_paintable, &Paintable::paintableChanged, this,
- [=] { this->update(); });
- emit paintableChanged();
- update();
-}
-
-void ImageItem::setHint(QString newHint) {
- if (m_hint != newHint) {
- m_hint = newHint;
- emit hintChanged();
- update();
- }
-}
-
-void ImageItem::setDefaultColor(QString color) {
- if (color != m_color) {
- m_color = color;
- emit defaultColorChanged();
- update();
- }
-}
-
-void ImageItem::setRound(bool value) {
- if (m_round != value) {
- m_round = value;
- emit roundChanged();
- update();
- }
-}
diff --git a/src/imageitem.h b/src/imageitem.h
deleted file mode 100644
index a0c6816..0000000
--- a/src/imageitem.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef IMAGEITEM_H
-#define IMAGEITEM_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "paintable.h"
-
-class ImageItem : public QQuickPaintedItem {
- Q_OBJECT
- Q_PROPERTY(Paintable* source READ paintable WRITE setPaintable NOTIFY
- paintableChanged)
- Q_PROPERTY(QString hint READ hint WRITE setHint NOTIFY hintChanged)
- Q_PROPERTY(QString defaultColor READ defaultColor WRITE setDefaultColor NOTIFY
- defaultColorChanged)
- Q_PROPERTY(bool round READ round WRITE setRound NOTIFY roundChanged)
-
- public:
- ImageItem(QQuickItem* parent = nullptr);
-
- void paint(QPainter* painter);
-
- Paintable* paintable() { return m_paintable; }
- void setPaintable(Paintable* paintable);
-
- QString hint() { return m_hint; }
- void setHint(QString hint);
-
- QString defaultColor() { return m_color; }
- void setDefaultColor(QString color);
-
- bool round() { return m_round; }
- void setRound(bool value);
-
- signals:
- void paintableChanged();
- void hintChanged();
- void defaultColorChanged();
- void roundChanged();
-
- private:
- QPointer m_paintable;
- QString m_hint = "H";
- QString m_color;
- bool m_round = true;
-};
-
-#endif // IMAGEITEM_H
diff --git a/src/imageprovider.cpp b/src/imageprovider.cpp
index 85aad34..c067743 100644
--- a/src/imageprovider.cpp
+++ b/src/imageprovider.cpp
@@ -1,79 +1,87 @@
#include "imageprovider.h"
-#include
-#include
-#include
+#include
+#include
+
#include
-#include
+#include
-#include "jobs/mediathumbnailjob.h"
+using QMatrixClient::BaseJob;
+using QMatrixClient::Connection;
-#include "connection.h"
-
-using QMatrixClient::MediaThumbnailJob;
-
-ImageProvider::ImageProvider(QObject* parent)
- : QObject(parent),
- QQuickImageProvider(
- QQmlImageProviderBase::Image,
- QQmlImageProviderBase::ForceAsynchronousImageLoading) {
-#if (QT_VERSION < QT_VERSION_CHECK(5, 10, 0))
- qRegisterMetaType();
-#endif
+ThumbnailResponse::ThumbnailResponse(Connection* c, QString mediaId,
+ const QSize& requestedSize)
+ : c(c),
+ mediaId(std::move(mediaId)),
+ requestedSize(requestedSize),
+ errorStr("Image request hasn't started") {
+ moveToThread(c->thread());
+ if (requestedSize.isEmpty()) {
+ errorStr.clear();
+ emit finished();
+ return;
+ }
+ // Execute a request on the main thread asynchronously
+ QMetaObject::invokeMethod(this, &ThumbnailResponse::startRequest,
+ Qt::QueuedConnection);
}
-QImage ImageProvider::requestImage(const QString& id, QSize* pSize,
- const QSize& requestedSize) {
- if (!id.startsWith("mxc://")) {
- qWarning() << "ImageProvider: won't fetch an invalid id:" << id
- << "doesn't follow server/mediaId pattern";
- return {};
+void ThumbnailResponse::startRequest() {
+ // Runs in the main thread, not QML thread
+ if (mediaId.count('/') != 1) {
+ errorStr =
+ QStringLiteral("Media id '%1' doesn't follow server/mediaId pattern")
+ .arg(mediaId);
+ emit finished();
+ return;
}
- QUrl mxcUri{id};
+ QWriteLocker _(&lock);
+ job = c->getThumbnail(mediaId, requestedSize);
+ // Connect to any possible outcome including abandonment
+ // to make sure the QML thread is not left stuck forever.
+ connect(job, &BaseJob::finished, this, &ThumbnailResponse::prepareResult);
+}
- QUrl tempfilePath = QUrl::fromLocalFile(
- QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/" +
- mxcUri.fileName() + "-" + QString::number(requestedSize.width()) + "x" +
- QString::number(requestedSize.height()) + ".png");
-
- QImage cachedImage;
- if (cachedImage.load(tempfilePath.toLocalFile())) {
- if (pSize != nullptr) *pSize = cachedImage.size();
- return cachedImage;
- }
-
- MediaThumbnailJob* job = nullptr;
- QReadLocker locker(&m_lock);
-
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
- QMetaObject::invokeMethod(
- m_connection,
- [=] { return m_connection->getThumbnail(mxcUri, requestedSize); },
- Qt::BlockingQueuedConnection, &job);
-#else
- QMetaObject::invokeMethod(m_connection, "getThumbnail",
- Qt::BlockingQueuedConnection,
- Q_RETURN_ARG(MediaThumbnailJob*, job),
- Q_ARG(QUrl, mxcUri), Q_ARG(QSize, requestedSize));
-#endif
- if (!job) {
- qDebug() << "ImageProvider: failed to send a request";
- return {};
- }
- QImage result;
+void ThumbnailResponse::prepareResult() {
{
- QWaitCondition condition; // The most compact way to block on a signal
- job->connect(job, &MediaThumbnailJob::finished, job, [&] {
- result = job->thumbnail();
- condition.wakeAll();
- });
- condition.wait(&m_lock);
+ QWriteLocker _(&lock);
+ Q_ASSERT(job->error() != BaseJob::Pending);
+
+ if (job->error() == BaseJob::Success) {
+ image = job->thumbnail();
+ errorStr.clear();
+ } else {
+ errorStr = job->errorString();
+ qWarning() << "ThumbnailResponse: no valid image for" << mediaId << "-"
+ << errorStr;
+ }
+ job = nullptr;
}
-
- if (pSize != nullptr) *pSize = result.size();
-
- result.save(tempfilePath.toLocalFile());
-
- return result;
+ emit finished();
+}
+
+QQuickTextureFactory* ThumbnailResponse::textureFactory() const {
+ QReadLocker _(&lock);
+ return QQuickTextureFactory::textureFactoryForImage(image);
+}
+
+QString ThumbnailResponse::errorString() const {
+ QReadLocker _(&lock);
+ return errorStr;
+}
+
+void ThumbnailResponse::cancel() {
+ QWriteLocker _(&lock);
+ if (job) {
+ job->abandon();
+ job = nullptr;
+ }
+ errorStr = "Image request has been cancelled";
+}
+
+QQuickImageResponse* ImageProvider::requestImageResponse(
+ const QString& id, const QSize& requestedSize) {
+ qDebug() << "ImageProvider: requesting " << id;
+ return new ThumbnailResponse(m_connection.load(), id, requestedSize);
}
diff --git a/src/imageprovider.h b/src/imageprovider.h
index 1e668bc..08d6a36 100644
--- a/src/imageprovider.h
+++ b/src/imageprovider.h
@@ -1,38 +1,61 @@
#ifndef IMAGEPROVIDER_H
#define IMAGEPROVIDER_H
+#pragma once
-#include
+#include
+#include
+#include
#include
-#include
+#include
-#include "connection.h"
+namespace QMatrixClient {
+class Connection;
+}
-class ImageProvider : public QObject, public QQuickImageProvider {
+class ThumbnailResponse : public QQuickImageResponse {
+ public:
+ ThumbnailResponse(QMatrixClient::Connection* c, QString mediaId,
+ const QSize& requestedSize);
+ ~ThumbnailResponse() override = default;
+
+ void startRequest();
+
+ private:
+ QMatrixClient::Connection* c;
+ const QString mediaId;
+ const QSize requestedSize;
+ QMatrixClient::MediaThumbnailJob* job = nullptr;
+
+ QImage image;
+ QString errorStr;
+ mutable QReadWriteLock lock;
+
+ void prepareResult();
+ QQuickTextureFactory* textureFactory() const override;
+ QString errorString() const override;
+ void cancel() override;
+};
+
+class ImageProvider : public QObject, public QQuickAsyncImageProvider {
Q_OBJECT
Q_PROPERTY(QMatrixClient::Connection* connection READ connection WRITE
setConnection NOTIFY connectionChanged)
public:
- explicit ImageProvider(QObject* parent = nullptr);
+ explicit ImageProvider() : QObject(), QQuickAsyncImageProvider() {}
- QImage requestImage(const QString& id, QSize* pSize,
- const QSize& requestedSize) override;
-
- void initializeEngine(QQmlEngine* engine, const char* uri);
+ QQuickImageResponse* requestImageResponse(
+ const QString& id, const QSize& requestedSize) override;
QMatrixClient::Connection* connection() { return m_connection; }
- void setConnection(QMatrixClient::Connection* newConnection) {
- if (m_connection != newConnection) {
- m_connection = newConnection;
- emit connectionChanged();
- }
+ void setConnection(QMatrixClient::Connection* connection) {
+ m_connection.store(connection);
}
signals:
void connectionChanged();
private:
- QReadWriteLock m_lock;
- QMatrixClient::Connection* m_connection = nullptr;
+ QAtomicPointer m_connection;
};
#endif // IMAGEPROVIDER_H
diff --git a/src/main.cpp b/src/main.cpp
index 804373f..ca17cf3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,12 +1,13 @@
+#include
#include
#include
+#include
#include
#include
#include "accountlistmodel.h"
#include "controller.h"
#include "emojimodel.h"
-#include "imageitem.h"
#include "imageprovider.h"
#include "messageeventmodel.h"
#include "room.h"
@@ -23,7 +24,19 @@
using namespace QMatrixClient;
int main(int argc, char *argv[]) {
- QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#if defined(Q_OS_LINUX) || defined(Q_OS_WIN) || defined(Q_OS_FREEBSD)
+ if (qgetenv("QT_SCALE_FACTOR").size() == 0) {
+ QSettings settings("ENCOM", "Spectral");
+ float factor = settings.value("Interface/dpi", 100).toFloat() / 100;
+
+ qDebug() << "DPI:" << factor;
+
+ if (factor != -1)
+ qputenv("QT_SCALE_FACTOR", QString::number(factor).toUtf8());
+ }
+#endif
+
+ QNetworkProxyFactory::setUseSystemConfiguration(true);
QApplication app(argc, argv);
@@ -34,7 +47,6 @@ int main(int argc, char *argv[]) {
qmlRegisterType("SortFilterProxyModel", 0,
2, "SortFilterProxyModel");
- qmlRegisterType("Spectral", 0, 1, "ImageItem");
qmlRegisterType("Spectral", 0, 1, "Controller");
qmlRegisterType("Spectral", 0, 1, "AccountListModel");
qmlRegisterType("Spectral", 0, 1, "RoomListModel");
@@ -51,6 +63,11 @@ int main(int argc, char *argv[]) {
qRegisterMetaType("SpectralRoom*");
qRegisterMetaType("SpectralUser*");
+#if defined(BUNDLE_FONT)
+ QFontDatabase::addApplicationFont(":/assets/font/roboto.ttf");
+ QFontDatabase::addApplicationFont(":/assets/font/twemoji.ttf");
+#endif
+
QQmlApplicationEngine engine;
engine.addImportPath("qrc:/imports");
diff --git a/src/messageeventmodel.cpp b/src/messageeventmodel.cpp
index 60c277b..d5e9799 100644
--- a/src/messageeventmodel.cpp
+++ b/src/messageeventmodel.cpp
@@ -9,16 +9,11 @@
#include
#include
-#include
#include
#include // for qmlRegisterType()
#include "utils.h"
-static QString parseAvatarUrl(QUrl url) {
- return url.host() + "/" + url.path();
-}
-
QHash MessageEventModel::roleNames() const {
QHash roles = QAbstractItemModel::roleNames();
roles[EventTypeRole] = "eventType";
@@ -39,6 +34,9 @@ QHash MessageEventModel::roleNames() const {
roles[LongOperationRole] = "progressInfo";
roles[AnnotationRole] = "annotation";
roles[EventResolvedTypeRole] = "eventResolvedType";
+ roles[ReplyEventIdRole] = "replyEventId";
+ roles[ReplyAuthorRole] = "replyAuthor";
+ roles[ReplyDisplayRole] = "replyDisplay";
roles[UserMarkerRole] = "userMarker";
return roles;
}
@@ -89,6 +87,9 @@ void MessageEventModel::setRoom(SpectralRoom *room) {
{AboveEventTypeRole, AboveAuthorRole,
AboveSectionRole, AboveTimeRole});
}
+ for (auto i = m_currentRoom->maxTimelineIndex() - biggest;
+ i <= m_currentRoom->maxTimelineIndex() - lowest; ++i)
+ refreshLastUserEvents(i);
});
connect(m_currentRoom, &Room::pendingEventAboutToAdd, this,
[this] { beginInsertRows({}, 0, 0); });
@@ -108,9 +109,10 @@ void MessageEventModel::setRoom(SpectralRoom *room) {
endMoveRows();
movingEvent = false;
}
- refreshRow(timelineBaseIndex()); // Refresh the looks
+ refreshRow(timelineBaseIndex()); // Refresh the looks
+ refreshLastUserEvents(0);
if (m_currentRoom->timelineSize() > 1) // Refresh above
- refreshEventRoles(timelineBaseIndex() + 1);
+ refreshEventRoles(timelineBaseIndex() + 1, {ReadMarkerRole});
if (timelineBaseIndex() > 0) // Refresh below, see #312
refreshEventRoles(timelineBaseIndex() - 1,
{AboveEventTypeRole, AboveAuthorRole,
@@ -128,9 +130,11 @@ void MessageEventModel::setRoom(SpectralRoom *room) {
{ReadMarkerRole});
refreshEventRoles(lastReadEventId, {ReadMarkerRole});
});
- connect(
- m_currentRoom, &Room::replacedEvent, this,
- [this](const RoomEvent *newEvent) { refreshEvent(newEvent->id()); });
+ connect(m_currentRoom, &Room::replacedEvent, this,
+ [this](const RoomEvent *newEvent) {
+ refreshLastUserEvents(refreshEvent(newEvent->id()) -
+ timelineBaseIndex());
+ });
connect(m_currentRoom, &Room::fileTransferProgress, this,
&MessageEventModel::refreshEvent);
connect(m_currentRoom, &Room::fileTransferCompleted, this,
@@ -140,7 +144,7 @@ void MessageEventModel::setRoom(SpectralRoom *room) {
connect(m_currentRoom, &Room::fileTransferCancelled, this,
&MessageEventModel::refreshEvent);
connect(m_currentRoom, &Room::readMarkerForUserMoved, this,
- [=](User *user, QString fromEventId, QString toEventId) {
+ [=](User *, QString fromEventId, QString toEventId) {
refreshEventRoles(fromEventId, {UserMarkerRole});
refreshEventRoles(toEventId, {UserMarkerRole});
});
@@ -214,6 +218,23 @@ QString MessageEventModel::renderDate(QDateTime timestamp) const {
return date.toString(Qt::DefaultLocaleShortDate);
}
+void MessageEventModel::refreshLastUserEvents(int baseTimelineRow) {
+ if (!m_currentRoom || m_currentRoom->timelineSize() <= baseTimelineRow)
+ return;
+
+ const auto &timelineBottom = m_currentRoom->messageEvents().rbegin();
+ const auto &lastSender = (*(timelineBottom + baseTimelineRow))->senderId();
+ const auto limit = timelineBottom + std::min(baseTimelineRow + 10,
+ m_currentRoom->timelineSize());
+ for (auto it = timelineBottom + std::max(baseTimelineRow - 10, 0);
+ it != limit; ++it) {
+ if ((*it)->senderId() == lastSender) {
+ auto idx = index(it - timelineBottom);
+ emit dataChanged(idx, idx);
+ }
+ }
+}
+
int MessageEventModel::rowCount(const QModelIndex &parent) const {
if (!m_currentRoom || parent.isValid()) return 0;
return m_currentRoom->timelineSize();
@@ -235,13 +256,11 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
const auto &evt = isPending ? **pendingIt : **timelineIt;
if (role == Qt::DisplayRole) {
- return utils::eventToString(evt, m_currentRoom, Qt::RichText);
+ return utils::removeReply(utils::eventToString(evt, m_currentRoom, Qt::RichText));
}
if (role == MessageRole) {
- static const QRegExp rmReplyRegExp("^> <@.*:.*> .*\n\n(.*)");
- return utils::eventToString(evt, m_currentRoom)
- .replace(rmReplyRegExp, "\\1");
+ return utils::removeReply(utils::eventToString(evt, m_currentRoom));
}
if (role == Qt::ToolTipRole) {
@@ -306,13 +325,14 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
if (role == HighlightRole) return m_currentRoom->isEventHighlighted(&evt);
- if (role == ReadMarkerRole) return evt.id() == lastReadEventId && row > timelineBaseIndex();
+ if (role == ReadMarkerRole)
+ return evt.id() == lastReadEventId && row > timelineBaseIndex();
if (role == SpecialMarksRole) {
if (isPending) return pendingIt->deliveryStatus();
if (is(evt)) return EventStatus::Hidden;
- if (evt.isRedacted()) return EventStatus::Redacted;
+ if (evt.isRedacted()) return EventStatus::Hidden;
if (evt.isStateEvent() &&
static_cast(evt).repeatsState())
@@ -348,6 +368,28 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const {
return variantList;
}
+ if (role == ReplyEventIdRole || role == ReplyDisplayRole ||
+ role == ReplyAuthorRole) {
+ const QString &replyEventId = evt.contentJson()["m.relates_to"]
+ .toObject()["m.in_reply_to"]
+ .toObject()["event_id"]
+ .toString();
+ if (replyEventId.isEmpty()) return {};
+ const auto replyIt = m_currentRoom->findInTimeline(replyEventId);
+ if (replyIt == m_currentRoom->timelineEdge()) return {};
+ const auto& replyEvt = **replyIt;
+ switch (role) {
+ case ReplyEventIdRole:
+ return replyEventId;
+ case ReplyDisplayRole:
+ return utils::removeReply(utils::eventToString(replyEvt, m_currentRoom, Qt::RichText));
+ case ReplyAuthorRole:
+ return QVariant::fromValue(
+ m_currentRoom->user(replyEvt.senderId()));
+ }
+ return {};
+ }
+
if (role == AboveEventTypeRole || role == AboveSectionRole ||
role == AboveAuthorRole || role == AboveTimeRole)
for (auto r = row + 1; r < rowCount(); ++r) {
diff --git a/src/messageeventmodel.h b/src/messageeventmodel.h
index f142a7c..a828f99 100644
--- a/src/messageeventmodel.h
+++ b/src/messageeventmodel.h
@@ -1,8 +1,8 @@
#ifndef MESSAGEEVENTMODEL_H
#define MESSAGEEVENTMODEL_H
-#include "spectralroom.h"
#include "room.h"
+#include "spectralroom.h"
#include
@@ -30,6 +30,9 @@ class MessageEventModel : public QAbstractListModel {
LongOperationRole,
AnnotationRole,
UserMarkerRole,
+ ReplyEventIdRole,
+ ReplyAuthorRole,
+ ReplyDisplayRole,
// For debugging
EventResolvedTypeRole,
};
@@ -62,6 +65,7 @@ class MessageEventModel : public QAbstractListModel {
const QMatrixClient::Room::rev_iter_t& baseIt) const;
QString renderDate(QDateTime timestamp) const;
+ void refreshLastUserEvents(int baseRow);
void refreshEventRoles(int row, const QVector& roles = {});
int refreshEventRoles(const QString& eventId, const QVector& roles = {});
diff --git a/src/notifications/manager.h b/src/notifications/manager.h
index b55eac2..0115713 100644
--- a/src/notifications/manager.h
+++ b/src/notifications/manager.h
@@ -23,7 +23,7 @@ class NotificationsManager : public QObject {
void postNotification(const QString &roomId, const QString &eventId,
const QString &roomName, const QString &senderName,
- const QString &text, const QImage &icon, const QUrl &iconPath);
+ const QString &text, const QImage &icon);
signals:
void notificationClicked(const QString roomId, const QString eventId);
diff --git a/src/notifications/managerlinux.cpp b/src/notifications/managerlinux.cpp
index 3a09b08..cd5c7d0 100644
--- a/src/notifications/managerlinux.cpp
+++ b/src/notifications/managerlinux.cpp
@@ -25,8 +25,7 @@ NotificationsManager::NotificationsManager(QObject *parent)
void NotificationsManager::postNotification(
const QString &roomid, const QString &eventid, const QString &roomname,
- const QString &sender, const QString &text, const QImage &icon,
- const QUrl &iconPath) {
+ const QString &sender, const QString &text, const QImage &icon) {
uint id = showNotification(roomname, sender + ": " + text, icon);
notificationIds[id] = roomEventId{roomid, eventid};
}
diff --git a/src/notifications/managermac.mm b/src/notifications/managermac.mm
index 2ddc939..782be1f 100644
--- a/src/notifications/managermac.mm
+++ b/src/notifications/managermac.mm
@@ -19,13 +19,11 @@ NotificationsManager::postNotification(
const QString &roomName,
const QString &senderName,
const QString &text,
- const QImage &icon,
- const QUrl &iconPath)
+ const QImage &icon)
{
Q_UNUSED(roomId);
Q_UNUSED(eventId);
Q_UNUSED(icon);
- Q_UNUSED(iconPath);
NSUserNotification * notif = [[NSUserNotification alloc] init];
diff --git a/src/notifications/managerwin.cpp b/src/notifications/managerwin.cpp
index 70d943c..b6bf61a 100644
--- a/src/notifications/managerwin.cpp
+++ b/src/notifications/managerwin.cpp
@@ -46,8 +46,7 @@ NotificationsManager::NotificationsManager(QObject *parent) : QObject(parent) {}
void NotificationsManager::postNotification(
const QString &room_id, const QString &event_id, const QString &room_name,
- const QString &sender, const QString &text, const QImage &icon,
- const QUrl &iconPath) {
+ const QString &sender, const QString &text, const QImage &icon) {
Q_UNUSED(room_id)
Q_UNUSED(event_id)
Q_UNUSED(icon)
@@ -65,9 +64,6 @@ void NotificationsManager::postNotification(
templ.setTextField(QString("%1").arg(text).toStdWString(),
WinToastTemplate::SecondLine);
- templ.setImagePath(
- reinterpret_cast(QDir::toNativeSeparators(iconPath.toLocalFile()).utf16()));
-
count++;
CustomHandler *customHandler = new CustomHandler(count, this);
notificationIds[count] = roomEventId{room_id, event_id};
diff --git a/src/paintable.cpp b/src/paintable.cpp
deleted file mode 100644
index a44b826..0000000
--- a/src/paintable.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "paintable.h"
-
-Paintable::Paintable(QObject *parent) : QObject(parent) {}
diff --git a/src/paintable.h b/src/paintable.h
deleted file mode 100644
index 5eb56ef..0000000
--- a/src/paintable.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef PAINTABLE_H
-#define PAINTABLE_H
-
-#include
-#include
-
-class Paintable : public QObject {
- Q_OBJECT
- public:
- Paintable(QObject* parent = nullptr);
- virtual ~Paintable() = default;
-
- virtual QImage image(int) = 0;
- virtual QImage image(int, int) = 0;
-
- signals:
- void paintableChanged();
-};
-
-#endif // PAINTABLE_H
diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp
index f6c8839..28068c0 100644
--- a/src/roomlistmodel.cpp
+++ b/src/roomlistmodel.cpp
@@ -70,6 +70,8 @@ void RoomListModel::connectRoomSignals(SpectralRoom* room) {
[=] { unreadMessagesChanged(room); });
connect(room, &Room::notificationCountChanged, this,
[=] { unreadMessagesChanged(room); });
+ connect(room, &Room::avatarChanged, this,
+ [this, room] { refresh(room, {AvatarRole}); });
connect(room, &Room::tagsChanged, this, [=] { refresh(room); });
connect(room, &Room::joinStateChanged, this, [=] { refresh(room); });
connect(room, &Room::addedMessages, this,
@@ -77,17 +79,13 @@ void RoomListModel::connectRoomSignals(SpectralRoom* room) {
connect(room, &Room::aboutToAddNewMessages, this,
[=](QMatrixClient::RoomEventsRange eventsRange) {
RoomEvent* event = (eventsRange.end() - 1)->get();
+ if (event->isStateEvent()) return;
User* sender = room->user(event->senderId());
if (sender == room->localUser()) return;
- QUrl _url = room->avatarUrl();
emit newMessage(
room->id(), event->id(), room->displayName(),
sender->displayname(), utils::eventToString(*event),
- room->avatar(128),
- QUrl::fromLocalFile(QStandardPaths::writableLocation(
- QStandardPaths::CacheLocation) +
- "/avatar/" + _url.authority() + '_' +
- _url.fileName() + ".png"));
+ room->avatar(128));
});
}
@@ -152,7 +150,7 @@ QVariant RoomListModel::data(const QModelIndex& index, int role) const {
}
SpectralRoom* room = m_rooms.at(index.row());
if (role == NameRole) return room->displayName();
- if (role == PaintableRole) return QVariant::fromValue(room->paintable());
+ if (role == AvatarRole) return room->avatarMediaId();
if (role == TopicRole) return room->topic();
if (role == CategoryRole) {
if (room->joinState() == JoinState::Invite) return RoomType::Invited;
@@ -192,7 +190,7 @@ void RoomListModel::unreadMessagesChanged(SpectralRoom* room) {
QHash RoomListModel::roleNames() const {
QHash roles;
roles[NameRole] = "name";
- roles[PaintableRole] = "paintable";
+ roles[AvatarRole] = "avatar";
roles[TopicRole] = "topic";
roles[CategoryRole] = "category";
roles[UnreadCountRole] = "unreadCount";
diff --git a/src/roomlistmodel.h b/src/roomlistmodel.h
index c42e956..9da486d 100644
--- a/src/roomlistmodel.h
+++ b/src/roomlistmodel.h
@@ -31,7 +31,7 @@ class RoomListModel : public QAbstractListModel {
public:
enum EventRoles {
NameRole = Qt::UserRole + 1,
- PaintableRole,
+ AvatarRole,
TopicRole,
CategoryRole,
UnreadCountRole,
@@ -76,7 +76,7 @@ class RoomListModel : public QAbstractListModel {
void roomAdded(SpectralRoom* room);
void newMessage(const QString& roomId, const QString& eventId,
const QString& roomName, const QString& senderName,
- const QString& text, const QImage& icon, const QUrl& iconPath);
+ const QString& text, const QImage& icon);
};
#endif // ROOMLISTMODEL_H
diff --git a/src/spectralroom.cpp b/src/spectralroom.cpp
index 01f38dc..8d23f75 100644
--- a/src/spectralroom.cpp
+++ b/src/spectralroom.cpp
@@ -9,64 +9,67 @@
#include "events/typingevent.h"
#include
+#include
+#include
#include
#include
+#include "cmark.h"
+
#include "utils.h"
SpectralRoom::SpectralRoom(Connection* connection, QString roomId,
JoinState joinState)
- : Room(connection, std::move(roomId), joinState), m_paintable(this) {
+ : Room(connection, std::move(roomId), joinState) {
connect(this, &SpectralRoom::notificationCountChanged, this,
&SpectralRoom::countChanged);
connect(this, &SpectralRoom::highlightCountChanged, this,
&SpectralRoom::countChanged);
connect(this, &Room::addedMessages, this, [=] { setBusy(false); });
+ connect(this, &Room::fileTransferCompleted, this, [=] {
+ setFileUploadingProgress(0);
+ setHasFileUploading(false);
+ });
+}
+
+inline QString getMIME(const QUrl& fileUrl) {
+ return QMimeDatabase().mimeTypeForFile(fileUrl.toLocalFile()).name();
+}
+
+inline QSize getImageSize(const QUrl& imageUrl) {
+ QImageReader reader(imageUrl.toLocalFile());
+ return reader.size();
}
void SpectralRoom::chooseAndUploadFile() {
auto localFile = QFileDialog::getOpenFileUrl(Q_NULLPTR, tr("Save File as"));
if (!localFile.isEmpty()) {
- UploadContentJob* job =
- connection()->uploadFile(localFile.toLocalFile(), getMIME(localFile));
- if (isJobRunning(job)) {
- setHasFileUploading(true);
- connect(job, &BaseJob::uploadProgress, this,
- [=](qint64 bytesSent, qint64 bytesTotal) {
- if (bytesTotal != 0) {
- setFileUploadingProgress(bytesSent * 100 / bytesTotal);
- }
- });
- connect(job, &BaseJob::success, this,
- [=] { postFile(localFile, job->contentUri()); });
- connect(job, &BaseJob::finished, this, [=] {
- setHasFileUploading(false);
+ QString txnID = postFile(localFile.fileName(), localFile, false);
+ setHasFileUploading(true);
+ connect(this, &Room::fileTransferCompleted,
+ [=](QString id, QUrl localFile, QUrl mxcUrl) {
+ if (id == txnID) {
+ setFileUploadingProgress(0);
+ setHasFileUploading(false);
+ }
+ });
+ connect(this, &Room::fileTransferFailed, [=](QString id, QString error) {
+ if (id == txnID) {
setFileUploadingProgress(0);
- });
- } else {
- qDebug() << "Failed transfer.";
- }
+ setHasFileUploading(false);
+ }
+ });
+ connect(
+ this, &Room::fileTransferProgress,
+ [=](QString id, qint64 progress, qint64 total) {
+ if (id == txnID) {
+ qDebug() << "Progress:" << progress << total;
+ setFileUploadingProgress(int(float(progress) / float(total) * 100));
+ }
+ });
}
}
-void SpectralRoom::postFile(const QUrl& localFile, const QUrl& mxcUrl) {
- const QString mime = getMIME(localFile);
- const QString fileName = localFile.fileName();
- QString msgType = "m.file";
- if (mime.startsWith("image")) msgType = "m.image";
- if (mime.startsWith("video")) msgType = "m.video";
- if (mime.startsWith("audio")) msgType = "m.audio";
- QJsonObject json{QJsonObject{{"msgtype", msgType},
- {"body", fileName},
- {"filename", fileName},
- {"url", mxcUrl.url()}}};
- postJson("m.room.message", json);
-}
-
-QString SpectralRoom::getMIME(const QUrl& fileUrl) const {
- return QMimeDatabase().mimeTypeForFile(fileUrl.toLocalFile()).name();
-}
-
void SpectralRoom::saveFileAs(QString eventId) {
auto fileName = QFileDialog::getSaveFileName(Q_NULLPTR, tr("Save File as"),
fileNameToDownload(eventId));
@@ -85,16 +88,14 @@ bool SpectralRoom::hasUsersTyping() {
return count != 0;
}
-QString SpectralRoom::getUsersTyping() {
- QString usersTypingStr;
+QVariantList SpectralRoom::getUsersTyping() {
QList users = usersTyping();
users.removeOne(localUser());
+ QVariantList out;
for (User* user : users) {
- usersTypingStr += user->displayname() + " ";
+ out.append(QVariant::fromValue(user));
}
- usersTypingStr += users.count() < 2 ? "is" : "are";
- usersTypingStr += " typing.";
- return usersTypingStr;
+ return out;
}
void SpectralRoom::sendTypingNotification(bool isTyping) {
@@ -162,8 +163,6 @@ QDateTime SpectralRoom::lastActiveTime() {
return messageEvents().rbegin()->get()->timestamp();
}
-float SpectralRoom::orderForTag(QString name) { return tag(name).order; }
-
int SpectralRoom::savedTopVisibleIndex() const {
return firstDisplayedMarker() == timelineEdge()
? 0
@@ -204,3 +203,10 @@ QVariantList SpectralRoom::getUsers(const QString& prefix) {
return matchedList;
}
+
+QString SpectralRoom::postMarkdownText(const QString& markdown) {
+ QByteArray local = markdown.toLocal8Bit();
+ const char* data = local.data();
+ QString html = cmark_markdown_to_html(data, local.length(), 0);
+ return postHtmlText(markdown, html);
+}
diff --git a/src/spectralroom.h b/src/spectralroom.h
index ebb736e..68722dc 100644
--- a/src/spectralroom.h
+++ b/src/spectralroom.h
@@ -1,7 +1,6 @@
#ifndef SpectralRoom_H
#define SpectralRoom_H
-#include "paintable.h"
#include "room.h"
#include "spectraluser.h"
@@ -11,31 +10,10 @@
using namespace QMatrixClient;
-class RoomPaintable : public Paintable {
- Q_OBJECT
- public:
- RoomPaintable(Room* parent) : Paintable(parent), m_room(parent) {
- connect(m_room, &Room::avatarChanged, [=] { emit paintableChanged(); });
- }
-
- QImage image(int dimension) override {
- if (!m_room) return QImage();
- return m_room->avatar(dimension);
- }
- QImage image(int width, int height) override {
- if (!m_room) return QImage();
- return m_room->avatar(width, height);
- }
-
- private:
- Room* m_room;
-};
-
class SpectralRoom : public Room {
Q_OBJECT
- Q_PROPERTY(Paintable* paintable READ paintable CONSTANT)
Q_PROPERTY(bool hasUsersTyping READ hasUsersTyping NOTIFY typingChanged)
- Q_PROPERTY(QString usersTyping READ getUsersTyping NOTIFY typingChanged)
+ Q_PROPERTY(QVariantList usersTyping READ getUsersTyping NOTIFY typingChanged)
Q_PROPERTY(QString cachedInput READ cachedInput WRITE setCachedInput NOTIFY
cachedInputChanged)
Q_PROPERTY(bool hasFileUploading READ hasFileUploading NOTIFY
@@ -48,8 +26,6 @@ class SpectralRoom : public Room {
explicit SpectralRoom(Connection* connection, QString roomId,
JoinState joinState = {});
- Paintable* paintable() { return &m_paintable; }
-
const QString& cachedInput() const { return m_cachedInput; }
void setCachedInput(const QString& input) {
if (input != m_cachedInput) {
@@ -67,7 +43,7 @@ class SpectralRoom : public Room {
}
bool hasUsersTyping();
- QString getUsersTyping();
+ QVariantList getUsersTyping();
QString lastEvent();
bool isEventHighlighted(const QMatrixClient::RoomEvent* e) const;
@@ -90,7 +66,6 @@ class SpectralRoom : public Room {
}
}
- Q_INVOKABLE float orderForTag(QString name);
Q_INVOKABLE int savedTopVisibleIndex() const;
Q_INVOKABLE int savedBottomVisibleIndex() const;
Q_INVOKABLE void saveViewport(int topIndex, int bottomIndex);
@@ -99,6 +74,8 @@ class SpectralRoom : public Room {
Q_INVOKABLE QVariantList getUsers(const QString& prefix);
+ Q_INVOKABLE QString postMarkdownText(const QString& markdown);
+
private:
QString m_cachedInput;
QSet highlights;
@@ -108,9 +85,6 @@ class SpectralRoom : public Room {
bool m_busy = false;
- QString getMIME(const QUrl& fileUrl) const;
- void postFile(const QUrl& localFile, const QUrl& mxcUrl);
-
void checkForHighlights(const QMatrixClient::TimelineItem& ti);
void onAddNewTimelineEvents(timeline_iter_t from) override;
@@ -133,9 +107,6 @@ class SpectralRoom : public Room {
void sendTypingNotification(bool isTyping);
void sendReply(QString userId, QString eventId, QString replyContent,
QString sendContent);
-
- private:
- RoomPaintable m_paintable;
};
#endif // SpectralRoom_H
diff --git a/src/spectraluser.h b/src/spectraluser.h
index 11a81d4..e62e51e 100644
--- a/src/spectraluser.h
+++ b/src/spectraluser.h
@@ -1,44 +1,18 @@
#ifndef SpectralUser_H
#define SpectralUser_H
-#include "paintable.h"
#include "room.h"
#include "user.h"
#include
-#include
using namespace QMatrixClient;
-class UserPaintable : public Paintable {
- Q_OBJECT
- public:
- UserPaintable(User* parent) : Paintable(parent), m_user(parent) {}
-
- QImage image(int dimension) override {
- if (!m_user) return QImage();
- return m_user->avatar(dimension);
- }
- QImage image(int width, int height) override {
- if (!m_user) return QImage();
- return m_user->avatar(width, height);
- }
-
- private:
- User* m_user;
-};
-
class SpectralUser : public User {
Q_OBJECT
- Q_PROPERTY(Paintable* paintable READ paintable CONSTANT)
public:
SpectralUser(QString userId, Connection* connection)
- : User(userId, connection), m_paintable(this) {}
-
- Paintable* paintable() { return &m_paintable; }
-
- private:
- UserPaintable m_paintable;
+ : User(userId, connection) {}
};
#endif // SpectralUser_H
diff --git a/src/userlistmodel.cpp b/src/userlistmodel.cpp
index eb242d9..15cff77 100644
--- a/src/userlistmodel.cpp
+++ b/src/userlistmodel.cpp
@@ -34,12 +34,8 @@ void UserListModel::setRoom(QMatrixClient::Room* room) {
connect(m_currentRoom, &Room::memberRenamed, this,
&UserListModel::userAdded);
{
- QElapsedTimer et;
- et.start();
m_users = m_currentRoom->users();
std::sort(m_users.begin(), m_users.end(), room->memberSorter());
- qDebug() << "Sorting" << m_users.size() << "user(s) in"
- << m_currentRoom->displayName() << "took" << et;
}
for (User* user : m_users) {
connect(user, &User::avatarChanged, this, &UserListModel::avatarChanged);
@@ -72,8 +68,8 @@ QVariant UserListModel::data(const QModelIndex& index, int role) const {
if (role == UserIDRole) {
return user->id();
}
- if (role == PaintableRole) {
- return QVariant::fromValue((static_cast(user))->paintable());
+ if (role == AvatarRole) {
+ return user->avatarMediaId();
}
return QVariant();
@@ -115,7 +111,7 @@ void UserListModel::refresh(QMatrixClient::User* user, QVector roles) {
void UserListModel::avatarChanged(QMatrixClient::User* user,
const QMatrixClient::Room* context) {
- if (context == m_currentRoom) refresh(user, {PaintableRole});
+ if (context == m_currentRoom) refresh(user, {AvatarRole});
}
int UserListModel::findUserPos(User* user) const {
@@ -130,6 +126,6 @@ QHash UserListModel::roleNames() const {
QHash roles;
roles[NameRole] = "name";
roles[UserIDRole] = "userId";
- roles[PaintableRole] = "paintable";
+ roles[AvatarRole] = "avatar";
return roles;
}
diff --git a/src/userlistmodel.h b/src/userlistmodel.h
index 88146ad..fd01a5e 100644
--- a/src/userlistmodel.h
+++ b/src/userlistmodel.h
@@ -17,7 +17,7 @@ class UserListModel : public QAbstractListModel {
Q_PROPERTY(
QMatrixClient::Room* room READ room WRITE setRoom NOTIFY roomChanged)
public:
- enum EventRoles { NameRole = Qt::UserRole + 1, UserIDRole, PaintableRole };
+ enum EventRoles { NameRole = Qt::UserRole + 1, UserIDRole, AvatarRole };
using User = QMatrixClient::User;
diff --git a/src/utils.cpp b/src/utils.cpp
index b14e9be..3154dd3 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -2,5 +2,14 @@
QString utils::removeReply(const QString& text) {
QString result(text);
- return result.remove(utils::removeReplyRegex);
+ result.remove(utils::removeRichReplyRegex);
+ result.remove(utils::removeReplyRegex);
+ return result;
+}
+
+QString utils::cleanHTML(const QString& text, QMatrixClient::Room* room) {
+ QString result(text);
+ result.replace(codePillRegExp, "\\1");
+ result.replace(userPillRegExp, "\\1");
+ return result;
}
diff --git a/src/utils.h b/src/utils.h
index 2304610..cce426d 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -2,9 +2,10 @@
#define Utils_H
#include "room.h"
+#include "user.h"
#include
-#include
+#include
#include
#include
@@ -13,9 +14,18 @@
#include
namespace utils {
-const QRegExp removeReplyRegex{"> <.*>.*\\n\\n"};
+static const QRegularExpression removeReplyRegex{
+ "> <.*?>.*?\\n\\n", QRegularExpression::DotMatchesEverythingOption};
+static const QRegularExpression removeRichReplyRegex{
+ ".*? ", QRegularExpression::DotMatchesEverythingOption};
+static const QRegularExpression codePillRegExp{
+ "(.*?)
", QRegularExpression::DotMatchesEverythingOption};
+static const QRegularExpression userPillRegExp{
+ "(.*?)",
+ QRegularExpression::DotMatchesEverythingOption};
QString removeReply(const QString& text);
+QString cleanHTML(const QString& text, QMatrixClient::Room* room);
template
QString eventToString(const BaseEventT& evt,
@@ -31,13 +41,8 @@ QString eventToString(const BaseEventT& evt,
if (prettyPrint && e.hasTextContent() &&
e.mimeType().name() != "text/plain") {
- static const QRegExp userPillRegExp(
- "(.*)");
- QString formattedStr(
- static_cast(e.content())->body);
- formattedStr.replace(userPillRegExp,
- "\\1");
- return formattedStr;
+ return cleanHTML(static_cast(e.content())->body,
+ room);
}
if (e.hasFileContent()) {
auto fileCaption = e.content()->fileInfo()->originalName;