From e216094e2192c05ddbd0988458eb8c0012e7baf8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 2 Sep 2014 01:10:54 +0200 Subject: lol --- src/blocks.c | 1352 +++++++++++---------- src/bstrlib.c | 2979 ---------------------------------------------- src/bstrlib.h | 304 ----- src/buffer.c | 313 +++++ src/buffer.h | 119 ++ src/case_fold_switch.c | 2637 ---------------------------------------- src/case_fold_switch.inc | 2637 ++++++++++++++++++++++++++++++++++++++++ src/casefold.c | 2699 ----------------------------------------- src/detab.c | 48 - src/getopt.c | 199 ---- src/inlines.c | 1711 +++++++++++++------------- src/main.c | 2 +- src/scanners.h | 28 +- src/scanners.re | 54 +- src/stmd.h | 76 +- src/utf8.c | 221 ++-- 16 files changed, 4878 insertions(+), 10501 deletions(-) delete mode 100644 src/bstrlib.c delete mode 100644 src/bstrlib.h create mode 100644 src/buffer.c create mode 100644 src/buffer.h delete mode 100644 src/case_fold_switch.c create mode 100644 src/case_fold_switch.inc delete mode 100644 src/casefold.c delete mode 100644 src/detab.c delete mode 100644 src/getopt.c (limited to 'src') diff --git a/src/blocks.c b/src/blocks.c index 2776231..eabac03 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -10,738 +11,767 @@ static block* make_block(int tag, int start_line, int start_column) { - block* e; - e = (block*) malloc(sizeof(block)); - e->tag = tag; - e->open = true; - e->last_line_blank = false; - e->start_line = start_line; - e->start_column = start_column; - e->end_line = start_line; - e->children = NULL; - e->last_child = NULL; - e->parent = NULL; - e->top = NULL; - e->attributes.refmap = NULL; - e->string_content = bfromcstr(""); - e->inline_content = NULL; - e->next = NULL; - e->prev = NULL; - return e; + block* e; + e = (block*) malloc(sizeof(block)); + e->tag = tag; + e->open = true; + e->last_line_blank = false; + e->start_line = start_line; + e->start_column = start_column; + e->end_line = start_line; + e->children = NULL; + e->last_child = NULL; + e->parent = NULL; + e->top = NULL; + e->attributes.refmap = NULL; + gh_buf_init(&e->string_content, 32); + e->string_pos = 0; + e->inline_content = NULL; + e->next = NULL; + e->prev = NULL; + return e; } // Create a root document block. extern block* make_document() { - block * e = make_block(document, 1, 1); - reference * map = NULL; - reference ** refmap; - refmap = (reference**) malloc(sizeof(reference*)); - *refmap = map; - e->attributes.refmap = refmap; - e->top = e; - return e; + block * e = make_block(document, 1, 1); + reference * map = NULL; + reference ** refmap; + refmap = (reference**) malloc(sizeof(reference*)); + *refmap = map; + e->attributes.refmap = refmap; + e->top = e; + return e; } // Returns true if line has only space characters, else false. -bool is_blank(bstring s, int offset) +bool is_blank(gh_buf *s, int offset) { - char c; - while ((c = bchar(s, offset))) { - if (c == '\n') { - return true; - } else if (c == ' ') { - offset++; - } else { - return false; - } - } - return true; + while (offset < s->size) { + switch (s->ptr[offset]) { + case '\n': + return true; + case ' ': + offset++; + default: + return false; + } + } + + return true; } static inline bool can_contain(int parent_type, int child_type) { - return ( parent_type == document || - parent_type == block_quote || - parent_type == list_item || - (parent_type == list && child_type == list_item) ); + return ( parent_type == document || + parent_type == block_quote || + parent_type == list_item || + (parent_type == list && child_type == list_item) ); } static inline bool accepts_lines(int block_type) { - return (block_type == paragraph || - block_type == atx_header || - block_type == indented_code || - block_type == fenced_code); + return (block_type == paragraph || + block_type == atx_header || + block_type == indented_code || + block_type == fenced_code); } -static int add_line(block* block, bstring ln, int offset) +static void add_line(block* block, gh_buf *ln, int offset) { - bstring s = bmidstr(ln, offset, blength(ln) - offset); - check(block->open, "attempted to add line (%s) to closed container (%d)", - ln->data, block->tag); - check(bformata(block->string_content, "%s", s->data) == 0, - "could not append line to string_content"); - bdestroy(s); - return 0; - error: - return -1; + assert(block->open); + gh_buf_put(&block->string_content, ln->ptr + offset, ln->size - offset); } -static int remove_trailing_blank_lines(bstring ln) +static void remove_trailing_blank_lines(gh_buf *ln) { - bstring tofind = bfromcstr(" \t\r\n"); - int pos; - // find last nonspace: - pos = bninchrr(ln, blength(ln) - 1, tofind); - if (pos == BSTR_ERR) { // all spaces - bassigncstr(ln, ""); - } else { - // find next newline after it - pos = bstrchrp(ln, '\n', pos); - if (pos != BSTR_ERR) { - check(bdelete(ln, pos, blength(ln) - pos) != BSTR_ERR, - "failed to delete trailing blank lines"); - } - } - bdestroy(tofind); - return 0; - error: - return -1; + int i; + + for (i = ln->size - 1; i >= 0; --i) { + char c = ln->ptr[i]; + + if (c != ' ' && c != '\t' && c != '\r' && c != '\n') + break; + } + + if (i < 0) { + gh_buf_clear(ln); + return; + } + + i = gh_buf_strchr(ln, '\n', i); + if (i >= 0) + gh_buf_truncate(ln, i + 1); } // Check to see if a block ends with a blank line, descending // if needed into lists and sublists. static bool ends_with_blank_line(block* block) { - if (block->last_line_blank) { - return true; - } - if ((block->tag == list || block->tag == list_item) && block->last_child) { - return ends_with_blank_line(block->last_child); - } else { - return false; - } + if (block->last_line_blank) { + return true; + } + if ((block->tag == list || block->tag == list_item) && block->last_child) { + return ends_with_blank_line(block->last_child); + } else { + return false; + } } // Break out of all containing lists static int break_out_of_lists(block ** bptr, int line_number) { - block * container = *bptr; - block * b = container->top; - // find first containing list: - while (b && b->tag != list) { - b = b->last_child; - } - if (b) { - while (container && container != b) { - finalize(container, line_number); - container = container->parent; - } - finalize(b, line_number); - *bptr = b->parent; - } - return 0; + block * container = *bptr; + block * b = container->top; + // find first containing list: + while (b && b->tag != list) { + b = b->last_child; + } + if (b) { + while (container && container != b) { + finalize(container, line_number); + container = container->parent; + } + finalize(b, line_number); + *bptr = b->parent; + } + return 0; } -extern int finalize(block* b, int line_number) +extern void finalize(block* b, int line_number) { - int firstlinelen; - int pos; - block* item; - block* subitem; - - check(b != NULL, "finalize called on null block"); - if (!b->open) { - return 0; // don't do anything if the block is already closed - } - b->open = false; - if (line_number > b->start_line) { - b->end_line = line_number - 1; - } else { - b->end_line = line_number; - } - - switch (b->tag) { - - case paragraph: - pos = 0; - while (bchar(b->string_content, 0) == '[' && - (pos = parse_reference(b->string_content, - b->top->attributes.refmap))) { - bdelete(b->string_content, 0, pos); - } - if (is_blank(b->string_content, 0)) { - b->tag = reference_def; - } - break; - - case indented_code: - remove_trailing_blank_lines(b->string_content); - bformata(b->string_content, "\n"); - break; - - case fenced_code: - // first line of contents becomes info - firstlinelen = bstrchr(b->string_content, '\n'); - b->attributes.fenced_code_data.info = - bmidstr(b->string_content, 0, firstlinelen); - bdelete(b->string_content, 0, firstlinelen + 1); // +1 for \n - btrimws(b->attributes.fenced_code_data.info); - unescape(b->attributes.fenced_code_data.info); - break; - - case list: // determine tight/loose status - b->attributes.list_data.tight = true; // tight by default - item = b->children; - - while (item) { - // check for non-final non-empty list item ending with blank line: - if (item->last_line_blank && item->next) { - b->attributes.list_data.tight = false; - break; - } - // recurse into children of list item, to see if there are - // spaces between them: - subitem = item->children; - while (subitem) { - if (ends_with_blank_line(subitem) && - (item->next || subitem->next)) { - b->attributes.list_data.tight = false; - break; - } - subitem = subitem->next; - } - if (!(b->attributes.list_data.tight)) { - break; - } - item = item->next; - } - - break; - - default: - break; - } - - return 0; - error: - return -1; + int firstlinelen; + int pos; + block* item; + block* subitem; + + if (!b->open) + return; // don't do anything if the block is already closed + + b->open = false; + if (line_number > b->start_line) { + b->end_line = line_number - 1; + } else { + b->end_line = line_number; + } + + switch (b->tag) { + case paragraph: + pos = 0; + while (gh_buf_at(&b->string_content, b->string_pos) == '[' && + (pos = parse_reference(&b->string_content, b->string_pos, + b->top->attributes.refmap))) { + b->string_pos = pos; + } + if (is_blank(&b->string_content, b->string_pos)) { + b->tag = reference_def; + } + break; + + case indented_code: + remove_trailing_blank_lines(&b->string_content); + gh_buf_putc(&b->string_content, '\n'); + break; + + case fenced_code: + // first line of contents becomes info + firstlinelen = gh_buf_strchr(&b->string_content, '\n', b->string_pos); + gh_buf_set( + &b->attributes.fenced_code_data.info, + b->string_content.ptr + b->string_pos, + firstlinelen + ); + + b->string_pos = firstlinelen + 1; + + gh_buf_trim(&b->attributes.fenced_code_data.info); + unescape_buffer(&b->attributes.fenced_code_data.info); + break; + + case list: // determine tight/loose status + b->attributes.list_data.tight = true; // tight by default + item = b->children; + + while (item) { + // check for non-final non-empty list item ending with blank line: + if (item->last_line_blank && item->next) { + b->attributes.list_data.tight = false; + break; + } + // recurse into children of list item, to see if there are + // spaces between them: + subitem = item->children; + while (subitem) { + if (ends_with_blank_line(subitem) && + (item->next || subitem->next)) { + b->attributes.list_data.tight = false; + break; + } + subitem = subitem->next; + } + if (!(b->attributes.list_data.tight)) { + break; + } + item = item->next; + } + + break; + + default: + break; + } } // Add a block as child of another. Return pointer to child. extern block* add_child(block* parent, - int block_type, int start_line, int start_column) + int block_type, int start_line, int start_column) { - // if 'parent' isn't the kind of block that can accept this child, - // then back up til we hit a block that can. - while (!can_contain(parent->tag, block_type)) { - finalize(parent, start_line); - parent = parent->parent; - } - - check(parent != NULL, "parent container cannot accept children"); - - block* child = make_block(block_type, start_line, start_column); - child->parent = parent; - child->top = parent->top; - - if (parent->last_child) { - parent->last_child->next = child; - child->prev = parent->last_child; - } else { - parent->children = child; - child->prev = NULL; - } - parent->last_child = child; - return child; - error: - return NULL; + assert(parent); + + // if 'parent' isn't the kind of block that can accept this child, + // then back up til we hit a block that can. + while (!can_contain(parent->tag, block_type)) { + finalize(parent, start_line); + parent = parent->parent; + } + + block* child = make_block(block_type, start_line, start_column); + child->parent = parent; + child->top = parent->top; + + if (parent->last_child) { + parent->last_child->next = child; + child->prev = parent->last_child; + } else { + parent->children = child; + child->prev = NULL; + } + parent->last_child = child; + return child; } // Free a block list and any children. extern void free_blocks(block* e) { - block * next; - while (e != NULL) { - next = e->next; - free_inlines(e->inline_content); - bdestroy(e->string_content); - if (e->tag == fenced_code) { - bdestroy(e->attributes.fenced_code_data.info); - } else if (e->tag == document) { - free_reference_map(e->attributes.refmap); - } - free_blocks(e->children); - free(e); - e = next; - } + block * next; + while (e != NULL) { + next = e->next; + free_inlines(e->inline_content); + gh_buf_free(&e->string_content); + if (e->tag == fenced_code) { + gh_buf_free(&e->attributes.fenced_code_data.info); + } else if (e->tag == document) { + free_reference_map(e->attributes.refmap); + } + free_blocks(e->children); + free(e); + e = next; + } } // Walk through block and all children, recursively, parsing // string content into inline content where appropriate. -int process_inlines(block* cur, reference** refmap) +void process_inlines(block* cur, reference** refmap) { - switch (cur->tag) { - - case paragraph: - case atx_header: - case setext_header: - check(cur->string_content != NULL, "string_content is NULL"); - cur->inline_content = parse_inlines(cur->string_content, refmap); - bdestroy(cur->string_content); - cur->string_content = NULL; - break; - - default: - break; - } - - block * child = cur->children; - while (child != NULL) { - process_inlines(child, refmap); - child = child->next; - } - - return 0; - error: - return -1; + switch (cur->tag) { + case paragraph: + case atx_header: + case setext_header: + cur->inline_content = parse_inlines(&cur->string_content, cur->string_pos, refmap); + // MEM + // gh_buf_free(&cur->string_content); + break; + + default: + break; + } + + block *child = cur->children; + while (child != NULL) { + process_inlines(child, refmap); + child = child->next; + } } // Attempts to parse a list item marker (bullet or enumerated). // On success, returns length of the marker, and populates // data with the details. On failure, returns 0. -static int parse_list_marker(bstring ln, int pos, - struct ListData ** dataptr) +static int parse_list_marker(gh_buf *ln, int pos, + struct ListData ** dataptr) { - char c; - int startpos; - int start = 1; - struct ListData * data; - - startpos = pos; - c = bchar(ln, pos); - - if ((c == '*' || c == '-' || c == '+') && !scan_hrule(ln, pos)) { - pos++; - if (!isspace(bchar(ln, pos))) { - return 0; - } - data = malloc(sizeof(struct ListData)); - data->marker_offset = 0; // will be adjusted later - data->list_type = bullet; - data->bullet_char = c; - data->start = 1; - data->delimiter = period; - data->tight = false; - - } else if (isdigit(c)) { - - pos++; - while (isdigit(bchar(ln, pos))) { - pos++; - } - - if (!sscanf((char *) ln->data + startpos, "%d", &start)) { - log_err("sscanf failed"); - return 0; - } - - c = bchar(ln, pos); - if (c == '.' || c == ')') { - pos++; - if (!isspace(bchar(ln, pos))) { - return 0; - } - data = malloc(sizeof(struct ListData)); - data->marker_offset = 0; // will be adjusted later - data->list_type = ordered; - data->bullet_char = 0; - data->start = start; - data->delimiter = (c == '.' ? period : parens); - data->tight = false; - } else { - return 0; - } - - } else { - return 0; - } - - *dataptr = data; - return (pos - startpos); + char c; + int startpos; + struct ListData * data; + + startpos = pos; + c = gh_buf_at(ln, pos); + + if ((c == '*' || c == '-' || c == '+') && !scan_hrule(ln, pos)) { + pos++; + if (!isspace(gh_buf_at(ln, pos))) { + return 0; + } + data = malloc(sizeof(struct ListData)); + data->marker_offset = 0; // will be adjusted later + data->list_type = bullet; + data->bullet_char = c; + data->start = 1; + data->delimiter = period; + data->tight = false; + + } else if (isdigit(c)) { + int start = 0; + + do { + start = (10 * start) + (gh_buf_at(ln, pos) - '0'); + pos++; + } while (isdigit(gh_buf_at(ln, pos))); + + c = gh_buf_at(ln, pos); + if (c == '.' || c == ')') { + pos++; + if (!isspace(gh_buf_at(ln, pos))) { + return 0; + } + data = malloc(sizeof(struct ListData)); + data->marker_offset = 0; // will be adjusted later + data->list_type = ordered; + data->bullet_char = 0; + data->start = start; + data->delimiter = (c == '.' ? period : parens); + data->tight = false; + } else { + return 0; + } + + } else { + return 0; + } + + *dataptr = data; + return (pos - startpos); } // Return 1 if list item belongs in list, else 0. static int lists_match(struct ListData list_data, - struct ListData item_data) + struct ListData item_data) +{ + return (list_data.list_type == item_data.list_type && + list_data.delimiter == item_data.delimiter && + // list_data.marker_offset == item_data.marker_offset && + list_data.bullet_char == item_data.bullet_char); +} + +static void expand_tabs(gh_buf *ob, const char *line, size_t size) +{ + size_t i = 0, tab = 0; + + while (i < size) { + size_t org = i; + + while (i < size && line[i] != '\t') { + i++; tab++; + } + + if (i > org) + gh_buf_put(ob, line + org, i - org); + + if (i >= size) + break; + + do { + gh_buf_putc(ob, ' '); tab++; + } while (tab % 4); + + i++; + } +} + +extern block *stmd_parse_document(const char *buffer, size_t len) { - return (list_data.list_type == item_data.list_type && - list_data.delimiter == item_data.delimiter && - // list_data.marker_offset == item_data.marker_offset && - list_data.bullet_char == item_data.bullet_char); + gh_buf line = GH_BUF_INIT; + + block *document = make_document(); + int linenum = 1; + const char *end = buffer + len; + + while (buffer < end) { + const char *eol = memchr(buffer, '\n', end - buffer); + + if (!eol) { + expand_tabs(&line, buffer, end - buffer); + buffer = end; + } else { + expand_tabs(&line, buffer, (eol - buffer) + 1); + buffer += (eol - buffer) + 1; + } + + incorporate_line(&line, linenum, &document); + gh_buf_clear(&line); + linenum++; + } + + gh_buf_free(&line); + + while (document != document->top) { + finalize(document, linenum); + document = document->parent; + } + + finalize(document, linenum); + process_inlines(document, document->attributes.refmap); + + return document; } // Process one line at a time, modifying a block. // Returns 0 if successful. curptr is changed to point to // the currently open block. -extern int incorporate_line(bstring ln, int line_number, block** curptr) +extern void incorporate_line(gh_buf *ln, int line_number, block** curptr) { - block* last_matched_container; - int offset = 0; - int matched = 0; - int lev = 0; - int i; - struct ListData * data = NULL; - bool all_matched = true; - block* container; - block* cur = *curptr; - bool blank = false; - int first_nonspace; - int indent; - - // detab input line - check(bdetab(ln, 1) != BSTR_ERR, - "invalid UTF-8 sequence in line %d\n", line_number); - - // container starts at the document root. - container = cur->top; - - // for each containing block, try to parse the associated line start. - // bail out on failure: container will point to the last matching block. - - while (container->last_child && container->last_child->open) { - container = container->last_child; - - first_nonspace = offset; - while (bchar(ln, first_nonspace) == ' ') { - first_nonspace++; - } - - indent = first_nonspace - offset; - blank = bchar(ln, first_nonspace) == '\n'; - - if (container->tag == block_quote) { - - matched = indent <= 3 && bchar(ln, first_nonspace) == '>'; - if (matched) { - offset = first_nonspace + 1; - if (bchar(ln, offset) == ' ') { - offset++; - } - } else { - all_matched = false; - } - - } else if (container->tag == list_item) { - - if (indent >= container->attributes.list_data.marker_offset + - container->attributes.list_data.padding) { - offset += container->attributes.list_data.marker_offset + - container->attributes.list_data.padding; - } else if (blank) { - offset = first_nonspace; - } else { - all_matched = false; - } - - } else if (container->tag == indented_code) { - - if (indent >= CODE_INDENT) { - offset += CODE_INDENT; - } else if (blank) { - offset = first_nonspace; - } else { - all_matched = false; - } - - } else if (container->tag == atx_header || - container->tag == setext_header) { - - // a header can never contain more than one line - all_matched = false; - - } else if (container->tag == fenced_code) { - - // skip optional spaces of fence offset - i = container->attributes.fenced_code_data.fence_offset; - while (i > 0 && bchar(ln, offset) == ' ') { - offset++; - i--; - } - - } else if (container->tag == html_block) { - - if (blank) { - all_matched = false; - } - - } else if (container->tag == paragraph) { - - if (blank) { - container->last_line_blank =true; - all_matched = false; - } - - } - - if (!all_matched) { - container = container->parent; // back up to last matching block - break; - } - } - - last_matched_container = container; - - // check to see if we've hit 2nd blank line, break out of list: - if (blank && container->last_line_blank) { - break_out_of_lists(&container, line_number); - } - - // unless last matched container is code block, try new container starts: - while (container->tag != fenced_code && container->tag != indented_code && - container->tag != html_block) { - - first_nonspace = offset; - while (bchar(ln, first_nonspace) == ' ') { - first_nonspace++; - } - - indent = first_nonspace - offset; - blank = bchar(ln, first_nonspace) == '\n'; - - if (indent >= CODE_INDENT) { - - if (cur->tag != paragraph && !blank) { - offset += CODE_INDENT; - container = add_child(container, indented_code, line_number, offset + 1); - } else { // indent > 4 in lazy line - break; - } - - } else if (bchar(ln, first_nonspace) == '>') { - - offset = first_nonspace + 1; - // optional following character - if (bchar(ln, offset) == ' ') { - offset++; - } - container = add_child(container, block_quote, line_number, offset + 1); - - } else if ((matched = scan_atx_header_start(ln, first_nonspace))) { - - offset = first_nonspace + matched; - container = add_child(container, atx_header, line_number, offset + 1); - int hashpos = bstrchrp(ln, '#', first_nonspace); - check(hashpos != BSTR_ERR, "no # found in atx header start"); - int level = 0; - while (bchar(ln, hashpos) == '#') { - level++; - hashpos++; - } - container->attributes.header_level = level; - - } else if ((matched = scan_open_code_fence(ln, first_nonspace))) { - - container = add_child(container, fenced_code, line_number, - first_nonspace + 1); - container->attributes.fenced_code_data.fence_char = bchar(ln, - first_nonspace); - container->attributes.fenced_code_data.fence_length = matched; - container->attributes.fenced_code_data.fence_offset = - first_nonspace - offset; - offset = first_nonspace + matched; - - } else if ((matched = scan_html_block_tag(ln, first_nonspace))) { - - container = add_child(container, html_block, line_number, - first_nonspace + 1); - // note, we don't adjust offset because the tag is part of the text - - } else if (container->tag == paragraph && - (lev = scan_setext_header_line(ln, first_nonspace)) && - // check that there is only one line in the paragraph: - bstrrchrp(container->string_content, '\n', - blength(container->string_content) - 2) == BSTR_ERR) { - - container->tag = setext_header; - container->attributes.header_level = lev; - offset = blength(ln) - 1; - - } else if (!(container->tag == paragraph && !all_matched) && - (matched = scan_hrule(ln, first_nonspace))) { - - // it's only now that we know the line is not part of a setext header: - container = add_child(container, hrule, line_number, first_nonspace + 1); - finalize(container, line_number); - container = container->parent; - offset = blength(ln) - 1; - - } else if ((matched = parse_list_marker(ln, first_nonspace, &data))) { - - // compute padding: - offset = first_nonspace + matched; - i = 0; - while (i <= 5 && bchar(ln, offset + i) == ' ') { - i++; - } - // i = number of spaces after marker, up to 5 - if (i >= 5 || i < 1 || bchar(ln, offset) == '\n') { - data->padding = matched + 1; - if (i > 0) { - offset += 1; - } - } else { - data->padding = matched + i; - offset += i; - } - - // check container; if it's a list, see if this list item - // can continue the list; otherwise, create a list container. - - data->marker_offset = indent; - - if (container->tag != list || - !lists_match(container->attributes.list_data, *data)) { - container = add_child(container, list, line_number, - first_nonspace + 1); - container->attributes.list_data = *data; - } - - // add the list item - container = add_child(container, list_item, line_number, - first_nonspace + 1); - container->attributes.list_data = *data; - free(data); - - } else { - break; - } - - if (accepts_lines(container->tag)) { - // if it's a line container, it can't contain other containers - break; - } - } - - // what remains at offset is a text line. add the text to the - // appropriate container. - - first_nonspace = offset; - while (bchar(ln, first_nonspace) == ' ') { - first_nonspace++; - } - - indent = first_nonspace - offset; - blank = bchar(ln, first_nonspace) == '\n'; - - // block quote lines are never blank as they start with > - // and we don't count blanks in fenced code for purposes of tight/loose - // lists or breaking out of lists. we also don't set last_line_blank - // on an empty list item. - container->last_line_blank = (blank && - container->tag != block_quote && - container->tag != fenced_code && - !(container->tag == list_item && - container->children == NULL && - container->start_line == line_number)); - - block *cont = container; - while (cont->parent) { - cont->parent->last_line_blank = false; - cont = cont->parent; - } - - if (cur != last_matched_container && - container == last_matched_container && - !blank && - cur->tag == paragraph && - blength(cur->string_content) > 0) { - - check(add_line(cur, ln, offset) == 0, "could not add line"); - - } else { // not a lazy continuation - - // finalize any blocks that were not matched and set cur to container: - while (cur != last_matched_container) { - - finalize(cur, line_number); - cur = cur->parent; - check(cur != NULL, "cur is NULL, last_matched_container->tag = %d", - last_matched_container->tag); - - } - - if (container->tag == indented_code) { - - check(add_line(container, ln, offset) == 0, "could not add line"); - - } else if (container->tag == fenced_code) { - - matched = (indent <= 3 - && bchar(ln, first_nonspace) == container->attributes.fenced_code_data.fence_char) - && scan_close_code_fence(ln, first_nonspace, - container->attributes.fenced_code_data.fence_length); - if (matched) { - // if closing fence, don't add line to container; instead, close it: - finalize(container, line_number); - container = container->parent; // back up to parent - } else { - check(add_line(container, ln, offset) == 0, "could not add line"); - } - - } else if (container->tag == html_block) { - - check(add_line(container, ln, offset) == 0, "could not add line"); - - } else if (blank) { - - // ??? do nothing - - } else if (container->tag == atx_header) { - - // chop off trailing ###s...use a scanner? - brtrimws(ln); - int p = blength(ln) - 1; - int numhashes = 0; - // if string ends in #s, remove these: - while (bchar(ln, p) == '#') { - p--; - numhashes++; - } - if (bchar(ln, p) == '\\') { - // the last # was escaped, so we include it. - p++; - numhashes--; - } - check(bdelete(ln, p + 1, numhashes) != BSTR_ERR, - "could not delete final hashes"); - check(add_line(container, ln, first_nonspace) == 0, "could not add line"); - finalize(container, line_number); - container = container->parent; - - } else if (accepts_lines(container->tag)) { - - check(add_line(container, ln, first_nonspace) == 0, "could not add line"); + block* last_matched_container; + int offset = 0; + int matched = 0; + int lev = 0; + int i; + struct ListData * data = NULL; + bool all_matched = true; + block* container; + block* cur = *curptr; + bool blank = false; + int first_nonspace; + int indent; + + // container starts at the document root. + container = cur->top; + + // for each containing block, try to parse the associated line start. + // bail out on failure: container will point to the last matching block. + + while (container->last_child && container->last_child->open) { + container = container->last_child; + + first_nonspace = offset; + while (gh_buf_at(ln, first_nonspace) == ' ') { + first_nonspace++; + } + + indent = first_nonspace - offset; + blank = gh_buf_at(ln, first_nonspace) == '\n'; + + if (container->tag == block_quote) { + + matched = indent <= 3 && gh_buf_at(ln, first_nonspace) == '>'; + if (matched) { + offset = first_nonspace + 1; + if (gh_buf_at(ln, offset) == ' ') { + offset++; + } + } else { + all_matched = false; + } + + } else if (container->tag == list_item) { + + if (indent >= container->attributes.list_data.marker_offset + + container->attributes.list_data.padding) { + offset += container->attributes.list_data.marker_offset + + container->attributes.list_data.padding; + } else if (blank) { + offset = first_nonspace; + } else { + all_matched = false; + } + + } else if (container->tag == indented_code) { + + if (indent >= CODE_INDENT) { + offset += CODE_INDENT; + } else if (blank) { + offset = first_nonspace; + } else { + all_matched = false; + } + + } else if (container->tag == atx_header || + container->tag == setext_header) { + + // a header can never contain more than one line + all_matched = false; + + } else if (container->tag == fenced_code) { + + // skip optional spaces of fence offset + i = container->attributes.fenced_code_data.fence_offset; + while (i > 0 && gh_buf_at(ln, offset) == ' ') { + offset++; + i--; + } + + } else if (container->tag == html_block) { + + if (blank) { + all_matched = false; + } + + } else if (container->tag == paragraph) { + + if (blank) { + container->last_line_blank = true; + all_matched = false; + } + + } + + if (!all_matched) { + container = container->parent; // back up to last matching block + break; + } + } + + last_matched_container = container; + + // check to see if we've hit 2nd blank line, break out of list: + if (blank && container->last_line_blank) { + break_out_of_lists(&container, line_number); + } + + // unless last matched container is code block, try new container starts: + while (container->tag != fenced_code && container->tag != indented_code && + container->tag != html_block) { + + first_nonspace = offset; + while (gh_buf_at(ln, first_nonspace) == ' ') { + first_nonspace++; + } + + indent = first_nonspace - offset; + blank = gh_buf_at(ln, first_nonspace) == '\n'; + + if (indent >= CODE_INDENT) { + + if (cur->tag != paragraph && !blank) { + offset += CODE_INDENT; + container = add_child(container, indented_code, line_number, offset + 1); + } else { // indent > 4 in lazy line + break; + } + + } else if (gh_buf_at(ln, first_nonspace) == '>') { + + offset = first_nonspace + 1; + // optional following character + if (gh_buf_at(ln, offset) == ' ') { + offset++; + } + container = add_child(container, block_quote, line_number, offset + 1); + + } else if ((matched = scan_atx_header_start(ln, first_nonspace))) { + + offset = first_nonspace + matched; + container = add_child(container, atx_header, line_number, offset + 1); + + int hashpos = gh_buf_strchr(ln, '#', first_nonspace); + assert(hashpos >= 0); + + int level = 0; + while (gh_buf_at(ln, hashpos) == '#') { + level++; + hashpos++; + } + container->attributes.header_level = level; + + } else if ((matched = scan_open_code_fence(ln, first_nonspace))) { + + container = add_child(container, fenced_code, line_number, + first_nonspace + 1); + container->attributes.fenced_code_data.fence_char = gh_buf_at(ln, + first_nonspace); + container->attributes.fenced_code_data.fence_length = matched; + container->attributes.fenced_code_data.fence_offset = + first_nonspace - offset; + offset = first_nonspace + matched; + + } else if ((matched = scan_html_block_tag(ln, first_nonspace))) { + + container = add_child(container, html_block, line_number, + first_nonspace + 1); + // note, we don't adjust offset because the tag is part of the text + + } else if (container->tag == paragraph && + (lev = scan_setext_header_line(ln, first_nonspace)) && + // check that there is only one line in the paragraph: + gh_buf_strrchr(&container->string_content, '\n', + gh_buf_len(&container->string_content) - 2) < 0) { + + container->tag = setext_header; + container->attributes.header_level = lev; + offset = gh_buf_len(ln) - 1; + + } else if (!(container->tag == paragraph && !all_matched) && + (matched = scan_hrule(ln, first_nonspace))) { + + // it's only now that we know the line is not part of a setext header: + container = add_child(container, hrule, line_number, first_nonspace + 1); + finalize(container, line_number); + container = container->parent; + offset = gh_buf_len(ln) - 1; + + } else if ((matched = parse_list_marker(ln, first_nonspace, &data))) { + + // compute padding: + offset = first_nonspace + matched; + i = 0; + while (i <= 5 && gh_buf_at(ln, offset + i) == ' ') { + i++; + } + // i = number of spaces after marker, up to 5 + if (i >= 5 || i < 1 || gh_buf_at(ln, offset) == '\n') { + data->padding = matched + 1; + if (i > 0) { + offset += 1; + } + } else { + data->padding = matched + i; + offset += i; + } + + // check container; if it's a list, see if this list item + // can continue the list; otherwise, create a list container. + + data->marker_offset = indent; + + if (container->tag != list || + !lists_match(container->attributes.list_data, *data)) { + container = add_child(container, list, line_number, + first_nonspace + 1); + container->attributes.list_data = *data; + } + + // add the list item + container = add_child(container, list_item, line_number, + first_nonspace + 1); + container->attributes.list_data = *data; + free(data); + + } else { + break; + } + + if (accepts_lines(container->tag)) { + // if it's a line container, it can't contain other containers + break; + } + } + + // what remains at offset is a text line. add the text to the + // appropriate container. + + first_nonspace = offset; + while (gh_buf_at(ln, first_nonspace) == ' ') { + first_nonspace++; + } + + indent = first_nonspace - offset; + blank = gh_buf_at(ln, first_nonspace) == '\n'; + + // block quote lines are never blank as they start with > + // and we don't count blanks in fenced code for purposes of tight/loose + // lists or breaking out of lists. we also don't set last_line_blank + // on an empty list item. + container->last_line_blank = (blank && + container->tag != block_quote && + container->tag != fenced_code && + !(container->tag == list_item && + container->children == NULL && + container->start_line == line_number)); + + block *cont = container; + while (cont->parent) { + cont->parent->last_line_blank = false; + cont = cont->parent; + } + + if (cur != last_matched_container && + container == last_matched_container && + !blank && + cur->tag == paragraph && + gh_buf_len(&cur->string_content) > 0) { + + add_line(cur, ln, offset); + + } else { // not a lazy continuation + + // finalize any blocks that were not matched and set cur to container: + while (cur != last_matched_container) { + + finalize(cur, line_number); + cur = cur->parent; + assert(cur != NULL); + } + + if (container->tag == indented_code) { + + add_line(container, ln, offset); + + } else if (container->tag == fenced_code) { + + matched = (indent <= 3 + && gh_buf_at(ln, first_nonspace) == container->attributes.fenced_code_data.fence_char) + && scan_close_code_fence(ln, first_nonspace, + container->attributes.fenced_code_data.fence_length); + if (matched) { + // if closing fence, don't add line to container; instead, close it: + finalize(container, line_number); + container = container->parent; // back up to parent + } else { + add_line(container, ln, offset); + } + + } else if (container->tag == html_block) { + + add_line(container, ln, offset); + + } else if (blank) { + + // ??? do nothing + + } else if (container->tag == atx_header) { + // chop off trailing ###s...use a scanner? + gh_buf_trim(ln); + int p = gh_buf_len(ln) - 1; + + // if string ends in #s, remove these: + while (gh_buf_at(ln, p) == '#') { + p--; + } + if (gh_buf_at(ln, p) == '\\') { + // the last # was escaped, so we include it. + p++; + } + + gh_buf_truncate(ln, p + 1); + add_line(container, ln, first_nonspace); + finalize(container, line_number); + container = container->parent; + + } else if (accepts_lines(container->tag)) { + + add_line(container, ln, first_nonspace); + + } else if (container->tag != hrule && container->tag != setext_header) { + + // create paragraph container for line + container = add_child(container, paragraph, line_number, first_nonspace + 1); + add_line(container, ln, first_nonspace); - } else if (container->tag != hrule && container->tag != setext_header) { - - // create paragraph container for line - container = add_child(container, paragraph, line_number, first_nonspace + 1); - check(add_line(container, ln, first_nonspace) == 0, "could not add line"); - - } else { + } else { + assert(false); + } - log_warn("Line %d with container type %d did not match any condition:\n\"%s\"", - line_number, container->tag, ln->data); - - } - *curptr = container; - } - - return 0; - error: - return -1; + *curptr = container; + } } diff --git a/src/bstrlib.c b/src/bstrlib.c deleted file mode 100644 index 1b19dbe..0000000 --- a/src/bstrlib.c +++ /dev/null @@ -1,2979 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ - -/* - * bstrlib.c - * - * This file is the core module for implementing the bstring functions. - */ - -#if defined (_MSC_VER) -/* These warnings from MSVC++ are totally pointless. */ -# define _CRT_SECURE_NO_WARNINGS -#endif - -#include -#include -#include -#include -#include -#include -#include "bstrlib.h" - -/* Optionally include a mechanism for debugging memory */ - -#if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG) -#include "memdbg.h" -#endif - -#ifndef bstr__alloc -#define bstr__alloc(x) malloc (x) -#endif - -#ifndef bstr__free -#define bstr__free(p) free (p) -#endif - -#ifndef bstr__realloc -#define bstr__realloc(p,x) realloc ((p), (x)) -#endif - -#ifndef bstr__memcpy -#define bstr__memcpy(d,s,l) memcpy ((d), (s), (l)) -#endif - -#ifndef bstr__memmove -#define bstr__memmove(d,s,l) memmove ((d), (s), (l)) -#endif - -#ifndef bstr__memset -#define bstr__memset(d,c,l) memset ((d), (c), (l)) -#endif - -#ifndef bstr__memcmp -#define bstr__memcmp(d,c,l) memcmp ((d), (c), (l)) -#endif - -#ifndef bstr__memchr -#define bstr__memchr(s,c,l) memchr ((s), (c), (l)) -#endif - -/* Just a length safe wrapper for memmove. */ - -#define bBlockCopy(D,S,L) { if ((L) > 0) bstr__memmove ((D),(S),(L)); } - -/* Compute the snapped size for a given requested size. By snapping to powers - of 2 like this, repeated reallocations are avoided. */ -static int snapUpSize (int i) { - if (i < 8) { - i = 8; - } else { - unsigned int j; - j = (unsigned int) i; - - j |= (j >> 1); - j |= (j >> 2); - j |= (j >> 4); - j |= (j >> 8); /* Ok, since int >= 16 bits */ -#if (UINT_MAX != 0xffff) - j |= (j >> 16); /* For 32 bit int systems */ -#if (UINT_MAX > 0xffffffffUL) - j |= (j >> 32); /* For 64 bit int systems */ -#endif -#endif - /* Least power of two greater than i */ - j++; - if ((int) j >= i) i = (int) j; - } - return i; -} - -/* int balloc (bstring b, int len) - * - * Increase the size of the memory backing the bstring b to at least len. - */ -int balloc (bstring b, int olen) { - int len; - if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen <= 0 || - b->mlen < b->slen || olen <= 0) { - return BSTR_ERR; - } - - if (olen >= b->mlen) { - unsigned char * x; - - if ((len = snapUpSize (olen)) <= b->mlen) return BSTR_OK; - - /* Assume probability of a non-moving realloc is 0.125 */ - if (7 * b->mlen < 8 * b->slen) { - - /* If slen is close to mlen in size then use realloc to reduce - the memory defragmentation */ - - reallocStrategy:; - - x = (unsigned char *) bstr__realloc (b->data, (size_t) len); - if (x == NULL) { - - /* Since we failed, try allocating the tighest possible - allocation */ - - if (NULL == (x = (unsigned char *) bstr__realloc (b->data, (size_t) (len = olen)))) { - return BSTR_ERR; - } - } - } else { - - /* If slen is not close to mlen then avoid the penalty of copying - the extra bytes that are allocated, but not considered part of - the string */ - - if (NULL == (x = (unsigned char *) bstr__alloc ((size_t) len))) { - - /* Perhaps there is no available memory for the two - allocations to be in memory at once */ - - goto reallocStrategy; - - } else { - if (b->slen) bstr__memcpy ((char *) x, (char *) b->data, (size_t) b->slen); - bstr__free (b->data); - } - } - b->data = x; - b->mlen = len; - b->data[b->slen] = (unsigned char) '\0'; - } - - return BSTR_OK; -} - -/* int ballocmin (bstring b, int len) - * - * Set the size of the memory backing the bstring b to len or b->slen+1, - * whichever is larger. Note that repeated use of this function can degrade - * performance. - */ -int ballocmin (bstring b, int len) { - unsigned char * s; - - if (b == NULL || b->data == NULL || (b->slen+1) < 0 || b->mlen <= 0 || - b->mlen < b->slen || len <= 0) { - return BSTR_ERR; - } - - if (len < b->slen + 1) len = b->slen + 1; - - if (len != b->mlen) { - s = (unsigned char *) bstr__realloc (b->data, (size_t) len); - if (NULL == s) return BSTR_ERR; - s[b->slen] = (unsigned char) '\0'; - b->data = s; - b->mlen = len; - } - - return BSTR_OK; -} - -/* bstring bfromcstr (const char * str) - * - * Create a bstring which contains the contents of the '\0' terminated char * - * buffer str. - */ -bstring bfromcstr (const char * str) { -bstring b; -int i; -size_t j; - - if (str == NULL) return NULL; - j = (strlen) (str); - i = snapUpSize ((int) (j + (2 - (j != 0)))); - if (i <= (int) j) return NULL; - - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (NULL == b) return NULL; - b->slen = (int) j; - if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { - bstr__free (b); - return NULL; - } - - bstr__memcpy (b->data, str, j+1); - return b; -} - -/* bstring bfromcstralloc (int mlen, const char * str) - * - * Create a bstring which contains the contents of the '\0' terminated char * - * buffer str. The memory buffer backing the string is at least len - * characters in length. - */ -bstring bfromcstralloc (int mlen, const char * str) { -bstring b; -int i; -size_t j; - - if (str == NULL) return NULL; - j = (strlen) (str); - i = snapUpSize ((int) (j + (2 - (j != 0)))); - if (i <= (int) j) return NULL; - - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (b == NULL) return NULL; - b->slen = (int) j; - if (i < mlen) i = mlen; - - if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { - bstr__free (b); - return NULL; - } - - bstr__memcpy (b->data, str, j+1); - return b; -} - -/* bstring blk2bstr (const void * blk, int len) - * - * Create a bstring which contains the content of the block blk of length - * len. - */ -bstring blk2bstr (const void * blk, int len) { -bstring b; -int i; - - if (blk == NULL || len < 0) return NULL; - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (b == NULL) return NULL; - b->slen = len; - - i = len + (2 - (len != 0)); - i = snapUpSize (i); - - b->mlen = i; - - b->data = (unsigned char *) bstr__alloc ((size_t) b->mlen); - if (b->data == NULL) { - bstr__free (b); - return NULL; - } - - if (len > 0) bstr__memcpy (b->data, blk, (size_t) len); - b->data[len] = (unsigned char) '\0'; - - return b; -} - -/* char * bstr2cstr (const_bstring s, char z) - * - * Create a '\0' terminated char * buffer which is equal to the contents of - * the bstring s, except that any contained '\0' characters are converted - * to the character in z. This returned value should be freed with a - * bcstrfree () call, by the calling application. - */ -char * bstr2cstr (const_bstring b, char z) { -int i, l; -char * r; - - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - l = b->slen; - r = (char *) bstr__alloc ((size_t) (l + 1)); - if (r == NULL) return r; - - for (i=0; i < l; i ++) { - r[i] = (char) ((b->data[i] == '\0') ? z : (char) (b->data[i])); - } - - r[l] = (unsigned char) '\0'; - - return r; -} - -/* int bcstrfree (char * s) - * - * Frees a C-string generated by bstr2cstr (). This is normally unnecessary - * since it just wraps a call to bstr__free (), however, if bstr__alloc () - * and bstr__free () have been redefined as a macros within the bstrlib - * module (via defining them in memdbg.h after defining - * BSTRLIB_MEMORY_DEBUG) with some difference in behaviour from the std - * library functions, then this allows a correct way of freeing the memory - * that allows higher level code to be independent from these macro - * redefinitions. - */ -int bcstrfree (char * s) { - if (s) { - bstr__free (s); - return BSTR_OK; - } - return BSTR_ERR; -} - -/* int bconcat (bstring b0, const_bstring b1) - * - * Concatenate the bstring b1 to the bstring b0. - */ -int bconcat (bstring b0, const_bstring b1) { -int len, d; -bstring aux = (bstring) b1; - - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL) return BSTR_ERR; - - d = b0->slen; - len = b1->slen; - if ((d | (b0->mlen - d) | len | (d + len)) < 0) return BSTR_ERR; - - if (b0->mlen <= d + len + 1) { - ptrdiff_t pd = b1->data - b0->data; - if (0 <= pd && pd < b0->mlen) { - if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; - } - if (balloc (b0, d + len + 1) != BSTR_OK) { - if (aux != b1) bdestroy (aux); - return BSTR_ERR; - } - } - - bBlockCopy (&b0->data[d], &aux->data[0], (size_t) len); - b0->data[d + len] = (unsigned char) '\0'; - b0->slen = d + len; - if (aux != b1) bdestroy (aux); - return BSTR_OK; -} - -/* int bconchar (bstring b, char c) -/ * - * Concatenate the single character c to the bstring b. - */ -int bconchar (bstring b, char c) { -int d; - - if (b == NULL) return BSTR_ERR; - d = b->slen; - if ((d | (b->mlen - d)) < 0 || balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; - b->data[d] = (unsigned char) c; - b->data[d + 1] = (unsigned char) '\0'; - b->slen++; - return BSTR_OK; -} - -/* int bcatcstr (bstring b, const char * s) - * - * Concatenate a char * string to a bstring. - */ -int bcatcstr (bstring b, const char * s) { -char * d; -int i, l; - - if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen - || b->mlen <= 0 || s == NULL) return BSTR_ERR; - - /* Optimistically concatenate directly */ - l = b->mlen - b->slen; - d = (char *) &b->data[b->slen]; - for (i=0; i < l; i++) { - if ((*d++ = *s++) == '\0') { - b->slen += i; - return BSTR_OK; - } - } - b->slen += i; - - /* Need to explicitely resize and concatenate tail */ - return bcatblk (b, (const void *) s, (int) strlen (s)); -} - -/* int bcatblk (bstring b, const void * s, int len) - * - * Concatenate a fixed length buffer to a bstring. - */ -int bcatblk (bstring b, const void * s, int len) { -int nl; - - if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen - || b->mlen <= 0 || s == NULL || len < 0) return BSTR_ERR; - - if (0 > (nl = b->slen + len)) return BSTR_ERR; /* Overflow? */ - if (b->mlen <= nl && 0 > balloc (b, nl + 1)) return BSTR_ERR; - - bBlockCopy (&b->data[b->slen], s, (size_t) len); - b->slen = nl; - b->data[nl] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* bstring bstrcpy (const_bstring b) - * - * Create a copy of the bstring b. - */ -bstring bstrcpy (const_bstring b) { -bstring b0; -int i,j; - - /* Attempted to copy an invalid string? */ - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - - b0 = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (b0 == NULL) { - /* Unable to allocate memory for string header */ - return NULL; - } - - i = b->slen; - j = snapUpSize (i + 1); - - b0->data = (unsigned char *) bstr__alloc (j); - if (b0->data == NULL) { - j = i + 1; - b0->data = (unsigned char *) bstr__alloc (j); - if (b0->data == NULL) { - /* Unable to allocate memory for string data */ - bstr__free (b0); - return NULL; - } - } - - b0->mlen = j; - b0->slen = i; - - if (i) bstr__memcpy ((char *) b0->data, (char *) b->data, i); - b0->data[b0->slen] = (unsigned char) '\0'; - - return b0; -} - -/* int bassign (bstring a, const_bstring b) - * - * Overwrite the string a with the contents of string b. - */ -int bassign (bstring a, const_bstring b) { - if (b == NULL || b->data == NULL || b->slen < 0) - return BSTR_ERR; - if (b->slen != 0) { - if (balloc (a, b->slen) != BSTR_OK) return BSTR_ERR; - bstr__memmove (a->data, b->data, b->slen); - } else { - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0) - return BSTR_ERR; - } - a->data[b->slen] = (unsigned char) '\0'; - a->slen = b->slen; - return BSTR_OK; -} - -/* int bassignmidstr (bstring a, const_bstring b, int left, int len) - * - * Overwrite the string a with the middle of contents of string b - * starting from position left and running for a length len. left and - * len are clamped to the ends of b as with the function bmidstr. - */ -int bassignmidstr (bstring a, const_bstring b, int left, int len) { - if (b == NULL || b->data == NULL || b->slen < 0) - return BSTR_ERR; - - if (left < 0) { - len += left; - left = 0; - } - - if (len > b->slen - left) len = b->slen - left; - - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0) - return BSTR_ERR; - - if (len > 0) { - if (balloc (a, len) != BSTR_OK) return BSTR_ERR; - bstr__memmove (a->data, b->data + left, len); - a->slen = len; - } else { - a->slen = 0; - } - a->data[a->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bassigncstr (bstring a, const char * str) - * - * Overwrite the string a with the contents of char * string str. Note that - * the bstring a must be a well defined and writable bstring. If an error - * occurs BSTR_ERR is returned however a may be partially overwritten. - */ -int bassigncstr (bstring a, const char * str) { -int i; -size_t len; - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0 || NULL == str) - return BSTR_ERR; - - for (i=0; i < a->mlen; i++) { - if ('\0' == (a->data[i] = str[i])) { - a->slen = i; - return BSTR_OK; - } - } - - a->slen = i; - len = strlen (str + i); - if (len > INT_MAX || i + len + 1 > INT_MAX || - 0 > balloc (a, (int) (i + len + 1))) return BSTR_ERR; - bBlockCopy (a->data + i, str + i, (size_t) len + 1); - a->slen += (int) len; - return BSTR_OK; -} - -/* int bassignblk (bstring a, const void * s, int len) - * - * Overwrite the string a with the contents of the block (s, len). Note that - * the bstring a must be a well defined and writable bstring. If an error - * occurs BSTR_ERR is returned and a is not overwritten. - */ -int bassignblk (bstring a, const void * s, int len) { - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0 || NULL == s || len + 1 < 1) - return BSTR_ERR; - if (len + 1 > a->mlen && 0 > balloc (a, len + 1)) return BSTR_ERR; - bBlockCopy (a->data, s, (size_t) len); - a->data[len] = (unsigned char) '\0'; - a->slen = len; - return BSTR_OK; -} - -/* int btrunc (bstring b, int n) - * - * Truncate the bstring to at most n characters. - */ -int btrunc (bstring b, int n) { - if (n < 0 || b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - if (b->slen > n) { - b->slen = n; - b->data[n] = (unsigned char) '\0'; - } - return BSTR_OK; -} - -#define upcase(c) (toupper ((unsigned char) c)) -#define downcase(c) (tolower ((unsigned char) c)) -#define wspace(c) (isspace ((unsigned char) c)) - -/* int btoupper (bstring b) - * - * Convert contents of bstring to upper case. - */ -int btoupper (bstring b) { -int i, len; - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - for (i=0, len = b->slen; i < len; i++) { - b->data[i] = (unsigned char) upcase (b->data[i]); - } - return BSTR_OK; -} - -/* int btolower (bstring b) - * - * Convert contents of bstring to lower case. - */ -int btolower (bstring b) { -int i, len; - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - for (i=0, len = b->slen; i < len; i++) { - b->data[i] = (unsigned char) downcase (b->data[i]); - } - return BSTR_OK; -} - -/* int bstricmp (const_bstring b0, const_bstring b1) - * - * Compare two strings without differentiating between case. The return - * value is the difference of the values of the characters where the two - * strings first differ after lower case transformation, otherwise 0 is - * returned indicating that the strings are equal. If the lengths are - * different, then a difference from 0 is given, but if the first extra - * character is '\0', then it is taken to be the value UCHAR_MAX+1. - */ -int bstricmp (const_bstring b0, const_bstring b1) { -int i, v, n; - - if (bdata (b0) == NULL || b0->slen < 0 || - bdata (b1) == NULL || b1->slen < 0) return SHRT_MIN; - if ((n = b0->slen) > b1->slen) n = b1->slen; - else if (b0->slen == b1->slen && b0->data == b1->data) return BSTR_OK; - - for (i = 0; i < n; i ++) { - v = (char) downcase (b0->data[i]) - - (char) downcase (b1->data[i]); - if (0 != v) return v; - } - - if (b0->slen > n) { - v = (char) downcase (b0->data[n]); - if (v) return v; - return UCHAR_MAX + 1; - } - if (b1->slen > n) { - v = - (char) downcase (b1->data[n]); - if (v) return v; - return - (int) (UCHAR_MAX + 1); - } - return BSTR_OK; -} - -/* int bstrnicmp (const_bstring b0, const_bstring b1, int n) - * - * Compare two strings without differentiating between case for at most n - * characters. If the position where the two strings first differ is - * before the nth position, the return value is the difference of the values - * of the characters, otherwise 0 is returned. If the lengths are different - * and less than n characters, then a difference from 0 is given, but if the - * first extra character is '\0', then it is taken to be the value - * UCHAR_MAX+1. - */ -int bstrnicmp (const_bstring b0, const_bstring b1, int n) { -int i, v, m; - - if (bdata (b0) == NULL || b0->slen < 0 || - bdata (b1) == NULL || b1->slen < 0 || n < 0) return SHRT_MIN; - m = n; - if (m > b0->slen) m = b0->slen; - if (m > b1->slen) m = b1->slen; - - if (b0->data != b1->data) { - for (i = 0; i < m; i ++) { - v = (char) downcase (b0->data[i]); - v -= (char) downcase (b1->data[i]); - if (v != 0) return b0->data[i] - b1->data[i]; - } - } - - if (n == m || b0->slen == b1->slen) return BSTR_OK; - - if (b0->slen > m) { - v = (char) downcase (b0->data[m]); - if (v) return v; - return UCHAR_MAX + 1; - } - - v = - (char) downcase (b1->data[m]); - if (v) return v; - return - (int) (UCHAR_MAX + 1); -} - -/* int biseqcaseless (const_bstring b0, const_bstring b1) - * - * Compare two strings for equality without differentiating between case. - * If the strings differ other than in case, 0 is returned, if the strings - * are the same, 1 is returned, if there is an error, -1 is returned. If - * the length of the strings are different, this function is O(1). '\0' - * termination characters are not treated in any special way. - */ -int biseqcaseless (const_bstring b0, const_bstring b1) { -int i, n; - - if (bdata (b0) == NULL || b0->slen < 0 || - bdata (b1) == NULL || b1->slen < 0) return BSTR_ERR; - if (b0->slen != b1->slen) return BSTR_OK; - if (b0->data == b1->data || b0->slen == 0) return 1; - for (i=0, n=b0->slen; i < n; i++) { - if (b0->data[i] != b1->data[i]) { - unsigned char c = (unsigned char) downcase (b0->data[i]); - if (c != (unsigned char) downcase (b1->data[i])) return 0; - } - } - return 1; -} - -/* int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) - * - * Compare beginning of string b0 with a block of memory of length len - * without differentiating between case for equality. If the beginning of b0 - * differs from the memory block other than in case (or if b0 is too short), - * 0 is returned, if the strings are the same, 1 is returned, if there is an - * error, -1 is returned. '\0' characters are not treated in any special - * way. - */ -int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) { -int i; - - if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) - return BSTR_ERR; - if (b0->slen < len) return BSTR_OK; - if (b0->data == (const unsigned char *) blk || len == 0) return 1; - - for (i = 0; i < len; i ++) { - if (b0->data[i] != ((const unsigned char *) blk)[i]) { - if (downcase (b0->data[i]) != - downcase (((const unsigned char *) blk)[i])) return 0; - } - } - return 1; -} - -/* - * int bltrimws (bstring b) - * - * Delete whitespace contiguous from the left end of the string. - */ -int bltrimws (bstring b) { -int i, len; - - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - - for (len = b->slen, i = 0; i < len; i++) { - if (!wspace (b->data[i])) { - return bdelete (b, 0, i); - } - } - - b->data[0] = (unsigned char) '\0'; - b->slen = 0; - return BSTR_OK; -} - -/* - * int brtrimws (bstring b) - * - * Delete whitespace contiguous from the right end of the string. - */ -int brtrimws (bstring b) { -int i; - - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - - for (i = b->slen - 1; i >= 0; i--) { - if (!wspace (b->data[i])) { - if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; - b->slen = i + 1; - return BSTR_OK; - } - } - - b->data[0] = (unsigned char) '\0'; - b->slen = 0; - return BSTR_OK; -} - -/* - * int btrimws (bstring b) - * - * Delete whitespace contiguous from both ends of the string. - */ -int btrimws (bstring b) { -int i, j; - - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - - for (i = b->slen - 1; i >= 0; i--) { - if (!wspace (b->data[i])) { - if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; - b->slen = i + 1; - for (j = 0; wspace (b->data[j]); j++) {} - return bdelete (b, 0, j); - } - } - - b->data[0] = (unsigned char) '\0'; - b->slen = 0; - return BSTR_OK; -} - -/* int biseq (const_bstring b0, const_bstring b1) - * - * Compare the string b0 and b1. If the strings differ, 0 is returned, if - * the strings are the same, 1 is returned, if there is an error, -1 is - * returned. If the length of the strings are different, this function is - * O(1). '\0' termination characters are not treated in any special way. - */ -int biseq (const_bstring b0, const_bstring b1) { - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || - b0->slen < 0 || b1->slen < 0) return BSTR_ERR; - if (b0->slen != b1->slen) return BSTR_OK; - if (b0->data == b1->data || b0->slen == 0) return 1; - return !bstr__memcmp (b0->data, b1->data, b0->slen); -} - -/* int bisstemeqblk (const_bstring b0, const void * blk, int len) - * - * Compare beginning of string b0 with a block of memory of length len for - * equality. If the beginning of b0 differs from the memory block (or if b0 - * is too short), 0 is returned, if the strings are the same, 1 is returned, - * if there is an error, -1 is returned. '\0' characters are not treated in - * any special way. - */ -int bisstemeqblk (const_bstring b0, const void * blk, int len) { -int i; - - if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) - return BSTR_ERR; - if (b0->slen < len) return BSTR_OK; - if (b0->data == (const unsigned char *) blk || len == 0) return 1; - - for (i = 0; i < len; i ++) { - if (b0->data[i] != ((const unsigned char *) blk)[i]) return BSTR_OK; - } - return 1; -} - -/* int biseqcstr (const_bstring b, const char *s) - * - * Compare the bstring b and char * string s. The C string s must be '\0' - * terminated at exactly the length of the bstring b, and the contents - * between the two must be identical with the bstring b with no '\0' - * characters for the two contents to be considered equal. This is - * equivalent to the condition that their current contents will be always be - * equal when comparing them in the same format after converting one or the - * other. If the strings are equal 1 is returned, if they are unequal 0 is - * returned and if there is a detectable error BSTR_ERR is returned. - */ -int biseqcstr (const_bstring b, const char * s) { -int i; - if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; - for (i=0; i < b->slen; i++) { - if (s[i] == '\0' || b->data[i] != (unsigned char) s[i]) return BSTR_OK; - } - return s[i] == '\0'; -} - -/* int biseqcstrcaseless (const_bstring b, const char *s) - * - * Compare the bstring b and char * string s. The C string s must be '\0' - * terminated at exactly the length of the bstring b, and the contents - * between the two must be identical except for case with the bstring b with - * no '\0' characters for the two contents to be considered equal. This is - * equivalent to the condition that their current contents will be always be - * equal ignoring case when comparing them in the same format after - * converting one or the other. If the strings are equal, except for case, - * 1 is returned, if they are unequal regardless of case 0 is returned and - * if there is a detectable error BSTR_ERR is returned. - */ -int biseqcstrcaseless (const_bstring b, const char * s) { -int i; - if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; - for (i=0; i < b->slen; i++) { - if (s[i] == '\0' || - (b->data[i] != (unsigned char) s[i] && - downcase (b->data[i]) != (unsigned char) downcase (s[i]))) - return BSTR_OK; - } - return s[i] == '\0'; -} - -/* int bstrcmp (const_bstring b0, const_bstring b1) - * - * Compare the string b0 and b1. If there is an error, SHRT_MIN is returned, - * otherwise a value less than or greater than zero, indicating that the - * string pointed to by b0 is lexicographically less than or greater than - * the string pointed to by b1 is returned. If the the string lengths are - * unequal but the characters up until the length of the shorter are equal - * then a value less than, or greater than zero, indicating that the string - * pointed to by b0 is shorter or longer than the string pointed to by b1 is - * returned. 0 is returned if and only if the two strings are the same. If - * the length of the strings are different, this function is O(n). Like its - * standard C library counter part strcmp, the comparison does not proceed - * past any '\0' termination characters encountered. - */ -int bstrcmp (const_bstring b0, const_bstring b1) { -int i, v, n; - - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || - b0->slen < 0 || b1->slen < 0) return SHRT_MIN; - n = b0->slen; if (n > b1->slen) n = b1->slen; - if (b0->slen == b1->slen && (b0->data == b1->data || b0->slen == 0)) - return BSTR_OK; - - for (i = 0; i < n; i ++) { - v = ((char) b0->data[i]) - ((char) b1->data[i]); - if (v != 0) return v; - if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; - } - - if (b0->slen > n) return 1; - if (b1->slen > n) return -1; - return BSTR_OK; -} - -/* int bstrncmp (const_bstring b0, const_bstring b1, int n) - * - * Compare the string b0 and b1 for at most n characters. If there is an - * error, SHRT_MIN is returned, otherwise a value is returned as if b0 and - * b1 were first truncated to at most n characters then bstrcmp was called - * with these new strings are paremeters. If the length of the strings are - * different, this function is O(n). Like its standard C library counter - * part strcmp, the comparison does not proceed past any '\0' termination - * characters encountered. - */ -int bstrncmp (const_bstring b0, const_bstring b1, int n) { -int i, v, m; - - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || - b0->slen < 0 || b1->slen < 0) return SHRT_MIN; - m = n; - if (m > b0->slen) m = b0->slen; - if (m > b1->slen) m = b1->slen; - - if (b0->data != b1->data) { - for (i = 0; i < m; i ++) { - v = ((char) b0->data[i]) - ((char) b1->data[i]); - if (v != 0) return v; - if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; - } - } - - if (n == m || b0->slen == b1->slen) return BSTR_OK; - - if (b0->slen > m) return 1; - return -1; -} - -/* bstring bmidstr (const_bstring b, int left, int len) - * - * Create a bstring which is the substring of b starting from position left - * and running for a length len (clamped by the end of the bstring b.) If - * b is detectably invalid, then NULL is returned. The section described - * by (left, len) is clamped to the boundaries of b. - */ -bstring bmidstr (const_bstring b, int left, int len) { - - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - - if (left < 0) { - len += left; - left = 0; - } - - if (len > b->slen - left) len = b->slen - left; - - if (len <= 0) return bfromcstr (""); - return blk2bstr (b->data + left, len); -} - -/* int bdelete (bstring b, int pos, int len) - * - * Removes characters from pos to pos+len-1 inclusive and shifts the tail of - * the bstring starting from pos+len to pos. len must be positive for this - * call to have any effect. The section of the string described by (pos, - * len) is clamped to boundaries of the bstring b. - */ -int bdelete (bstring b, int pos, int len) { - /* Clamp to left side of bstring */ - if (pos < 0) { - len += pos; - pos = 0; - } - - if (len < 0 || b == NULL || b->data == NULL || b->slen < 0 || - b->mlen < b->slen || b->mlen <= 0) - return BSTR_ERR; - if (len > 0 && pos < b->slen) { - if (pos + len >= b->slen) { - b->slen = pos; - } else { - bBlockCopy ((char *) (b->data + pos), - (char *) (b->data + pos + len), - b->slen - (pos+len)); - b->slen -= len; - } - b->data[b->slen] = (unsigned char) '\0'; - } - return BSTR_OK; -} - -/* int bdestroy (bstring b) - * - * Free up the bstring. Note that if b is detectably invalid or not writable - * then no action is performed and BSTR_ERR is returned. Like a freed memory - * allocation, dereferences, writes or any other action on b after it has - * been bdestroyed is undefined. - */ -int bdestroy (bstring b) { - if (b == NULL || b->slen < 0 || b->mlen <= 0 || b->mlen < b->slen || - b->data == NULL) - return BSTR_ERR; - - bstr__free (b->data); - - /* In case there is any stale usage, there is one more chance to - notice this error. */ - - b->slen = -1; - b->mlen = -__LINE__; - b->data = NULL; - - bstr__free (b); - return BSTR_OK; -} - -/* int binstr (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * forward. If it is found then return with the first position where it is - * found, otherwise return BSTR_ERR. Note that this is just a brute force - * string searcher that does not attempt clever things like the Boyer-Moore - * search algorithm. Because of this there are many degenerate cases where - * this can take much longer than it needs to. - */ -int binstr (const_bstring b1, int pos, const_bstring b2) { -int j, ii, ll, lf; -unsigned char * d0; -unsigned char c0; -register unsigned char * d1; -register unsigned char c1; -register int i; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - /* No space to find such a string? */ - if ((lf = b1->slen - b2->slen + 1) <= pos) return BSTR_ERR; - - /* An obvious alias case */ - if (b1->data == b2->data && pos == 0) return 0; - - i = pos; - - d0 = b2->data; - d1 = b1->data; - ll = b2->slen; - - /* Peel off the b2->slen == 1 case */ - c0 = d0[0]; - if (1 == ll) { - for (;i < lf; i++) if (c0 == d1[i]) return i; - return BSTR_ERR; - } - - c1 = c0; - j = 0; - lf = b1->slen - 1; - - ii = -1; - if (i < lf) do { - /* Unrolled current character test */ - if (c1 != d1[i]) { - if (c1 != d1[1+i]) { - i += 2; - continue; - } - i++; - } - - /* Take note if this is the start of a potential match */ - if (0 == j) ii = i; - - /* Shift the test character down by one */ - j++; - i++; - - /* If this isn't past the last character continue */ - if (j < ll) { - c1 = d0[j]; - continue; - } - - N0:; - - /* If no characters mismatched, then we matched */ - if (i == ii+j) return ii; - - /* Shift back to the beginning */ - i -= j; - j = 0; - c1 = c0; - } while (i < lf); - - /* Deal with last case if unrolling caused a misalignment */ - if (i == lf && ll == j+1 && c1 == d1[i]) goto N0; - - return BSTR_ERR; -} - -/* int binstrr (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * backward. If it is found then return with the first position where it is - * found, otherwise return BSTR_ERR. Note that this is just a brute force - * string searcher that does not attempt clever things like the Boyer-Moore - * search algorithm. Because of this there are many degenerate cases where - * this can take much longer than it needs to. - */ -int binstrr (const_bstring b1, int pos, const_bstring b2) { -int j, i, l; -unsigned char * d0, * d1; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos && b2->slen == 0) return pos; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - /* Obvious alias case */ - if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return 0; - - i = pos; - if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; - - /* If no space to find such a string then snap back */ - if (l + 1 <= i) i = l; - j = 0; - - d0 = b2->data; - d1 = b1->data; - l = b2->slen; - - for (;;) { - if (d0[j] == d1[i + j]) { - j ++; - if (j >= l) return i; - } else { - i --; - if (i < 0) break; - j=0; - } - } - - return BSTR_ERR; -} - -/* int binstrcaseless (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * forward but without regard to case. If it is found then return with the - * first position where it is found, otherwise return BSTR_ERR. Note that - * this is just a brute force string searcher that does not attempt clever - * things like the Boyer-Moore search algorithm. Because of this there are - * many degenerate cases where this can take much longer than it needs to. - */ -int binstrcaseless (const_bstring b1, int pos, const_bstring b2) { -int j, i, l, ll; -unsigned char * d0, * d1; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - l = b1->slen - b2->slen + 1; - - /* No space to find such a string? */ - if (l <= pos) return BSTR_ERR; - - /* An obvious alias case */ - if (b1->data == b2->data && pos == 0) return BSTR_OK; - - i = pos; - j = 0; - - d0 = b2->data; - d1 = b1->data; - ll = b2->slen; - - for (;;) { - if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { - j ++; - if (j >= ll) return i; - } else { - i ++; - if (i >= l) break; - j=0; - } - } - - return BSTR_ERR; -} - -/* int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * backward but without regard to case. If it is found then return with the - * first position where it is found, otherwise return BSTR_ERR. Note that - * this is just a brute force string searcher that does not attempt clever - * things like the Boyer-Moore search algorithm. Because of this there are - * many degenerate cases where this can take much longer than it needs to. - */ -int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) { -int j, i, l; -unsigned char * d0, * d1; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos && b2->slen == 0) return pos; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - /* Obvious alias case */ - if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return BSTR_OK; - - i = pos; - if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; - - /* If no space to find such a string then snap back */ - if (l + 1 <= i) i = l; - j = 0; - - d0 = b2->data; - d1 = b1->data; - l = b2->slen; - - for (;;) { - if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { - j ++; - if (j >= l) return i; - } else { - i --; - if (i < 0) break; - j=0; - } - } - - return BSTR_ERR; -} - - -/* int bstrchrp (const_bstring b, int c, int pos) - * - * Search for the character c in b forwards from the position pos - * (inclusive). - */ -int bstrchrp (const_bstring b, int c, int pos) { -unsigned char * p; - - if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; - p = (unsigned char *) bstr__memchr ((b->data + pos), (unsigned char) c, (b->slen - pos)); - if (p) return (int) (p - b->data); - return BSTR_ERR; -} - -/* int bstrrchrp (const_bstring b, int c, int pos) - * - * Search for the character c in b backwards from the position pos in string - * (inclusive). - */ -int bstrrchrp (const_bstring b, int c, int pos) { -int i; - - if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; - for (i=pos; i >= 0; i--) { - if (b->data[i] == (unsigned char) c) return i; - } - return BSTR_ERR; -} - -#if !defined (BSTRLIB_AGGRESSIVE_MEMORY_FOR_SPEED_TRADEOFF) -#define LONG_LOG_BITS_QTY (3) -#define LONG_BITS_QTY (1 << LONG_LOG_BITS_QTY) -#define LONG_TYPE unsigned char - -#define CFCLEN ((1 << CHAR_BIT) / LONG_BITS_QTY) -struct charField { LONG_TYPE content[CFCLEN]; }; -#define testInCharField(cf,c) ((cf)->content[(c) >> LONG_LOG_BITS_QTY] & (((long)1) << ((c) & (LONG_BITS_QTY-1)))) -#define setInCharField(cf,idx) { \ - unsigned int c = (unsigned int) (idx); \ - (cf)->content[c >> LONG_LOG_BITS_QTY] |= (LONG_TYPE) (1ul << (c & (LONG_BITS_QTY-1))); \ -} - -#else - -#define CFCLEN (1 << CHAR_BIT) -struct charField { unsigned char content[CFCLEN]; }; -#define testInCharField(cf,c) ((cf)->content[(unsigned char) (c)]) -#define setInCharField(cf,idx) (cf)->content[(unsigned int) (idx)] = ~0 - -#endif - -/* Convert a bstring to charField */ -static int buildCharField (struct charField * cf, const_bstring b) { -int i; - if (b == NULL || b->data == NULL || b->slen <= 0) return BSTR_ERR; - memset ((void *) cf->content, 0, sizeof (struct charField)); - for (i=0; i < b->slen; i++) { - setInCharField (cf, b->data[i]); - } - return BSTR_OK; -} - -static void invertCharField (struct charField * cf) { -int i; - for (i=0; i < CFCLEN; i++) cf->content[i] = ~cf->content[i]; -} - -/* Inner engine for binchr */ -static int binchrCF (const unsigned char * data, int len, int pos, const struct charField * cf) { -int i; - for (i=pos; i < len; i++) { - unsigned char c = (unsigned char) data[i]; - if (testInCharField (cf, c)) return i; - } - return BSTR_ERR; -} - -/* int binchr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the first position in b0 starting from pos or after, in which - * one of the characters in b1 is found and return it. If such a position - * does not exist in b0, then BSTR_ERR is returned. - */ -int binchr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || - b0->slen <= pos) return BSTR_ERR; - if (1 == b1->slen) return bstrchrp (b0, b1->data[0], pos); - if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; - return binchrCF (b0->data, b0->slen, pos, &chrs); -} - -/* Inner engine for binchrr */ -static int binchrrCF (const unsigned char * data, int pos, const struct charField * cf) { -int i; - for (i=pos; i >= 0; i--) { - unsigned int c = (unsigned int) data[i]; - if (testInCharField (cf, c)) return i; - } - return BSTR_ERR; -} - -/* int binchrr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the last position in b0 no greater than pos, in which one of - * the characters in b1 is found and return it. If such a position does not - * exist in b0, then BSTR_ERR is returned. - */ -int binchrr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || b1 == NULL || - b0->slen < pos) return BSTR_ERR; - if (pos == b0->slen) pos--; - if (1 == b1->slen) return bstrrchrp (b0, b1->data[0], pos); - if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; - return binchrrCF (b0->data, pos, &chrs); -} - -/* int bninchr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the first position in b0 starting from pos or after, in which - * none of the characters in b1 is found and return it. If such a position - * does not exist in b0, then BSTR_ERR is returned. - */ -int bninchr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || - b0->slen <= pos) return BSTR_ERR; - if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; - invertCharField (&chrs); - return binchrCF (b0->data, b0->slen, pos, &chrs); -} - -/* int bninchrr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the last position in b0 no greater than pos, in which none of - * the characters in b1 is found and return it. If such a position does not - * exist in b0, then BSTR_ERR is returned. - */ -int bninchrr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || - b0->slen < pos) return BSTR_ERR; - if (pos == b0->slen) pos--; - if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; - invertCharField (&chrs); - return binchrrCF (b0->data, pos, &chrs); -} - -/* int bsetstr (bstring b0, int pos, bstring b1, unsigned char fill) - * - * Overwrite the string b0 starting at position pos with the string b1. If - * the position pos is past the end of b0, then the character "fill" is - * appended as necessary to make up the gap between the end of b0 and pos. - * If b1 is NULL, it behaves as if it were a 0-length string. - */ -int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill) { -int d, newlen; -ptrdiff_t pd; -bstring aux = (bstring) b1; - - if (pos < 0 || b0 == NULL || b0->slen < 0 || NULL == b0->data || - b0->mlen < b0->slen || b0->mlen <= 0) return BSTR_ERR; - if (b1 != NULL && (b1->slen < 0 || b1->data == NULL)) return BSTR_ERR; - - d = pos; - - /* Aliasing case */ - if (NULL != aux) { - if ((pd = (ptrdiff_t) (b1->data - b0->data)) >= 0 && pd < (ptrdiff_t) b0->mlen) { - if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; - } - d += aux->slen; - } - - /* Increase memory size if necessary */ - if (balloc (b0, d + 1) != BSTR_OK) { - if (aux != b1) bdestroy (aux); - return BSTR_ERR; - } - - newlen = b0->slen; - - /* Fill in "fill" character as necessary */ - if (pos > newlen) { - bstr__memset (b0->data + b0->slen, (int) fill, (size_t) (pos - b0->slen)); - newlen = pos; - } - - /* Copy b1 to position pos in b0. */ - if (aux != NULL) { - bBlockCopy ((char *) (b0->data + pos), (char *) aux->data, aux->slen); - if (aux != b1) bdestroy (aux); - } - - /* Indicate the potentially increased size of b0 */ - if (d > newlen) newlen = d; - - b0->slen = newlen; - b0->data[newlen] = (unsigned char) '\0'; - - return BSTR_OK; -} - -/* int binsert (bstring b1, int pos, bstring b2, unsigned char fill) - * - * Inserts the string b2 into b1 at position pos. If the position pos is - * past the end of b1, then the character "fill" is appended as necessary to - * make up the gap between the end of b1 and pos. Unlike bsetstr, binsert - * does not allow b2 to be NULL. - */ -int binsert (bstring b1, int pos, const_bstring b2, unsigned char fill) { -int d, l; -ptrdiff_t pd; -bstring aux = (bstring) b2; - - if (pos < 0 || b1 == NULL || b2 == NULL || b1->slen < 0 || - b2->slen < 0 || b1->mlen < b1->slen || b1->mlen <= 0) return BSTR_ERR; - - /* Aliasing case */ - if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->mlen) { - if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; - } - - /* Compute the two possible end pointers */ - d = b1->slen + aux->slen; - l = pos + aux->slen; - if ((d|l) < 0) return BSTR_ERR; - - if (l > d) { - /* Inserting past the end of the string */ - if (balloc (b1, l + 1) != BSTR_OK) { - if (aux != b2) bdestroy (aux); - return BSTR_ERR; - } - bstr__memset (b1->data + b1->slen, (int) fill, (size_t) (pos - b1->slen)); - b1->slen = l; - } else { - /* Inserting in the middle of the string */ - if (balloc (b1, d + 1) != BSTR_OK) { - if (aux != b2) bdestroy (aux); - return BSTR_ERR; - } - bBlockCopy (b1->data + l, b1->data + pos, d - l); - b1->slen = d; - } - bBlockCopy (b1->data + pos, aux->data, aux->slen); - b1->data[b1->slen] = (unsigned char) '\0'; - if (aux != b2) bdestroy (aux); - return BSTR_OK; -} - -/* int breplace (bstring b1, int pos, int len, bstring b2, - * unsigned char fill) - * - * Replace a section of a string from pos for a length len with the string b2. - * fill is used is pos > b1->slen. - */ -int breplace (bstring b1, int pos, int len, const_bstring b2, - unsigned char fill) { -int pl, ret; -ptrdiff_t pd; -bstring aux = (bstring) b2; - - if (pos < 0 || len < 0 || (pl = pos + len) < 0 || b1 == NULL || - b2 == NULL || b1->data == NULL || b2->data == NULL || - b1->slen < 0 || b2->slen < 0 || b1->mlen < b1->slen || - b1->mlen <= 0) return BSTR_ERR; - - /* Straddles the end? */ - if (pl >= b1->slen) { - if ((ret = bsetstr (b1, pos, b2, fill)) < 0) return ret; - if (pos + b2->slen < b1->slen) { - b1->slen = pos + b2->slen; - b1->data[b1->slen] = (unsigned char) '\0'; - } - return ret; - } - - /* Aliasing case */ - if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->slen) { - if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; - } - - if (aux->slen > len) { - if (balloc (b1, b1->slen + aux->slen - len) != BSTR_OK) { - if (aux != b2) bdestroy (aux); - return BSTR_ERR; - } - } - - if (aux->slen != len) bstr__memmove (b1->data + pos + aux->slen, b1->data + pos + len, b1->slen - (pos + len)); - bstr__memcpy (b1->data + pos, aux->data, aux->slen); - b1->slen += aux->slen - len; - b1->data[b1->slen] = (unsigned char) '\0'; - if (aux != b2) bdestroy (aux); - return BSTR_OK; -} - -/* - * findreplaceengine is used to implement bfindreplace and - * bfindreplacecaseless. It works by breaking the three cases of - * expansion, reduction and replacement, and solving each of these - * in the most efficient way possible. - */ - -typedef int (*instr_fnptr) (const_bstring s1, int pos, const_bstring s2); - -#define INITIAL_STATIC_FIND_INDEX_COUNT 32 - -static int findreplaceengine (bstring b, const_bstring find, const_bstring repl, int pos, instr_fnptr instr) { -int i, ret, slen, mlen, delta, acc; -int * d; -int static_d[INITIAL_STATIC_FIND_INDEX_COUNT+1]; /* This +1 is unnecessary, but it shuts up LINT. */ -ptrdiff_t pd; -bstring auxf = (bstring) find; -bstring auxr = (bstring) repl; - - if (b == NULL || b->data == NULL || find == NULL || - find->data == NULL || repl == NULL || repl->data == NULL || - pos < 0 || find->slen <= 0 || b->mlen < 0 || b->slen > b->mlen || - b->mlen <= 0 || b->slen < 0 || repl->slen < 0) return BSTR_ERR; - if (pos > b->slen - find->slen) return BSTR_OK; - - /* Alias with find string */ - pd = (ptrdiff_t) (find->data - b->data); - if ((ptrdiff_t) (pos - find->slen) < pd && pd < (ptrdiff_t) b->slen) { - if (NULL == (auxf = bstrcpy (find))) return BSTR_ERR; - } - - /* Alias with repl string */ - pd = (ptrdiff_t) (repl->data - b->data); - if ((ptrdiff_t) (pos - repl->slen) < pd && pd < (ptrdiff_t) b->slen) { - if (NULL == (auxr = bstrcpy (repl))) { - if (auxf != find) bdestroy (auxf); - return BSTR_ERR; - } - } - - delta = auxf->slen - auxr->slen; - - /* in-place replacement since find and replace strings are of equal - length */ - if (delta == 0) { - while ((pos = instr (b, pos, auxf)) >= 0) { - bstr__memcpy (b->data + pos, auxr->data, auxr->slen); - pos += auxf->slen; - } - if (auxf != find) bdestroy (auxf); - if (auxr != repl) bdestroy (auxr); - return BSTR_OK; - } - - /* shrinking replacement since auxf->slen > auxr->slen */ - if (delta > 0) { - acc = 0; - - while ((i = instr (b, pos, auxf)) >= 0) { - if (acc && i > pos) - bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); - if (auxr->slen) - bstr__memcpy (b->data + i - acc, auxr->data, auxr->slen); - acc += delta; - pos = i + auxf->slen; - } - - if (acc) { - i = b->slen; - if (i > pos) - bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); - b->slen -= acc; - b->data[b->slen] = (unsigned char) '\0'; - } - - if (auxf != find) bdestroy (auxf); - if (auxr != repl) bdestroy (auxr); - return BSTR_OK; - } - - /* expanding replacement since find->slen < repl->slen. Its a lot - more complicated. This works by first finding all the matches and - storing them to a growable array, then doing at most one resize of - the destination bstring and then performing the direct memory transfers - of the string segment pieces to form the final result. The growable - array of matches uses a deferred doubling reallocing strategy. What - this means is that it starts as a reasonably fixed sized auto array in - the hopes that many if not most cases will never need to grow this - array. But it switches as soon as the bounds of the array will be - exceeded. An extra find result is always appended to this array that - corresponds to the end of the destination string, so slen is checked - against mlen - 1 rather than mlen before resizing. - */ - - mlen = INITIAL_STATIC_FIND_INDEX_COUNT; - d = (int *) static_d; /* Avoid malloc for trivial/initial cases */ - acc = slen = 0; - - while ((pos = instr (b, pos, auxf)) >= 0) { - if (slen >= mlen - 1) { - int sl, *t; - - mlen += mlen; - sl = sizeof (int *) * mlen; - if (static_d == d) d = NULL; /* static_d cannot be realloced */ - if (mlen <= 0 || sl < mlen || NULL == (t = (int *) bstr__realloc (d, sl))) { - ret = BSTR_ERR; - goto done; - } - if (NULL == d) bstr__memcpy (t, static_d, sizeof (static_d)); - d = t; - } - d[slen] = pos; - slen++; - acc -= delta; - pos += auxf->slen; - if (pos < 0 || acc < 0) { - ret = BSTR_ERR; - goto done; - } - } - - /* slen <= INITIAL_STATIC_INDEX_COUNT-1 or mlen-1 here. */ - d[slen] = b->slen; - - if (BSTR_OK == (ret = balloc (b, b->slen + acc + 1))) { - b->slen += acc; - for (i = slen-1; i >= 0; i--) { - int s, l; - s = d[i] + auxf->slen; - l = d[i+1] - s; /* d[slen] may be accessed here. */ - if (l) { - bstr__memmove (b->data + s + acc, b->data + s, l); - } - if (auxr->slen) { - bstr__memmove (b->data + s + acc - auxr->slen, - auxr->data, auxr->slen); - } - acc += delta; - } - b->data[b->slen] = (unsigned char) '\0'; - } - - done:; - if (static_d == d) d = NULL; - bstr__free (d); - if (auxf != find) bdestroy (auxf); - if (auxr != repl) bdestroy (auxr); - return ret; -} - -/* int bfindreplace (bstring b, const_bstring find, const_bstring repl, - * int pos) - * - * Replace all occurrences of a find string with a replace string after a - * given point in a bstring. - */ -int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos) { - return findreplaceengine (b, find, repl, pos, binstr); -} - -/* int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, - * int pos) - * - * Replace all occurrences of a find string, ignoring case, with a replace - * string after a given point in a bstring. - */ -int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos) { - return findreplaceengine (b, find, repl, pos, binstrcaseless); -} - -/* int binsertch (bstring b, int pos, int len, unsigned char fill) - * - * Inserts the character fill repeatedly into b at position pos for a - * length len. If the position pos is past the end of b, then the - * character "fill" is appended as necessary to make up the gap between the - * end of b and the position pos + len. - */ -int binsertch (bstring b, int pos, int len, unsigned char fill) { -int d, l, i; - - if (pos < 0 || b == NULL || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || len < 0) return BSTR_ERR; - - /* Compute the two possible end pointers */ - d = b->slen + len; - l = pos + len; - if ((d|l) < 0) return BSTR_ERR; - - if (l > d) { - /* Inserting past the end of the string */ - if (balloc (b, l + 1) != BSTR_OK) return BSTR_ERR; - pos = b->slen; - b->slen = l; - } else { - /* Inserting in the middle of the string */ - if (balloc (b, d + 1) != BSTR_OK) return BSTR_ERR; - for (i = d - 1; i >= l; i--) { - b->data[i] = b->data[i - len]; - } - b->slen = d; - } - - for (i=pos; i < l; i++) b->data[i] = fill; - b->data[b->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bpattern (bstring b, int len) - * - * Replicate the bstring, b in place, end to end repeatedly until it - * surpasses len characters, then chop the result to exactly len characters. - * This function operates in-place. The function will return with BSTR_ERR - * if b is NULL or of length 0, otherwise BSTR_OK is returned. - */ -int bpattern (bstring b, int len) { -int i, d; - - d = blength (b); - if (d <= 0 || len < 0 || balloc (b, len + 1) != BSTR_OK) return BSTR_ERR; - if (len > 0) { - if (d == 1) return bsetstr (b, len, NULL, b->data[0]); - for (i = d; i < len; i++) b->data[i] = b->data[i - d]; - } - b->data[len] = (unsigned char) '\0'; - b->slen = len; - return BSTR_OK; -} - -#define BS_BUFF_SZ (1024) - -/* int breada (bstring b, bNread readPtr, void * parm) - * - * Use a finite buffer fread-like function readPtr to concatenate to the - * bstring b the entire contents of file-like source data in a roughly - * efficient way. - */ -int breada (bstring b, bNread readPtr, void * parm) { -int i, l, n; - - if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || readPtr == NULL) return BSTR_ERR; - - i = b->slen; - for (n=i+16; ; n += ((n < BS_BUFF_SZ) ? n : BS_BUFF_SZ)) { - if (BSTR_OK != balloc (b, n + 1)) return BSTR_ERR; - l = (int) readPtr ((void *) (b->data + i), 1, n - i, parm); - i += l; - b->slen = i; - if (i < n) break; - } - - b->data[i] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* bstring bread (bNread readPtr, void * parm) - * - * Use a finite buffer fread-like function readPtr to create a bstring - * filled with the entire contents of file-like source data in a roughly - * efficient way. - */ -bstring bread (bNread readPtr, void * parm) { -bstring buff; - - if (0 > breada (buff = bfromcstr (""), readPtr, parm)) { - bdestroy (buff); - return NULL; - } - return buff; -} - -/* int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) - * - * Use an fgetc-like single character stream reading function (getcPtr) to - * obtain a sequence of characters which are concatenated to the end of the - * bstring b. The stream read is terminated by the passed in terminator - * parameter. - * - * If getcPtr returns with a negative number, or the terminator character - * (which is appended) is read, then the stream reading is halted and the - * function returns with a partial result in b. If there is an empty partial - * result, 1 is returned. If no characters are read, or there is some other - * detectable error, BSTR_ERR is returned. - */ -int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) { -int c, d, e; - - if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; - d = 0; - e = b->mlen - 2; - - while ((c = getcPtr (parm)) >= 0) { - if (d > e) { - b->slen = d; - if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; - e = b->mlen - 2; - } - b->data[d] = (unsigned char) c; - d++; - if (c == terminator) break; - } - - b->data[d] = (unsigned char) '\0'; - b->slen = d; - - return d == 0 && c < 0; -} - -/* int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) - * - * Use an fgetc-like single character stream reading function (getcPtr) to - * obtain a sequence of characters which are concatenated to the end of the - * bstring b. The stream read is terminated by the passed in terminator - * parameter. - * - * If getcPtr returns with a negative number, or the terminator character - * (which is appended) is read, then the stream reading is halted and the - * function returns with a partial result concatentated to b. If there is - * an empty partial result, 1 is returned. If no characters are read, or - * there is some other detectable error, BSTR_ERR is returned. - */ -int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) { -int c, d, e; - - if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; - d = b->slen; - e = b->mlen - 2; - - while ((c = getcPtr (parm)) >= 0) { - if (d > e) { - b->slen = d; - if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; - e = b->mlen - 2; - } - b->data[d] = (unsigned char) c; - d++; - if (c == terminator) break; - } - - b->data[d] = (unsigned char) '\0'; - b->slen = d; - - return d == 0 && c < 0; -} - -/* bstring bgets (bNgetc getcPtr, void * parm, char terminator) - * - * Use an fgetc-like single character stream reading function (getcPtr) to - * obtain a sequence of characters which are concatenated into a bstring. - * The stream read is terminated by the passed in terminator function. - * - * If getcPtr returns with a negative number, or the terminator character - * (which is appended) is read, then the stream reading is halted and the - * result obtained thus far is returned. If no characters are read, or - * there is some other detectable error, NULL is returned. - */ -bstring bgets (bNgetc getcPtr, void * parm, char terminator) { -bstring buff; - - if (0 > bgetsa (buff = bfromcstr (""), getcPtr, parm, terminator) || 0 >= buff->slen) { - bdestroy (buff); - buff = NULL; - } - return buff; -} - -struct bStream { - bstring buff; /* Buffer for over-reads */ - void * parm; /* The stream handle for core stream */ - bNread readFnPtr; /* fread compatible fnptr for core stream */ - int isEOF; /* track file's EOF state */ - int maxBuffSz; -}; - -/* struct bStream * bsopen (bNread readPtr, void * parm) - * - * Wrap a given open stream (described by a fread compatible function - * pointer and stream handle) into an open bStream suitable for the bstring - * library streaming functions. - */ -struct bStream * bsopen (bNread readPtr, void * parm) { -struct bStream * s; - - if (readPtr == NULL) return NULL; - s = (struct bStream *) bstr__alloc (sizeof (struct bStream)); - if (s == NULL) return NULL; - s->parm = parm; - s->buff = bfromcstr (""); - s->readFnPtr = readPtr; - s->maxBuffSz = BS_BUFF_SZ; - s->isEOF = 0; - return s; -} - -/* int bsbufflength (struct bStream * s, int sz) - * - * Set the length of the buffer used by the bStream. If sz is zero, the - * length is not set. This function returns with the previous length. - */ -int bsbufflength (struct bStream * s, int sz) { -int oldSz; - if (s == NULL || sz < 0) return BSTR_ERR; - oldSz = s->maxBuffSz; - if (sz > 0) s->maxBuffSz = sz; - return oldSz; -} - -int bseof (const struct bStream * s) { - if (s == NULL || s->readFnPtr == NULL) return BSTR_ERR; - return s->isEOF && (s->buff->slen == 0); -} - -/* void * bsclose (struct bStream * s) - * - * Close the bStream, and return the handle to the stream that was originally - * used to open the given stream. - */ -void * bsclose (struct bStream * s) { -void * parm; - if (s == NULL) return NULL; - s->readFnPtr = NULL; - if (s->buff) bdestroy (s->buff); - s->buff = NULL; - parm = s->parm; - s->parm = NULL; - s->isEOF = 1; - bstr__free (s); - return parm; -} - -/* int bsreadlna (bstring r, struct bStream * s, char terminator) - * - * Read a bstring terminated by the terminator character or the end of the - * stream from the bStream (s) and return it into the parameter r. This - * function may read additional characters from the core stream that are not - * returned, but will be retained for subsequent read operations. - */ -int bsreadlna (bstring r, struct bStream * s, char terminator) { -int i, l, ret, rlo; -char * b; -struct tagbstring x; - - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 || - r->slen < 0 || r->mlen < r->slen) return BSTR_ERR; - l = s->buff->slen; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - b = (char *) s->buff->data; - x.data = (unsigned char *) b; - - /* First check if the current buffer holds the terminator */ - b[l] = terminator; /* Set sentinel */ - for (i=0; b[i] != terminator; i++) ; - if (i < l) { - x.slen = i + 1; - ret = bconcat (r, &x); - s->buff->slen = l; - if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); - return BSTR_OK; - } - - rlo = r->slen; - - /* If not then just concatenate the entire buffer to the output */ - x.slen = l; - if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; - - /* Perform direct in-place reads into the destination to allow for - the minimum of data-copies */ - for (;;) { - if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; - b = (char *) (r->data + r->slen); - l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); - if (l <= 0) { - r->data[r->slen] = (unsigned char) '\0'; - s->buff->slen = 0; - s->isEOF = 1; - /* If nothing was read return with an error message */ - return BSTR_ERR & -(r->slen == rlo); - } - b[l] = terminator; /* Set sentinel */ - for (i=0; b[i] != terminator; i++) ; - if (i < l) break; - r->slen += l; - } - - /* Terminator found, push over-read back to buffer */ - i++; - r->slen += i; - s->buff->slen = l - i; - bstr__memcpy (s->buff->data, b + i, l - i); - r->data[r->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bsreadlnsa (bstring r, struct bStream * s, bstring term) - * - * Read a bstring terminated by any character in the term string or the end - * of the stream from the bStream (s) and return it into the parameter r. - * This function may read additional characters from the core stream that - * are not returned, but will be retained for subsequent read operations. - */ -int bsreadlnsa (bstring r, struct bStream * s, const_bstring term) { -int i, l, ret, rlo; -unsigned char * b; -struct tagbstring x; -struct charField cf; - - if (s == NULL || s->buff == NULL || r == NULL || term == NULL || - term->data == NULL || r->mlen <= 0 || r->slen < 0 || - r->mlen < r->slen) return BSTR_ERR; - if (term->slen == 1) return bsreadlna (r, s, term->data[0]); - if (term->slen < 1 || buildCharField (&cf, term)) return BSTR_ERR; - - l = s->buff->slen; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - b = (unsigned char *) s->buff->data; - x.data = b; - - /* First check if the current buffer holds the terminator */ - b[l] = term->data[0]; /* Set sentinel */ - for (i=0; !testInCharField (&cf, b[i]); i++) ; - if (i < l) { - x.slen = i + 1; - ret = bconcat (r, &x); - s->buff->slen = l; - if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); - return BSTR_OK; - } - - rlo = r->slen; - - /* If not then just concatenate the entire buffer to the output */ - x.slen = l; - if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; - - /* Perform direct in-place reads into the destination to allow for - the minimum of data-copies */ - for (;;) { - if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; - b = (unsigned char *) (r->data + r->slen); - l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); - if (l <= 0) { - r->data[r->slen] = (unsigned char) '\0'; - s->buff->slen = 0; - s->isEOF = 1; - /* If nothing was read return with an error message */ - return BSTR_ERR & -(r->slen == rlo); - } - - b[l] = term->data[0]; /* Set sentinel */ - for (i=0; !testInCharField (&cf, b[i]); i++) ; - if (i < l) break; - r->slen += l; - } - - /* Terminator found, push over-read back to buffer */ - i++; - r->slen += i; - s->buff->slen = l - i; - bstr__memcpy (s->buff->data, b + i, l - i); - r->data[r->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bsreada (bstring r, struct bStream * s, int n) - * - * Read a bstring of length n (or, if it is fewer, as many bytes as is - * remaining) from the bStream. This function may read additional - * characters from the core stream that are not returned, but will be - * retained for subsequent read operations. This function will not read - * additional characters from the core stream beyond virtual stream pointer. - */ -int bsreada (bstring r, struct bStream * s, int n) { -int l, ret, orslen; -char * b; -struct tagbstring x; - - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 - || r->slen < 0 || r->mlen < r->slen || n <= 0) return BSTR_ERR; - - n += r->slen; - if (n <= 0) return BSTR_ERR; - - l = s->buff->slen; - - orslen = r->slen; - - if (0 == l) { - if (s->isEOF) return BSTR_ERR; - if (r->mlen > n) { - l = (int) s->readFnPtr (r->data + r->slen, 1, n - r->slen, s->parm); - if (0 >= l || l > n - r->slen) { - s->isEOF = 1; - return BSTR_ERR; - } - r->slen += l; - r->data[r->slen] = (unsigned char) '\0'; - return 0; - } - } - - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - b = (char *) s->buff->data; - x.data = (unsigned char *) b; - - do { - if (l + r->slen >= n) { - x.slen = n - r->slen; - ret = bconcat (r, &x); - s->buff->slen = l; - if (BSTR_OK == ret) bdelete (s->buff, 0, x.slen); - return BSTR_ERR & -(r->slen == orslen); - } - - x.slen = l; - if (BSTR_OK != bconcat (r, &x)) break; - - l = n - r->slen; - if (l > s->maxBuffSz) l = s->maxBuffSz; - - l = (int) s->readFnPtr (b, 1, l, s->parm); - - } while (l > 0); - if (l < 0) l = 0; - if (l == 0) s->isEOF = 1; - s->buff->slen = l; - return BSTR_ERR & -(r->slen == orslen); -} - -/* int bsreadln (bstring r, struct bStream * s, char terminator) - * - * Read a bstring terminated by the terminator character or the end of the - * stream from the bStream (s) and return it into the parameter r. This - * function may read additional characters from the core stream that are not - * returned, but will be retained for subsequent read operations. - */ -int bsreadln (bstring r, struct bStream * s, char terminator) { - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0) - return BSTR_ERR; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - r->slen = 0; - return bsreadlna (r, s, terminator); -} - -/* int bsreadlns (bstring r, struct bStream * s, bstring term) - * - * Read a bstring terminated by any character in the term string or the end - * of the stream from the bStream (s) and return it into the parameter r. - * This function may read additional characters from the core stream that - * are not returned, but will be retained for subsequent read operations. - */ -int bsreadlns (bstring r, struct bStream * s, const_bstring term) { - if (s == NULL || s->buff == NULL || r == NULL || term == NULL - || term->data == NULL || r->mlen <= 0) return BSTR_ERR; - if (term->slen == 1) return bsreadln (r, s, term->data[0]); - if (term->slen < 1) return BSTR_ERR; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - r->slen = 0; - return bsreadlnsa (r, s, term); -} - -/* int bsread (bstring r, struct bStream * s, int n) - * - * Read a bstring of length n (or, if it is fewer, as many bytes as is - * remaining) from the bStream. This function may read additional - * characters from the core stream that are not returned, but will be - * retained for subsequent read operations. This function will not read - * additional characters from the core stream beyond virtual stream pointer. - */ -int bsread (bstring r, struct bStream * s, int n) { - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 - || n <= 0) return BSTR_ERR; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - r->slen = 0; - return bsreada (r, s, n); -} - -/* int bsunread (struct bStream * s, const_bstring b) - * - * Insert a bstring into the bStream at the current position. These - * characters will be read prior to those that actually come from the core - * stream. - */ -int bsunread (struct bStream * s, const_bstring b) { - if (s == NULL || s->buff == NULL) return BSTR_ERR; - return binsert (s->buff, 0, b, (unsigned char) '?'); -} - -/* int bspeek (bstring r, const struct bStream * s) - * - * Return the currently buffered characters from the bStream that will be - * read prior to reads from the core stream. - */ -int bspeek (bstring r, const struct bStream * s) { - if (s == NULL || s->buff == NULL) return BSTR_ERR; - return bassign (r, s->buff); -} - -/* bstring bjoin (const struct bstrList * bl, const_bstring sep); - * - * Join the entries of a bstrList into one bstring by sequentially - * concatenating them with the sep string in between. If there is an error - * NULL is returned, otherwise a bstring with the correct result is returned. - */ -bstring bjoin (const struct bstrList * bl, const_bstring sep) { -bstring b; -int i, c, v; - - if (bl == NULL || bl->qty < 0) return NULL; - if (sep != NULL && (sep->slen < 0 || sep->data == NULL)) return NULL; - - for (i = 0, c = 1; i < bl->qty; i++) { - v = bl->entry[i]->slen; - if (v < 0) return NULL; /* Invalid input */ - c += v; - if (c < 0) return NULL; /* Wrap around ?? */ - } - - if (sep != NULL) c += (bl->qty - 1) * sep->slen; - - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (NULL == b) return NULL; /* Out of memory */ - b->data = (unsigned char *) bstr__alloc (c); - if (b->data == NULL) { - bstr__free (b); - return NULL; - } - - b->mlen = c; - b->slen = c-1; - - for (i = 0, c = 0; i < bl->qty; i++) { - if (i > 0 && sep != NULL) { - bstr__memcpy (b->data + c, sep->data, sep->slen); - c += sep->slen; - } - v = bl->entry[i]->slen; - bstr__memcpy (b->data + c, bl->entry[i]->data, v); - c += v; - } - b->data[c] = (unsigned char) '\0'; - return b; -} - -#define BSSSC_BUFF_LEN (256) - -/* int bssplitscb (struct bStream * s, const_bstring splitStr, - * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) - * - * Iterate the set of disjoint sequential substrings read from a stream - * divided by any of the characters in splitStr. An empty splitStr causes - * the whole stream to be iterated once. - * - * Note: At the point of calling the cb function, the bStream pointer is - * pointed exactly at the position right after having read the split - * character. The cb function can act on the stream by causing the bStream - * pointer to move, and bssplitscb will continue by starting the next split - * at the position of the pointer after the return from cb. - * - * However, if the cb causes the bStream s to be destroyed then the cb must - * return with a negative value, otherwise bssplitscb will continue in an - * undefined manner. - */ -int bssplitscb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { -struct charField chrs; -bstring buff; -int i, p, ret; - - if (cb == NULL || s == NULL || s->readFnPtr == NULL - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - - if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; - - if (splitStr->slen == 0) { - while (bsreada (buff, s, BSSSC_BUFF_LEN) >= 0) ; - if ((ret = cb (parm, 0, buff)) > 0) - ret = 0; - } else { - buildCharField (&chrs, splitStr); - ret = p = i = 0; - for (;;) { - if (i >= buff->slen) { - bsreada (buff, s, BSSSC_BUFF_LEN); - if (i >= buff->slen) { - if (0 < (ret = cb (parm, p, buff))) ret = 0; - break; - } - } - if (testInCharField (&chrs, buff->data[i])) { - struct tagbstring t; - unsigned char c; - - blk2tbstr (t, buff->data + i + 1, buff->slen - (i + 1)); - if ((ret = bsunread (s, &t)) < 0) break; - buff->slen = i; - c = buff->data[i]; - buff->data[i] = (unsigned char) '\0'; - if ((ret = cb (parm, p, buff)) < 0) break; - buff->data[i] = c; - buff->slen = 0; - p += i + 1; - i = -1; - } - i++; - } - } - - bdestroy (buff); - return ret; -} - -/* int bssplitstrcb (struct bStream * s, const_bstring splitStr, - * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) - * - * Iterate the set of disjoint sequential substrings read from a stream - * divided by the entire substring splitStr. An empty splitStr causes - * each character of the stream to be iterated. - * - * Note: At the point of calling the cb function, the bStream pointer is - * pointed exactly at the position right after having read the split - * character. The cb function can act on the stream by causing the bStream - * pointer to move, and bssplitscb will continue by starting the next split - * at the position of the pointer after the return from cb. - * - * However, if the cb causes the bStream s to be destroyed then the cb must - * return with a negative value, otherwise bssplitscb will continue in an - * undefined manner. - */ -int bssplitstrcb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { -bstring buff; -int i, p, ret; - - if (cb == NULL || s == NULL || s->readFnPtr == NULL - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - - if (splitStr->slen == 1) return bssplitscb (s, splitStr, cb, parm); - - if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; - - if (splitStr->slen == 0) { - for (i=0; bsreada (buff, s, BSSSC_BUFF_LEN) >= 0; i++) { - if ((ret = cb (parm, 0, buff)) < 0) { - bdestroy (buff); - return ret; - } - buff->slen = 0; - } - return BSTR_OK; - } else { - ret = p = i = 0; - for (i=p=0;;) { - if ((ret = binstr (buff, 0, splitStr)) >= 0) { - struct tagbstring t; - blk2tbstr (t, buff->data, ret); - i = ret + splitStr->slen; - if ((ret = cb (parm, p, &t)) < 0) break; - p += i; - bdelete (buff, 0, i); - } else { - bsreada (buff, s, BSSSC_BUFF_LEN); - if (bseof (s)) { - if ((ret = cb (parm, p, buff)) > 0) ret = 0; - break; - } - } - } - } - - bdestroy (buff); - return ret; -} - -/* int bstrListCreate (void) - * - * Create a bstrList. - */ -struct bstrList * bstrListCreate (void) { -struct bstrList * sl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (sl) { - sl->entry = (bstring *) bstr__alloc (1*sizeof (bstring)); - if (!sl->entry) { - bstr__free (sl); - sl = NULL; - } else { - sl->qty = 0; - sl->mlen = 1; - } - } - return sl; -} - -/* int bstrListDestroy (struct bstrList * sl) - * - * Destroy a bstrList that has been created by bsplit, bsplits or bstrListCreate. - */ -int bstrListDestroy (struct bstrList * sl) { -int i; - if (sl == NULL || sl->qty < 0) return BSTR_ERR; - for (i=0; i < sl->qty; i++) { - if (sl->entry[i]) { - bdestroy (sl->entry[i]); - sl->entry[i] = NULL; - } - } - sl->qty = -1; - sl->mlen = -1; - bstr__free (sl->entry); - sl->entry = NULL; - bstr__free (sl); - return BSTR_OK; -} - -/* int bstrListAlloc (struct bstrList * sl, int msz) - * - * Ensure that there is memory for at least msz number of entries for the - * list. - */ -int bstrListAlloc (struct bstrList * sl, int msz) { -bstring * l; -int smsz; -size_t nsz; - if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; - if (sl->mlen >= msz) return BSTR_OK; - smsz = snapUpSize (msz); - nsz = ((size_t) smsz) * sizeof (bstring); - if (nsz < (size_t) smsz) return BSTR_ERR; - l = (bstring *) bstr__realloc (sl->entry, nsz); - if (!l) { - smsz = msz; - nsz = ((size_t) smsz) * sizeof (bstring); - l = (bstring *) bstr__realloc (sl->entry, nsz); - if (!l) return BSTR_ERR; - } - sl->mlen = smsz; - sl->entry = l; - return BSTR_OK; -} - -/* int bstrListAllocMin (struct bstrList * sl, int msz) - * - * Try to allocate the minimum amount of memory for the list to include at - * least msz entries or sl->qty whichever is greater. - */ -int bstrListAllocMin (struct bstrList * sl, int msz) { -bstring * l; -size_t nsz; - if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; - if (msz < sl->qty) msz = sl->qty; - if (sl->mlen == msz) return BSTR_OK; - nsz = ((size_t) msz) * sizeof (bstring); - if (nsz < (size_t) msz) return BSTR_ERR; - l = (bstring *) bstr__realloc (sl->entry, nsz); - if (!l) return BSTR_ERR; - sl->mlen = msz; - sl->entry = l; - return BSTR_OK; -} - -/* int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - * int (* cb) (void * parm, int ofs, int len), void * parm) - * - * Iterate the set of disjoint sequential substrings over str divided by the - * character in splitChar. - * - * Note: Non-destructive modification of str from within the cb function - * while performing this split is not undefined. bsplitcb behaves in - * sequential lock step with calls to cb. I.e., after returning from a cb - * that return a non-negative integer, bsplitcb continues from the position - * 1 character after the last detected split character and it will halt - * immediately if the length of str falls below this point. However, if the - * cb function destroys str, then it *must* return with a negative value, - * otherwise bsplitcb will continue in an undefined manner. - */ -int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm) { -int i, p, ret; - - if (cb == NULL || str == NULL || pos < 0 || pos > str->slen) - return BSTR_ERR; - - p = pos; - do { - for (i=p; i < str->slen; i++) { - if (str->data[i] == splitChar) break; - } - if ((ret = cb (parm, p, i - p)) < 0) return ret; - p = i + 1; - } while (p <= str->slen); - return BSTR_OK; -} - -/* int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - * int (* cb) (void * parm, int ofs, int len), void * parm) - * - * Iterate the set of disjoint sequential substrings over str divided by any - * of the characters in splitStr. An empty splitStr causes the whole str to - * be iterated once. - * - * Note: Non-destructive modification of str from within the cb function - * while performing this split is not undefined. bsplitscb behaves in - * sequential lock step with calls to cb. I.e., after returning from a cb - * that return a non-negative integer, bsplitscb continues from the position - * 1 character after the last detected split character and it will halt - * immediately if the length of str falls below this point. However, if the - * cb function destroys str, then it *must* return with a negative value, - * otherwise bsplitscb will continue in an undefined manner. - */ -int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm) { -struct charField chrs; -int i, p, ret; - - if (cb == NULL || str == NULL || pos < 0 || pos > str->slen - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - if (splitStr->slen == 0) { - if ((ret = cb (parm, 0, str->slen)) > 0) ret = 0; - return ret; - } - - if (splitStr->slen == 1) - return bsplitcb (str, splitStr->data[0], pos, cb, parm); - - buildCharField (&chrs, splitStr); - - p = pos; - do { - for (i=p; i < str->slen; i++) { - if (testInCharField (&chrs, str->data[i])) break; - } - if ((ret = cb (parm, p, i - p)) < 0) return ret; - p = i + 1; - } while (p <= str->slen); - return BSTR_OK; -} - -/* int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - * int (* cb) (void * parm, int ofs, int len), void * parm) - * - * Iterate the set of disjoint sequential substrings over str divided by the - * substring splitStr. An empty splitStr causes the whole str to be - * iterated once. - * - * Note: Non-destructive modification of str from within the cb function - * while performing this split is not undefined. bsplitstrcb behaves in - * sequential lock step with calls to cb. I.e., after returning from a cb - * that return a non-negative integer, bsplitscb continues from the position - * 1 character after the last detected split character and it will halt - * immediately if the length of str falls below this point. However, if the - * cb function destroys str, then it *must* return with a negative value, - * otherwise bsplitscb will continue in an undefined manner. - */ -int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm) { -int i, p, ret; - - if (cb == NULL || str == NULL || pos < 0 || pos > str->slen - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - - if (0 == splitStr->slen) { - for (i=pos; i < str->slen; i++) { - if ((ret = cb (parm, i, 1)) < 0) return ret; - } - return BSTR_OK; - } - - if (splitStr->slen == 1) - return bsplitcb (str, splitStr->data[0], pos, cb, parm); - - for (i=p=pos; i <= str->slen - splitStr->slen; i++) { - if (0 == bstr__memcmp (splitStr->data, str->data + i, splitStr->slen)) { - if ((ret = cb (parm, p, i - p)) < 0) return ret; - i += splitStr->slen; - p = i; - } - } - if ((ret = cb (parm, p, str->slen - p)) < 0) return ret; - return BSTR_OK; -} - -struct genBstrList { - bstring b; - struct bstrList * bl; -}; - -static int bscb (void * parm, int ofs, int len) { -struct genBstrList * g = (struct genBstrList *) parm; - if (g->bl->qty >= g->bl->mlen) { - int mlen = g->bl->mlen * 2; - bstring * tbl; - - while (g->bl->qty >= mlen) { - if (mlen < g->bl->mlen) return BSTR_ERR; - mlen += mlen; - } - - tbl = (bstring *) bstr__realloc (g->bl->entry, sizeof (bstring) * mlen); - if (tbl == NULL) return BSTR_ERR; - - g->bl->entry = tbl; - g->bl->mlen = mlen; - } - - g->bl->entry[g->bl->qty] = bmidstr (g->b, ofs, len); - g->bl->qty++; - return BSTR_OK; -} - -/* struct bstrList * bsplit (const_bstring str, unsigned char splitChar) - * - * Create an array of sequential substrings from str divided by the character - * splitChar. - */ -struct bstrList * bsplit (const_bstring str, unsigned char splitChar) { -struct genBstrList g; - - if (str == NULL || str->data == NULL || str->slen < 0) return NULL; - - g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (g.bl == NULL) return NULL; - g.bl->mlen = 4; - g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); - if (NULL == g.bl->entry) { - bstr__free (g.bl); - return NULL; - } - - g.b = (bstring) str; - g.bl->qty = 0; - if (bsplitcb (str, splitChar, 0, bscb, &g) < 0) { - bstrListDestroy (g.bl); - return NULL; - } - return g.bl; -} - -/* struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) - * - * Create an array of sequential substrings from str divided by the entire - * substring splitStr. - */ -struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) { -struct genBstrList g; - - if (str == NULL || str->data == NULL || str->slen < 0) return NULL; - - g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (g.bl == NULL) return NULL; - g.bl->mlen = 4; - g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); - if (NULL == g.bl->entry) { - bstr__free (g.bl); - return NULL; - } - - g.b = (bstring) str; - g.bl->qty = 0; - if (bsplitstrcb (str, splitStr, 0, bscb, &g) < 0) { - bstrListDestroy (g.bl); - return NULL; - } - return g.bl; -} - -/* struct bstrList * bsplits (const_bstring str, bstring splitStr) - * - * Create an array of sequential substrings from str divided by any of the - * characters in splitStr. An empty splitStr causes a single entry bstrList - * containing a copy of str to be returned. - */ -struct bstrList * bsplits (const_bstring str, const_bstring splitStr) { -struct genBstrList g; - - if ( str == NULL || str->slen < 0 || str->data == NULL || - splitStr == NULL || splitStr->slen < 0 || splitStr->data == NULL) - return NULL; - - g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (g.bl == NULL) return NULL; - g.bl->mlen = 4; - g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); - if (NULL == g.bl->entry) { - bstr__free (g.bl); - return NULL; - } - g.b = (bstring) str; - g.bl->qty = 0; - - if (bsplitscb (str, splitStr, 0, bscb, &g) < 0) { - bstrListDestroy (g.bl); - return NULL; - } - return g.bl; -} - -#if defined (__TURBOC__) && !defined (__BORLANDC__) -# ifndef BSTRLIB_NOVSNP -# define BSTRLIB_NOVSNP -# endif -#endif - -/* Give WATCOM C/C++, MSVC some latitude for their non-support of vsnprintf */ -#if defined(__WATCOMC__) || defined(_MSC_VER) -#define exvsnprintf(r,b,n,f,a) {r = _vsnprintf (b,n,f,a);} -#else -#ifdef BSTRLIB_NOVSNP -/* This is just a hack. If you are using a system without a vsnprintf, it is - not recommended that bformat be used at all. */ -#define exvsnprintf(r,b,n,f,a) {vsprintf (b,f,a); r = -1;} -#define START_VSNBUFF (256) -#else - -#if defined(__GNUC__) && !defined(__APPLE__) -/* Something is making gcc complain about this prototype not being here, so - I've just gone ahead and put it in. */ -extern int vsnprintf (char *buf, size_t count, const char *format, va_list arg); -#endif - -#define exvsnprintf(r,b,n,f,a) {r = vsnprintf (b,n,f,a);} -#endif -#endif - -#if !defined (BSTRLIB_NOVSNP) - -#ifndef START_VSNBUFF -#define START_VSNBUFF (16) -#endif - -/* On IRIX vsnprintf returns n-1 when the operation would overflow the target - buffer, WATCOM and MSVC both return -1, while C99 requires that the - returned value be exactly what the length would be if the buffer would be - large enough. This leads to the idea that if the return value is larger - than n, then changing n to the return value will reduce the number of - iterations required. */ - -/* int bformata (bstring b, const char * fmt, ...) - * - * After the first parameter, it takes the same parameters as printf (), but - * rather than outputting results to stdio, it appends the results to - * a bstring which contains what would have been output. Note that if there - * is an early generation of a '\0' character, the bstring will be truncated - * to this end point. - */ -int bformata (bstring b, const char * fmt, ...) { -va_list arglist; -bstring buff; -int n, r; - - if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 - || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; - - /* Since the length is not determinable beforehand, a search is - performed using the truncating "vsnprintf" call (to avoid buffer - overflows) on increasing potential sizes for the output result. */ - - if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) { - n = 1; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; - } - - for (;;) { - va_start (arglist, fmt); - exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); - va_end (arglist); - - buff->data[n] = (unsigned char) '\0'; - buff->slen = (int) (strlen) ((char *) buff->data); - - if (buff->slen < n) break; - - if (r > n) n = r; else n += n; - - if (BSTR_OK != balloc (buff, n + 2)) { - bdestroy (buff); - return BSTR_ERR; - } - } - - r = bconcat (b, buff); - bdestroy (buff); - return r; -} - -/* int bassignformat (bstring b, const char * fmt, ...) - * - * After the first parameter, it takes the same parameters as printf (), but - * rather than outputting results to stdio, it outputs the results to - * the bstring parameter b. Note that if there is an early generation of a - * '\0' character, the bstring will be truncated to this end point. - */ -int bassignformat (bstring b, const char * fmt, ...) { -va_list arglist; -bstring buff; -int n, r; - - if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 - || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; - - /* Since the length is not determinable beforehand, a search is - performed using the truncating "vsnprintf" call (to avoid buffer - overflows) on increasing potential sizes for the output result. */ - - if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) { - n = 1; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; - } - - for (;;) { - va_start (arglist, fmt); - exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); - va_end (arglist); - - buff->data[n] = (unsigned char) '\0'; - buff->slen = (int) (strlen) ((char *) buff->data); - - if (buff->slen < n) break; - - if (r > n) n = r; else n += n; - - if (BSTR_OK != balloc (buff, n + 2)) { - bdestroy (buff); - return BSTR_ERR; - } - } - - r = bassign (b, buff); - bdestroy (buff); - return r; -} - -/* bstring bformat (const char * fmt, ...) - * - * Takes the same parameters as printf (), but rather than outputting results - * to stdio, it forms a bstring which contains what would have been output. - * Note that if there is an early generation of a '\0' character, the - * bstring will be truncated to this end point. - */ -bstring bformat (const char * fmt, ...) { -va_list arglist; -bstring buff; -int n, r; - - if (fmt == NULL) return NULL; - - /* Since the length is not determinable beforehand, a search is - performed using the truncating "vsnprintf" call (to avoid buffer - overflows) on increasing potential sizes for the output result. */ - - if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) { - n = 1; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) return NULL; - } - - for (;;) { - va_start (arglist, fmt); - exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); - va_end (arglist); - - buff->data[n] = (unsigned char) '\0'; - buff->slen = (int) (strlen) ((char *) buff->data); - - if (buff->slen < n) break; - - if (r > n) n = r; else n += n; - - if (BSTR_OK != balloc (buff, n + 2)) { - bdestroy (buff); - return NULL; - } - } - - return buff; -} - -/* int bvcformata (bstring b, int count, const char * fmt, va_list arglist) - * - * The bvcformata function formats data under control of the format control - * string fmt and attempts to append the result to b. The fmt parameter is - * the same as that of the printf function. The variable argument list is - * replaced with arglist, which has been initialized by the va_start macro. - * The size of the appended output is upper bounded by count. If the - * required output exceeds count, the string b is not augmented with any - * contents and a value below BSTR_ERR is returned. If a value below -count - * is returned then it is recommended that the negative of this value be - * used as an update to the count in a subsequent pass. On other errors, - * such as running out of memory, parameter errors or numeric wrap around - * BSTR_ERR is returned. BSTR_OK is returned when the output is successfully - * generated and appended to b. - * - * Note: There is no sanity checking of arglist, and this function is - * destructive of the contents of b from the b->slen point onward. If there - * is an early generation of a '\0' character, the bstring will be truncated - * to this end point. - */ -int bvcformata (bstring b, int count, const char * fmt, va_list arg) { -int n, r, l; - - if (b == NULL || fmt == NULL || count <= 0 || b->data == NULL - || b->mlen <= 0 || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; - - if (count > (n = b->slen + count) + 2) return BSTR_ERR; - if (BSTR_OK != balloc (b, n + 2)) return BSTR_ERR; - - exvsnprintf (r, (char *) b->data + b->slen, count + 2, fmt, arg); - - /* Did the operation complete successfully within bounds? */ - for (l = b->slen; l <= n; l++) { - if ('\0' == b->data[l]) { - b->slen = l; - return BSTR_OK; - } - } - - /* Abort, since the buffer was not large enough. The return value - tries to help set what the retry length should be. */ - - b->data[b->slen] = '\0'; - if (r > count + 1) { /* Does r specify a particular target length? */ - n = r; - } else { - n = count + count; /* If not, just double the size of count */ - if (count > n) n = INT_MAX; - } - n = -n; - - if (n > BSTR_ERR-1) n = BSTR_ERR-1; - return n; -} - -#endif diff --git a/src/bstrlib.h b/src/bstrlib.h deleted file mode 100644 index c8fa694..0000000 --- a/src/bstrlib.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ - -/* - * bstrlib.h - * - * This file is the header file for the core module for implementing the - * bstring functions. - */ - -#ifndef BSTRLIB_INCLUDE -#define BSTRLIB_INCLUDE - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) -# if defined (__TURBOC__) && !defined (__BORLANDC__) -# define BSTRLIB_NOVSNP -# endif -#endif - -#define BSTR_ERR (-1) -#define BSTR_OK (0) -#define BSTR_BS_BUFF_LENGTH_GET (0) - -typedef struct tagbstring * bstring; -typedef const struct tagbstring * const_bstring; - -/* Copy functions */ -#define cstr2bstr bfromcstr -extern bstring bfromcstr (const char * str); -extern bstring bfromcstralloc (int mlen, const char * str); -extern bstring blk2bstr (const void * blk, int len); -extern char * bstr2cstr (const_bstring s, char z); -extern int bcstrfree (char * s); -extern bstring bstrcpy (const_bstring b1); -extern int bassign (bstring a, const_bstring b); -extern int bassignmidstr (bstring a, const_bstring b, int left, int len); -extern int bassigncstr (bstring a, const char * str); -extern int bassignblk (bstring a, const void * s, int len); - -/* Destroy function */ -extern int bdestroy (bstring b); - -/* Space allocation hinting functions */ -extern int balloc (bstring s, int len); -extern int ballocmin (bstring b, int len); - -/* Substring extraction */ -extern bstring bmidstr (const_bstring b, int left, int len); - -/* Various standard manipulations */ -extern int bconcat (bstring b0, const_bstring b1); -extern int bconchar (bstring b0, char c); -extern int bcatcstr (bstring b, const char * s); -extern int bcatblk (bstring b, const void * s, int len); -extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill); -extern int binsertch (bstring s1, int pos, int len, unsigned char fill); -extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill); -extern int bdelete (bstring s1, int pos, int len); -extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill); -extern int btrunc (bstring b, int n); - -/* Scan/search functions */ -extern int bstricmp (const_bstring b0, const_bstring b1); -extern int bstrnicmp (const_bstring b0, const_bstring b1, int n); -extern int biseqcaseless (const_bstring b0, const_bstring b1); -extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len); -extern int biseq (const_bstring b0, const_bstring b1); -extern int bisstemeqblk (const_bstring b0, const void * blk, int len); -extern int biseqcstr (const_bstring b, const char * s); -extern int biseqcstrcaseless (const_bstring b, const char * s); -extern int bstrcmp (const_bstring b0, const_bstring b1); -extern int bstrncmp (const_bstring b0, const_bstring b1, int n); -extern int binstr (const_bstring s1, int pos, const_bstring s2); -extern int binstrr (const_bstring s1, int pos, const_bstring s2); -extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2); -extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2); -extern int bstrchrp (const_bstring b, int c, int pos); -extern int bstrrchrp (const_bstring b, int c, int pos); -#define bstrchr(b,c) bstrchrp ((b), (c), 0) -#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1) -extern int binchr (const_bstring b0, int pos, const_bstring b1); -extern int binchrr (const_bstring b0, int pos, const_bstring b1); -extern int bninchr (const_bstring b0, int pos, const_bstring b1); -extern int bninchrr (const_bstring b0, int pos, const_bstring b1); -extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos); -extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos); - -/* List of string container functions */ -struct bstrList { - int qty, mlen; - bstring * entry; -}; -extern struct bstrList * bstrListCreate (void); -extern int bstrListDestroy (struct bstrList * sl); -extern int bstrListAlloc (struct bstrList * sl, int msz); -extern int bstrListAllocMin (struct bstrList * sl, int msz); - -/* String split and join functions */ -extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar); -extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr); -extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr); -extern bstring bjoin (const struct bstrList * bl, const_bstring sep); -extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); -extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); -extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); - -/* Miscellaneous functions */ -extern int bpattern (bstring b, int len); -extern int btoupper (bstring b); -extern int btolower (bstring b); -extern int bltrimws (bstring b); -extern int brtrimws (bstring b); -extern int btrimws (bstring b); - -/* <*>printf format functions */ -#if !defined (BSTRLIB_NOVSNP) -extern bstring bformat (const char * fmt, ...); -extern int bformata (bstring b, const char * fmt, ...); -extern int bassignformat (bstring b, const char * fmt, ...); -extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); - -#define bvformata(ret, b, fmt, lastarg) { \ -bstring bstrtmp_b = (b); \ -const char * bstrtmp_fmt = (fmt); \ -int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \ - for (;;) { \ - va_list bstrtmp_arglist; \ - va_start (bstrtmp_arglist, lastarg); \ - bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \ - va_end (bstrtmp_arglist); \ - if (bstrtmp_r >= 0) { /* Everything went ok */ \ - bstrtmp_r = BSTR_OK; \ - break; \ - } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \ - bstrtmp_r = BSTR_ERR; \ - break; \ - } \ - bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \ - } \ - ret = bstrtmp_r; \ -} - -#endif - -typedef int (*bNgetc) (void *parm); -typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm); - -/* Input functions */ -extern bstring bgets (bNgetc getcPtr, void * parm, char terminator); -extern bstring bread (bNread readPtr, void * parm); -extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator); -extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator); -extern int breada (bstring b, bNread readPtr, void * parm); - -/* Stream functions */ -extern struct bStream * bsopen (bNread readPtr, void * parm); -extern void * bsclose (struct bStream * s); -extern int bsbufflength (struct bStream * s, int sz); -extern int bsreadln (bstring b, struct bStream * s, char terminator); -extern int bsreadlns (bstring r, struct bStream * s, const_bstring term); -extern int bsread (bstring b, struct bStream * s, int n); -extern int bsreadlna (bstring b, struct bStream * s, char terminator); -extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term); -extern int bsreada (bstring b, struct bStream * s, int n); -extern int bsunread (struct bStream * s, const_bstring b); -extern int bspeek (bstring r, const struct bStream * s); -extern int bssplitscb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); -extern int bssplitstrcb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); -extern int bseof (const struct bStream * s); - -struct tagbstring { - int mlen; - int slen; - unsigned char * data; -}; - -/* Accessor macros */ -#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen)) -#define blength(b) (blengthe ((b), 0)) -#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o)) -#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0)) -#define bdatae(b, e) (bdataofse (b, 0, e)) -#define bdata(b) (bdataofs (b, 0)) -#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e)) -#define bchar(b, p) bchare ((b), (p), '\0') - -/* Static constant string initialization macro */ -#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")} -#if defined(_MSC_VER) -/* There are many versions of MSVC which emit __LINE__ as a non-constant. */ -# define bsStatic(q) bsStaticMlen(q,-32) -#endif -#ifndef bsStatic -# define bsStatic(q) bsStaticMlen(q,-__LINE__) -#endif - -/* Static constant block parameter pair */ -#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1) - -/* Reference building macros */ -#define cstr2tbstr btfromcstr -#define btfromcstr(t,s) { \ - (t).data = (unsigned char *) (s); \ - (t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \ - (t).mlen = -1; \ -} -#define blk2tbstr(t,s,l) { \ - (t).data = (unsigned char *) (s); \ - (t).slen = l; \ - (t).mlen = -1; \ -} -#define btfromblk(t,s,l) blk2tbstr(t,s,l) -#define bmid2tbstr(t,b,p,l) { \ - const_bstring bstrtmp_s = (b); \ - if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \ - int bstrtmp_left = (p); \ - int bstrtmp_len = (l); \ - if (bstrtmp_left < 0) { \ - bstrtmp_len += bstrtmp_left; \ - bstrtmp_left = 0; \ - } \ - if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \ - bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \ - if (bstrtmp_len <= 0) { \ - (t).data = (unsigned char *)""; \ - (t).slen = 0; \ - } else { \ - (t).data = bstrtmp_s->data + bstrtmp_left; \ - (t).slen = bstrtmp_len; \ - } \ - } else { \ - (t).data = (unsigned char *)""; \ - (t).slen = 0; \ - } \ - (t).mlen = -__LINE__; \ -} -#define btfromblkltrimws(t,s,l) { \ - int bstrtmp_idx = 0, bstrtmp_len = (l); \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \ - if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ - } \ - } \ - (t).data = bstrtmp_s + bstrtmp_idx; \ - (t).slen = bstrtmp_len - bstrtmp_idx; \ - (t).mlen = -__LINE__; \ -} -#define btfromblkrtrimws(t,s,l) { \ - int bstrtmp_len = (l) - 1; \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_len >= 0; bstrtmp_len--) { \ - if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ - } \ - } \ - (t).data = bstrtmp_s; \ - (t).slen = bstrtmp_len + 1; \ - (t).mlen = -__LINE__; \ -} -#define btfromblktrimws(t,s,l) { \ - int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \ - if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ - } \ - for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \ - if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ - } \ - } \ - (t).data = bstrtmp_s + bstrtmp_idx; \ - (t).slen = bstrtmp_len + 1 - bstrtmp_idx; \ - (t).mlen = -__LINE__; \ -} - -/* Write protection macros */ -#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; } -#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); } -#define biswriteprotected(t) ((t).mlen <= 0) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/buffer.c b/src/buffer.c new file mode 100644 index 0000000..b81e7fa --- /dev/null +++ b/src/buffer.c @@ -0,0 +1,313 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "buffer.h" + +/* Used as default value for gh_buf->ptr so that people can always + * assume ptr is non-NULL and zero terminated even for new gh_bufs. + */ +unsigned char gh_buf__initbuf[1]; +unsigned char gh_buf__oom[1]; + +#define ENSURE_SIZE(b, d) \ + if ((d) > buf->asize && gh_buf_grow(b, (d)) < 0)\ + return -1; + +void gh_buf_init(gh_buf *buf, int initial_size) +{ + buf->asize = 0; + buf->size = 0; + buf->ptr = gh_buf__initbuf; + + if (initial_size) + gh_buf_grow(buf, initial_size); +} + +int gh_buf_try_grow(gh_buf *buf, int target_size, bool mark_oom) +{ + char *new_ptr; + size_t new_size; + + if (buf->ptr == gh_buf__oom || buf->asize < 0) + return -1; + + if (target_size <= buf->asize) + return 0; + + if (buf->asize == 0) { + new_size = target_size; + new_ptr = NULL; + } else { + new_size = buf->asize; + new_ptr = buf->ptr; + } + + /* grow the buffer size by 1.5, until it's big enough + * to fit our target size */ + while (new_size < target_size) + new_size = (new_size << 1) - (new_size >> 1); + + /* round allocation up to multiple of 8 */ + new_size = (new_size + 7) & ~7; + + new_ptr = realloc(new_ptr, new_size); + + if (!new_ptr) { + if (mark_oom) + buf->ptr = gh_buf__oom; + return -1; + } + + buf->asize = new_size; + buf->ptr = new_ptr; + + /* truncate the existing buffer size if necessary */ + if (buf->size >= buf->asize) + buf->size = buf->asize - 1; + buf->ptr[buf->size] = '\0'; + + return 0; +} + +void gh_buf_free(gh_buf *buf) +{ + if (!buf) return; + + if (buf->asize > 0 && buf->ptr != gh_buf__initbuf && buf->ptr != gh_buf__oom) + free(buf->ptr); + + gh_buf_init(buf, 0); +} + +void gh_buf_clear(gh_buf *buf) +{ + buf->size = 0; + + if (buf->asize > 0) + buf->ptr[0] = '\0'; + + if (buf->asize < 0) { + buf->ptr = gh_buf__initbuf; + buf->asize = 0; + } +} + +int gh_buf_set(gh_buf *buf, const char *data, int len) +{ + if (len == 0 || data == NULL) { + gh_buf_clear(buf); + } else { + if (data != buf->ptr) { + ENSURE_SIZE(buf, len + 1); + memmove(buf->ptr, data, len); + } + buf->size = len; + buf->ptr[buf->size] = '\0'; + } + return 0; +} + +int gh_buf_sets(gh_buf *buf, const char *string) +{ + return gh_buf_set(buf, string, string ? strlen(string) : 0); +} + +int gh_buf_putc(gh_buf *buf, char c) +{ + ENSURE_SIZE(buf, buf->size + 2); + buf->ptr[buf->size++] = c; + buf->ptr[buf->size] = '\0'; + return 0; +} + +int gh_buf_put(gh_buf *buf, const char *data, int len) +{ + ENSURE_SIZE(buf, buf->size + len + 1); + memmove(buf->ptr + buf->size, data, len); + buf->size += len; + buf->ptr[buf->size] = '\0'; + return 0; +} + +int gh_buf_puts(gh_buf *buf, const char *string) +{ + assert(string); + return gh_buf_put(buf, string, strlen(string)); +} + +int gh_buf_vprintf(gh_buf *buf, const char *format, va_list ap) +{ + const int expected_size = buf->size + (strlen(format) * 2); + int len; + + ENSURE_SIZE(buf, expected_size); + + while (1) { + va_list args; + va_copy(args, ap); + + len = vsnprintf( + buf->ptr + buf->size, + buf->asize - buf->size, + format, args + ); + + if (len < 0) { + free(buf->ptr); + buf->ptr = gh_buf__oom; + return -1; + } + + if (len + 1 <= buf->asize - buf->size) { + buf->size += len; + break; + } + + ENSURE_SIZE(buf, buf->size + len + 1); + } + + return 0; +} + +int gh_buf_printf(gh_buf *buf, const char *format, ...) +{ + int r; + va_list ap; + + va_start(ap, format); + r = gh_buf_vprintf(buf, format, ap); + va_end(ap); + + return r; +} + +void gh_buf_copy_cstr(char *data, size_t datasize, const gh_buf *buf) +{ + size_t copylen; + + assert(data && datasize && buf); + + data[0] = '\0'; + + if (buf->size == 0 || buf->asize <= 0) + return; + + copylen = buf->size; + if (copylen > datasize - 1) + copylen = datasize - 1; + memmove(data, buf->ptr, copylen); + data[copylen] = '\0'; +} + +void gh_buf_swap(gh_buf *buf_a, gh_buf *buf_b) +{ + gh_buf t = *buf_a; + *buf_a = *buf_b; + *buf_b = t; +} + +char *gh_buf_detach(gh_buf *buf) +{ + char *data = buf->ptr; + + if (buf->asize == 0 || buf->ptr == gh_buf__oom) + return NULL; + + gh_buf_init(buf, 0); + + return data; +} + +void gh_buf_attach(gh_buf *buf, char *ptr, int asize) +{ + gh_buf_free(buf); + + if (ptr) { + buf->ptr = ptr; + buf->size = strlen(ptr); + if (asize) + buf->asize = (asize < buf->size) ? buf->size + 1 : asize; + else /* pass 0 to fall back on strlen + 1 */ + buf->asize = buf->size + 1; + } else { + gh_buf_grow(buf, asize); + } +} + +int gh_buf_cmp(const gh_buf *a, const gh_buf *b) +{ + int result = memcmp(a->ptr, b->ptr, MIN(a->size, b->size)); + return (result != 0) ? result : + (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0; +} + +int gh_buf_strchr(const gh_buf *buf, int c, int pos) +{ + const char *p = memchr(buf->ptr + pos, c, buf->size - pos); + if (!p) + return -1; + + return (int)(p - p->ptr); +} + +int gh_buf_strrchr(const gh_buf *buf, int c, int pos) +{ + int i; + + for (i = pos; i >= 0; i--) { + if (buf->ptr[i] == (unsigned char) c) + return i; + } + + return -1; +} + +void gh_buf_truncate(gh_buf *buf, size_t len) +{ + assert(buf->asize >= 0); + + if (len < buf->size) { + buf->size = len; + buf->ptr[buf->size] = '\0'; + } +} + +void gh_buf_ltruncate(gh_buf *buf, size_t len) +{ + assert(buf->asize >= 0); + + if (len && len < buf->size) { + memmove(buf->ptr, buf->ptr + len, buf->size - len); + buf->size -= len; + buf->ptr[buf->size] = '\0'; + } +} + +void gh_buf_trim(gh_buf *buf) +{ + size_t i = 0; + + assert(buf->asize >= 0); + + /* ltrim */ + while (i < buf->size && isspace(buf->ptr[i])) + i++; + + gh_buf_truncate(buf, i); + + /* rtrim */ + while (buf->size > 0) { + if (!isspace(buf->ptr[buf->size - 1])) + break; + + buf->size--; + } + + buf->ptr[buf->size] = '\0'; +} diff --git a/src/buffer.h b/src/buffer.h new file mode 100644 index 0000000..2581ee3 --- /dev/null +++ b/src/buffer.h @@ -0,0 +1,119 @@ +#ifndef INCLUDE_buffer_h__ +#define INCLUDE_buffer_h__ + +#include +#include +#include +#include + +typedef struct { + unsigned char *ptr; + int asize, size; +} gh_buf; + +extern unsigned char gh_buf__initbuf[]; +extern unsigned char gh_buf__oom[]; + +#define GH_BUF_INIT { gh_buf__initbuf, 0, 0 } + +/** + * Initialize a gh_buf structure. + * + * For the cases where GH_BUF_INIT cannot be used to do static + * initialization. + */ +extern void gh_buf_init(gh_buf *buf, int initial_size); + +static inline void gh_buf_static(gh_buf *buf, unsigned char *source) +{ + buf->ptr = source; + buf->size = strlen(source); + buf->asize = -1; +} + +/** + * Attempt to grow the buffer to hold at least `target_size` bytes. + * + * If the allocation fails, this will return an error. If mark_oom is true, + * this will mark the buffer as invalid for future operations; if false, + * existing buffer content will be preserved, but calling code must handle + * that buffer was not expanded. + */ +extern int gh_buf_try_grow(gh_buf *buf, int target_size, bool mark_oom); + +/** + * Grow the buffer to hold at least `target_size` bytes. + * + * If the allocation fails, this will return an error and the buffer will be + * marked as invalid for future operations, invaliding contents. + * + * @return 0 on success or -1 on failure + */ +static inline int gh_buf_grow(gh_buf *buf, int target_size) +{ + return gh_buf_try_grow(buf, target_size, true); +} + +extern void gh_buf_free(gh_buf *buf); +extern void gh_buf_swap(gh_buf *buf_a, gh_buf *buf_b); + +/** + * Test if there have been any reallocation failures with this gh_buf. + * + * Any function that writes to a gh_buf can fail due to memory allocation + * issues. If one fails, the gh_buf will be marked with an OOM error and + * further calls to modify the buffer will fail. Check gh_buf_oom() at the + * end of your sequence and it will be true if you ran out of memory at any + * point with that buffer. + * + * @return false if no error, true if allocation error + */ +static inline bool gh_buf_oom(const gh_buf *buf) +{ + return (buf->ptr == gh_buf__oom); +} + + +static inline size_t gh_buf_len(const gh_buf *buf) +{ + return buf->size; +} + +extern int gh_buf_cmp(const gh_buf *a, const gh_buf *b); + +extern void gh_buf_attach(gh_buf *buf, char *ptr, int asize); +extern char *gh_buf_detach(gh_buf *buf); +extern void gh_buf_copy_cstr(char *data, int datasize, const gh_buf *buf); + +static inline const char *gh_buf_cstr(const gh_buf *buf) +{ + return buf->ptr; +} + +#define gh_buf_at(buf, n) ((buf)->ptr[n]) + +/* + * Functions below that return int value error codes will return 0 on + * success or -1 on failure (which generally means an allocation failed). + * Using a gh_buf where the allocation has failed with result in -1 from + * all further calls using that buffer. As a result, you can ignore the + * return code of these functions and call them in a series then just call + * gh_buf_oom at the end. + */ +extern int gh_buf_set(gh_buf *buf, const char *data, int len); +extern int gh_buf_sets(gh_buf *buf, const char *string); +extern int gh_buf_putc(gh_buf *buf, char c); +extern int gh_buf_put(gh_buf *buf, const char *data, int len); +extern int gh_buf_puts(gh_buf *buf, const char *string); +extern int gh_buf_printf(gh_buf *buf, const char *format, ...) + __attribute__((format (printf, 2, 3))); +extern int gh_buf_vprintf(gh_buf *buf, const char *format, va_list ap); +extern void gh_buf_clear(gh_buf *buf); + +int gh_buf_strchr(const gh_buf *buf, int c, int pos); +int gh_buf_strrchr(const gh_buf *buf, int c, int pos); +void gh_buf_truncate(gh_buf *buf, int len); +void gh_buf_ltruncate(gh_buf *buf, int len); +void gh_buf_trim(gh_buf *buf); + +#endif diff --git a/src/case_fold_switch.c b/src/case_fold_switch.c deleted file mode 100644 index 70fdd75..0000000 --- a/src/case_fold_switch.c +++ /dev/null @@ -1,2637 +0,0 @@ - switch (c) { - case 0x0041: - bufpush(0x0061); - break; - case 0x0042: - bufpush(0x0062); - break; - case 0x0043: - bufpush(0x0063); - break; - case 0x0044: - bufpush(0x0064); - break; - case 0x0045: - bufpush(0x0065); - break; - case 0x0046: - bufpush(0x0066); - break; - case 0x0047: - bufpush(0x0067); - break; - case 0x0048: - bufpush(0x0068); - break; - case 0x0049: - bufpush(0x0069); - break; - case 0x004A: - bufpush(0x006A); - break; - case 0x004B: - bufpush(0x006B); - break; - case 0x004C: - bufpush(0x006C); - break; - case 0x004D: - bufpush(0x006D); - break; - case 0x004E: - bufpush(0x006E); - break; - case 0x004F: - bufpush(0x006F); - break; - case 0x0050: - bufpush(0x0070); - break; - case 0x0051: - bufpush(0x0071); - break; - case 0x0052: - bufpush(0x0072); - break; - case 0x0053: - bufpush(0x0073); - break; - case 0x0054: - bufpush(0x0074); - break; - case 0x0055: - bufpush(0x0075); - break; - case 0x0056: - bufpush(0x0076); - break; - case 0x0057: - bufpush(0x0077); - break; - case 0x0058: - bufpush(0x0078); - break; - case 0x0059: - bufpush(0x0079); - break; - case 0x005A: - bufpush(0x007A); - break; - case 0x00B5: - bufpush(0x03BC); - break; - case 0x00C0: - bufpush(0x00E0); - break; - case 0x00C1: - bufpush(0x00E1); - break; - case 0x00C2: - bufpush(0x00E2); - break; - case 0x00C3: - bufpush(0x00E3); - break; - case 0x00C4: - bufpush(0x00E4); - break; - case 0x00C5: - bufpush(0x00E5); - break; - case 0x00C6: - bufpush(0x00E6); - break; - case 0x00C7: - bufpush(0x00E7); - break; - case 0x00C8: - bufpush(0x00E8); - break; - case 0x00C9: - bufpush(0x00E9); - break; - case 0x00CA: - bufpush(0x00EA); - break; - case 0x00CB: - bufpush(0x00EB); - break; - case 0x00CC: - bufpush(0x00EC); - break; - case 0x00CD: - bufpush(0x00ED); - break; - case 0x00CE: - bufpush(0x00EE); - break; - case 0x00CF: - bufpush(0x00EF); - break; - case 0x00D0: - bufpush(0x00F0); - break; - case 0x00D1: - bufpush(0x00F1); - break; - case 0x00D2: - bufpush(0x00F2); - break; - case 0x00D3: - bufpush(0x00F3); - break; - case 0x00D4: - bufpush(0x00F4); - break; - case 0x00D5: - bufpush(0x00F5); - break; - case 0x00D6: - bufpush(0x00F6); - break; - case 0x00D8: - bufpush(0x00F8); - break; - case 0x00D9: - bufpush(0x00F9); - break; - case 0x00DA: - bufpush(0x00FA); - break; - case 0x00DB: - bufpush(0x00FB); - break; - case 0x00DC: - bufpush(0x00FC); - break; - case 0x00DD: - bufpush(0x00FD); - break; - case 0x00DE: - bufpush(0x00FE); - break; - case 0x00DF: - bufpush(0x0073); - bufpush(0x0073); - break; - case 0x0100: - bufpush(0x0101); - break; - case 0x0102: - bufpush(0x0103); - break; - case 0x0104: - bufpush(0x0105); - break; - case 0x0106: - bufpush(0x0107); - break; - case 0x0108: - bufpush(0x0109); - break; - case 0x010A: - bufpush(0x010B); - break; - case 0x010C: - bufpush(0x010D); - break; - case 0x010E: - bufpush(0x010F); - break; - case 0x0110: - bufpush(0x0111); - break; - case 0x0112: - bufpush(0x0113); - break; - case 0x0114: - bufpush(0x0115); - break; - case 0x0116: - bufpush(0x0117); - break; - case 0x0118: - bufpush(0x0119); - break; - case 0x011A: - bufpush(0x011B); - break; - case 0x011C: - bufpush(0x011D); - break; - case 0x011E: - bufpush(0x011F); - break; - case 0x0120: - bufpush(0x0121); - break; - case 0x0122: - bufpush(0x0123); - break; - case 0x0124: - bufpush(0x0125); - break; - case 0x0126: - bufpush(0x0127); - break; - case 0x0128: - bufpush(0x0129); - break; - case 0x012A: - bufpush(0x012B); - break; - case 0x012C: - bufpush(0x012D); - break; - case 0x012E: - bufpush(0x012F); - break; - case 0x0130: - bufpush(0x0069); - bufpush(0x0307); - break; - case 0x0132: - bufpush(0x0133); - break; - case 0x0134: - bufpush(0x0135); - break; - case 0x0136: - bufpush(0x0137); - break; - case 0x0139: - bufpush(0x013A); - break; - case 0x013B: - bufpush(0x013C); - break; - case 0x013D: - bufpush(0x013E); - break; - case 0x013F: - bufpush(0x0140); - break; - case 0x0141: - bufpush(0x0142); - break; - case 0x0143: - bufpush(0x0144); - break; - case 0x0145: - bufpush(0x0146); - break; - case 0x0147: - bufpush(0x0148); - break; - case 0x0149: - bufpush(0x02BC); - bufpush(0x006E); - break; - case 0x014A: - bufpush(0x014B); - break; - case 0x014C: - bufpush(0x014D); - break; - case 0x014E: - bufpush(0x014F); - break; - case 0x0150: - bufpush(0x0151); - break; - case 0x0152: - bufpush(0x0153); - break; - case 0x0154: - bufpush(0x0155); - break; - case 0x0156: - bufpush(0x0157); - break; - case 0x0158: - bufpush(0x0159); - break; - case 0x015A: - bufpush(0x015B); - break; - case 0x015C: - bufpush(0x015D); - break; - case 0x015E: - bufpush(0x015F); - break; - case 0x0160: - bufpush(0x0161); - break; - case 0x0162: - bufpush(0x0163); - break; - case 0x0164: - bufpush(0x0165); - break; - case 0x0166: - bufpush(0x0167); - break; - case 0x0168: - bufpush(0x0169); - break; - case 0x016A: - bufpush(0x016B); - break; - case 0x016C: - bufpush(0x016D); - break; - case 0x016E: - bufpush(0x016F); - break; - case 0x0170: - bufpush(0x0171); - break; - case 0x0172: - bufpush(0x0173); - break; - case 0x0174: - bufpush(0x0175); - break; - case 0x0176: - bufpush(0x0177); - break; - case 0x0178: - bufpush(0x00FF); - break; - case 0x0179: - bufpush(0x017A); - break; - case 0x017B: - bufpush(0x017C); - break; - case 0x017D: - bufpush(0x017E); - break; - case 0x017F: - bufpush(0x0073); - break; - case 0x0181: - bufpush(0x0253); - break; - case 0x0182: - bufpush(0x0183); - break; - case 0x0184: - bufpush(0x0185); - break; - case 0x0186: - bufpush(0x0254); - break; - case 0x0187: - bufpush(0x0188); - break; - case 0x0189: - bufpush(0x0256); - break; - case 0x018A: - bufpush(0x0257); - break; - case 0x018B: - bufpush(0x018C); - break; - case 0x018E: - bufpush(0x01DD); - break; - case 0x018F: - bufpush(0x0259); - break; - case 0x0190: - bufpush(0x025B); - break; - case 0x0191: - bufpush(0x0192); - break; - case 0x0193: - bufpush(0x0260); - break; - case 0x0194: - bufpush(0x0263); - break; - case 0x0196: - bufpush(0x0269); - break; - case 0x0197: - bufpush(0x0268); - break; - case 0x0198: - bufpush(0x0199); - break; - case 0x019C: - bufpush(0x026F); - break; - case 0x019D: - bufpush(0x0272); - break; - case 0x019F: - bufpush(0x0275); - break; - case 0x01A0: - bufpush(0x01A1); - break; - case 0x01A2: - bufpush(0x01A3); - break; - case 0x01A4: - bufpush(0x01A5); - break; - case 0x01A6: - bufpush(0x0280); - break; - case 0x01A7: - bufpush(0x01A8); - break; - case 0x01A9: - bufpush(0x0283); - break; - case 0x01AC: - bufpush(0x01AD); - break; - case 0x01AE: - bufpush(0x0288); - break; - case 0x01AF: - bufpush(0x01B0); - break; - case 0x01B1: - bufpush(0x028A); - break; - case 0x01B2: - bufpush(0x028B); - break; - case 0x01B3: - bufpush(0x01B4); - break; - case 0x01B5: - bufpush(0x01B6); - break; - case 0x01B7: - bufpush(0x0292); - break; - case 0x01B8: - bufpush(0x01B9); - break; - case 0x01BC: - bufpush(0x01BD); - break; - case 0x01C4: - bufpush(0x01C6); - break; - case 0x01C5: - bufpush(0x01C6); - break; - case 0x01C7: - bufpush(0x01C9); - break; - case 0x01C8: - bufpush(0x01C9); - break; - case 0x01CA: - bufpush(0x01CC); - break; - case 0x01CB: - bufpush(0x01CC); - break; - case 0x01CD: - bufpush(0x01CE); - break; - case 0x01CF: - bufpush(0x01D0); - break; - case 0x01D1: - bufpush(0x01D2); - break; - case 0x01D3: - bufpush(0x01D4); - break; - case 0x01D5: - bufpush(0x01D6); - break; - case 0x01D7: - bufpush(0x01D8); - break; - case 0x01D9: - bufpush(0x01DA); - break; - case 0x01DB: - bufpush(0x01DC); - break; - case 0x01DE: - bufpush(0x01DF); - break; - case 0x01E0: - bufpush(0x01E1); - break; - case 0x01E2: - bufpush(0x01E3); - break; - case 0x01E4: - bufpush(0x01E5); - break; - case 0x01E6: - bufpush(0x01E7); - break; - case 0x01E8: - bufpush(0x01E9); - break; - case 0x01EA: - bufpush(0x01EB); - break; - case 0x01EC: - bufpush(0x01ED); - break; - case 0x01EE: - bufpush(0x01EF); - break; - case 0x01F0: - bufpush(0x006A); - bufpush(0x030C); - break; - case 0x01F1: - bufpush(0x01F3); - break; - case 0x01F2: - bufpush(0x01F3); - break; - case 0x01F4: - bufpush(0x01F5); - break; - case 0x01F6: - bufpush(0x0195); - break; - case 0x01F7: - bufpush(0x01BF); - break; - case 0x01F8: - bufpush(0x01F9); - break; - case 0x01FA: - bufpush(0x01FB); - break; - case 0x01FC: - bufpush(0x01FD); - break; - case 0x01FE: - bufpush(0x01FF); - break; - case 0x0200: - bufpush(0x0201); - break; - case 0x0202: - bufpush(0x0203); - break; - case 0x0204: - bufpush(0x0205); - break; - case 0x0206: - bufpush(0x0207); - break; - case 0x0208: - bufpush(0x0209); - break; - case 0x020A: - bufpush(0x020B); - break; - case 0x020C: - bufpush(0x020D); - break; - case 0x020E: - bufpush(0x020F); - break; - case 0x0210: - bufpush(0x0211); - break; - case 0x0212: - bufpush(0x0213); - break; - case 0x0214: - bufpush(0x0215); - break; - case 0x0216: - bufpush(0x0217); - break; - case 0x0218: - bufpush(0x0219); - break; - case 0x021A: - bufpush(0x021B); - break; - case 0x021C: - bufpush(0x021D); - break; - case 0x021E: - bufpush(0x021F); - break; - case 0x0220: - bufpush(0x019E); - break; - case 0x0222: - bufpush(0x0223); - break; - case 0x0224: - bufpush(0x0225); - break; - case 0x0226: - bufpush(0x0227); - break; - case 0x0228: - bufpush(0x0229); - break; - case 0x022A: - bufpush(0x022B); - break; - case 0x022C: - bufpush(0x022D); - break; - case 0x022E: - bufpush(0x022F); - break; - case 0x0230: - bufpush(0x0231); - break; - case 0x0232: - bufpush(0x0233); - break; - case 0x0345: - bufpush(0x03B9); - break; - case 0x0386: - bufpush(0x03AC); - break; - case 0x0388: - bufpush(0x03AD); - break; - case 0x0389: - bufpush(0x03AE); - break; - case 0x038A: - bufpush(0x03AF); - break; - case 0x038C: - bufpush(0x03CC); - break; - case 0x038E: - bufpush(0x03CD); - break; - case 0x038F: - bufpush(0x03CE); - break; - case 0x0390: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x0391: - bufpush(0x03B1); - break; - case 0x0392: - bufpush(0x03B2); - break; - case 0x0393: - bufpush(0x03B3); - break; - case 0x0394: - bufpush(0x03B4); - break; - case 0x0395: - bufpush(0x03B5); - break; - case 0x0396: - bufpush(0x03B6); - break; - case 0x0397: - bufpush(0x03B7); - break; - case 0x0398: - bufpush(0x03B8); - break; - case 0x0399: - bufpush(0x03B9); - break; - case 0x039A: - bufpush(0x03BA); - break; - case 0x039B: - bufpush(0x03BB); - break; - case 0x039C: - bufpush(0x03BC); - break; - case 0x039D: - bufpush(0x03BD); - break; - case 0x039E: - bufpush(0x03BE); - break; - case 0x039F: - bufpush(0x03BF); - break; - case 0x03A0: - bufpush(0x03C0); - break; - case 0x03A1: - bufpush(0x03C1); - break; - case 0x03A3: - bufpush(0x03C3); - break; - case 0x03A4: - bufpush(0x03C4); - break; - case 0x03A5: - bufpush(0x03C5); - break; - case 0x03A6: - bufpush(0x03C6); - break; - case 0x03A7: - bufpush(0x03C7); - break; - case 0x03A8: - bufpush(0x03C8); - break; - case 0x03A9: - bufpush(0x03C9); - break; - case 0x03AA: - bufpush(0x03CA); - break; - case 0x03AB: - bufpush(0x03CB); - break; - case 0x03B0: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x03C2: - bufpush(0x03C3); - break; - case 0x03D0: - bufpush(0x03B2); - break; - case 0x03D1: - bufpush(0x03B8); - break; - case 0x03D5: - bufpush(0x03C6); - break; - case 0x03D6: - bufpush(0x03C0); - break; - case 0x03D8: - bufpush(0x03D9); - break; - case 0x03DA: - bufpush(0x03DB); - break; - case 0x03DC: - bufpush(0x03DD); - break; - case 0x03DE: - bufpush(0x03DF); - break; - case 0x03E0: - bufpush(0x03E1); - break; - case 0x03E2: - bufpush(0x03E3); - break; - case 0x03E4: - bufpush(0x03E5); - break; - case 0x03E6: - bufpush(0x03E7); - break; - case 0x03E8: - bufpush(0x03E9); - break; - case 0x03EA: - bufpush(0x03EB); - break; - case 0x03EC: - bufpush(0x03ED); - break; - case 0x03EE: - bufpush(0x03EF); - break; - case 0x03F0: - bufpush(0x03BA); - break; - case 0x03F1: - bufpush(0x03C1); - break; - case 0x03F2: - bufpush(0x03C3); - break; - case 0x03F4: - bufpush(0x03B8); - break; - case 0x03F5: - bufpush(0x03B5); - break; - case 0x0400: - bufpush(0x0450); - break; - case 0x0401: - bufpush(0x0451); - break; - case 0x0402: - bufpush(0x0452); - break; - case 0x0403: - bufpush(0x0453); - break; - case 0x0404: - bufpush(0x0454); - break; - case 0x0405: - bufpush(0x0455); - break; - case 0x0406: - bufpush(0x0456); - break; - case 0x0407: - bufpush(0x0457); - break; - case 0x0408: - bufpush(0x0458); - break; - case 0x0409: - bufpush(0x0459); - break; - case 0x040A: - bufpush(0x045A); - break; - case 0x040B: - bufpush(0x045B); - break; - case 0x040C: - bufpush(0x045C); - break; - case 0x040D: - bufpush(0x045D); - break; - case 0x040E: - bufpush(0x045E); - break; - case 0x040F: - bufpush(0x045F); - break; - case 0x0410: - bufpush(0x0430); - break; - case 0x0411: - bufpush(0x0431); - break; - case 0x0412: - bufpush(0x0432); - break; - case 0x0413: - bufpush(0x0433); - break; - case 0x0414: - bufpush(0x0434); - break; - case 0x0415: - bufpush(0x0435); - break; - case 0x0416: - bufpush(0x0436); - break; - case 0x0417: - bufpush(0x0437); - break; - case 0x0418: - bufpush(0x0438); - break; - case 0x0419: - bufpush(0x0439); - break; - case 0x041A: - bufpush(0x043A); - break; - case 0x041B: - bufpush(0x043B); - break; - case 0x041C: - bufpush(0x043C); - break; - case 0x041D: - bufpush(0x043D); - break; - case 0x041E: - bufpush(0x043E); - break; - case 0x041F: - bufpush(0x043F); - break; - case 0x0420: - bufpush(0x0440); - break; - case 0x0421: - bufpush(0x0441); - break; - case 0x0422: - bufpush(0x0442); - break; - case 0x0423: - bufpush(0x0443); - break; - case 0x0424: - bufpush(0x0444); - break; - case 0x0425: - bufpush(0x0445); - break; - case 0x0426: - bufpush(0x0446); - break; - case 0x0427: - bufpush(0x0447); - break; - case 0x0428: - bufpush(0x0448); - break; - case 0x0429: - bufpush(0x0449); - break; - case 0x042A: - bufpush(0x044A); - break; - case 0x042B: - bufpush(0x044B); - break; - case 0x042C: - bufpush(0x044C); - break; - case 0x042D: - bufpush(0x044D); - break; - case 0x042E: - bufpush(0x044E); - break; - case 0x042F: - bufpush(0x044F); - break; - case 0x0460: - bufpush(0x0461); - break; - case 0x0462: - bufpush(0x0463); - break; - case 0x0464: - bufpush(0x0465); - break; - case 0x0466: - bufpush(0x0467); - break; - case 0x0468: - bufpush(0x0469); - break; - case 0x046A: - bufpush(0x046B); - break; - case 0x046C: - bufpush(0x046D); - break; - case 0x046E: - bufpush(0x046F); - break; - case 0x0470: - bufpush(0x0471); - break; - case 0x0472: - bufpush(0x0473); - break; - case 0x0474: - bufpush(0x0475); - break; - case 0x0476: - bufpush(0x0477); - break; - case 0x0478: - bufpush(0x0479); - break; - case 0x047A: - bufpush(0x047B); - break; - case 0x047C: - bufpush(0x047D); - break; - case 0x047E: - bufpush(0x047F); - break; - case 0x0480: - bufpush(0x0481); - break; - case 0x048A: - bufpush(0x048B); - break; - case 0x048C: - bufpush(0x048D); - break; - case 0x048E: - bufpush(0x048F); - break; - case 0x0490: - bufpush(0x0491); - break; - case 0x0492: - bufpush(0x0493); - break; - case 0x0494: - bufpush(0x0495); - break; - case 0x0496: - bufpush(0x0497); - break; - case 0x0498: - bufpush(0x0499); - break; - case 0x049A: - bufpush(0x049B); - break; - case 0x049C: - bufpush(0x049D); - break; - case 0x049E: - bufpush(0x049F); - break; - case 0x04A0: - bufpush(0x04A1); - break; - case 0x04A2: - bufpush(0x04A3); - break; - case 0x04A4: - bufpush(0x04A5); - break; - case 0x04A6: - bufpush(0x04A7); - break; - case 0x04A8: - bufpush(0x04A9); - break; - case 0x04AA: - bufpush(0x04AB); - break; - case 0x04AC: - bufpush(0x04AD); - break; - case 0x04AE: - bufpush(0x04AF); - break; - case 0x04B0: - bufpush(0x04B1); - break; - case 0x04B2: - bufpush(0x04B3); - break; - case 0x04B4: - bufpush(0x04B5); - break; - case 0x04B6: - bufpush(0x04B7); - break; - case 0x04B8: - bufpush(0x04B9); - break; - case 0x04BA: - bufpush(0x04BB); - break; - case 0x04BC: - bufpush(0x04BD); - break; - case 0x04BE: - bufpush(0x04BF); - break; - case 0x04C1: - bufpush(0x04C2); - break; - case 0x04C3: - bufpush(0x04C4); - break; - case 0x04C5: - bufpush(0x04C6); - break; - case 0x04C7: - bufpush(0x04C8); - break; - case 0x04C9: - bufpush(0x04CA); - break; - case 0x04CB: - bufpush(0x04CC); - break; - case 0x04CD: - bufpush(0x04CE); - break; - case 0x04D0: - bufpush(0x04D1); - break; - case 0x04D2: - bufpush(0x04D3); - break; - case 0x04D4: - bufpush(0x04D5); - break; - case 0x04D6: - bufpush(0x04D7); - break; - case 0x04D8: - bufpush(0x04D9); - break; - case 0x04DA: - bufpush(0x04DB); - break; - case 0x04DC: - bufpush(0x04DD); - break; - case 0x04DE: - bufpush(0x04DF); - break; - case 0x04E0: - bufpush(0x04E1); - break; - case 0x04E2: - bufpush(0x04E3); - break; - case 0x04E4: - bufpush(0x04E5); - break; - case 0x04E6: - bufpush(0x04E7); - break; - case 0x04E8: - bufpush(0x04E9); - break; - case 0x04EA: - bufpush(0x04EB); - break; - case 0x04EC: - bufpush(0x04ED); - break; - case 0x04EE: - bufpush(0x04EF); - break; - case 0x04F0: - bufpush(0x04F1); - break; - case 0x04F2: - bufpush(0x04F3); - break; - case 0x04F4: - bufpush(0x04F5); - break; - case 0x04F8: - bufpush(0x04F9); - break; - case 0x0500: - bufpush(0x0501); - break; - case 0x0502: - bufpush(0x0503); - break; - case 0x0504: - bufpush(0x0505); - break; - case 0x0506: - bufpush(0x0507); - break; - case 0x0508: - bufpush(0x0509); - break; - case 0x050A: - bufpush(0x050B); - break; - case 0x050C: - bufpush(0x050D); - break; - case 0x050E: - bufpush(0x050F); - break; - case 0x0531: - bufpush(0x0561); - break; - case 0x0532: - bufpush(0x0562); - break; - case 0x0533: - bufpush(0x0563); - break; - case 0x0534: - bufpush(0x0564); - break; - case 0x0535: - bufpush(0x0565); - break; - case 0x0536: - bufpush(0x0566); - break; - case 0x0537: - bufpush(0x0567); - break; - case 0x0538: - bufpush(0x0568); - break; - case 0x0539: - bufpush(0x0569); - break; - case 0x053A: - bufpush(0x056A); - break; - case 0x053B: - bufpush(0x056B); - break; - case 0x053C: - bufpush(0x056C); - break; - case 0x053D: - bufpush(0x056D); - break; - case 0x053E: - bufpush(0x056E); - break; - case 0x053F: - bufpush(0x056F); - break; - case 0x0540: - bufpush(0x0570); - break; - case 0x0541: - bufpush(0x0571); - break; - case 0x0542: - bufpush(0x0572); - break; - case 0x0543: - bufpush(0x0573); - break; - case 0x0544: - bufpush(0x0574); - break; - case 0x0545: - bufpush(0x0575); - break; - case 0x0546: - bufpush(0x0576); - break; - case 0x0547: - bufpush(0x0577); - break; - case 0x0548: - bufpush(0x0578); - break; - case 0x0549: - bufpush(0x0579); - break; - case 0x054A: - bufpush(0x057A); - break; - case 0x054B: - bufpush(0x057B); - break; - case 0x054C: - bufpush(0x057C); - break; - case 0x054D: - bufpush(0x057D); - break; - case 0x054E: - bufpush(0x057E); - break; - case 0x054F: - bufpush(0x057F); - break; - case 0x0550: - bufpush(0x0580); - break; - case 0x0551: - bufpush(0x0581); - break; - case 0x0552: - bufpush(0x0582); - break; - case 0x0553: - bufpush(0x0583); - break; - case 0x0554: - bufpush(0x0584); - break; - case 0x0555: - bufpush(0x0585); - break; - case 0x0556: - bufpush(0x0586); - break; - case 0x0587: - bufpush(0x0565); - bufpush(0x0582); - break; - case 0x1E00: - bufpush(0x1E01); - break; - case 0x1E02: - bufpush(0x1E03); - break; - case 0x1E04: - bufpush(0x1E05); - break; - case 0x1E06: - bufpush(0x1E07); - break; - case 0x1E08: - bufpush(0x1E09); - break; - case 0x1E0A: - bufpush(0x1E0B); - break; - case 0x1E0C: - bufpush(0x1E0D); - break; - case 0x1E0E: - bufpush(0x1E0F); - break; - case 0x1E10: - bufpush(0x1E11); - break; - case 0x1E12: - bufpush(0x1E13); - break; - case 0x1E14: - bufpush(0x1E15); - break; - case 0x1E16: - bufpush(0x1E17); - break; - case 0x1E18: - bufpush(0x1E19); - break; - case 0x1E1A: - bufpush(0x1E1B); - break; - case 0x1E1C: - bufpush(0x1E1D); - break; - case 0x1E1E: - bufpush(0x1E1F); - break; - case 0x1E20: - bufpush(0x1E21); - break; - case 0x1E22: - bufpush(0x1E23); - break; - case 0x1E24: - bufpush(0x1E25); - break; - case 0x1E26: - bufpush(0x1E27); - break; - case 0x1E28: - bufpush(0x1E29); - break; - case 0x1E2A: - bufpush(0x1E2B); - break; - case 0x1E2C: - bufpush(0x1E2D); - break; - case 0x1E2E: - bufpush(0x1E2F); - break; - case 0x1E30: - bufpush(0x1E31); - break; - case 0x1E32: - bufpush(0x1E33); - break; - case 0x1E34: - bufpush(0x1E35); - break; - case 0x1E36: - bufpush(0x1E37); - break; - case 0x1E38: - bufpush(0x1E39); - break; - case 0x1E3A: - bufpush(0x1E3B); - break; - case 0x1E3C: - bufpush(0x1E3D); - break; - case 0x1E3E: - bufpush(0x1E3F); - break; - case 0x1E40: - bufpush(0x1E41); - break; - case 0x1E42: - bufpush(0x1E43); - break; - case 0x1E44: - bufpush(0x1E45); - break; - case 0x1E46: - bufpush(0x1E47); - break; - case 0x1E48: - bufpush(0x1E49); - break; - case 0x1E4A: - bufpush(0x1E4B); - break; - case 0x1E4C: - bufpush(0x1E4D); - break; - case 0x1E4E: - bufpush(0x1E4F); - break; - case 0x1E50: - bufpush(0x1E51); - break; - case 0x1E52: - bufpush(0x1E53); - break; - case 0x1E54: - bufpush(0x1E55); - break; - case 0x1E56: - bufpush(0x1E57); - break; - case 0x1E58: - bufpush(0x1E59); - break; - case 0x1E5A: - bufpush(0x1E5B); - break; - case 0x1E5C: - bufpush(0x1E5D); - break; - case 0x1E5E: - bufpush(0x1E5F); - break; - case 0x1E60: - bufpush(0x1E61); - break; - case 0x1E62: - bufpush(0x1E63); - break; - case 0x1E64: - bufpush(0x1E65); - break; - case 0x1E66: - bufpush(0x1E67); - break; - case 0x1E68: - bufpush(0x1E69); - break; - case 0x1E6A: - bufpush(0x1E6B); - break; - case 0x1E6C: - bufpush(0x1E6D); - break; - case 0x1E6E: - bufpush(0x1E6F); - break; - case 0x1E70: - bufpush(0x1E71); - break; - case 0x1E72: - bufpush(0x1E73); - break; - case 0x1E74: - bufpush(0x1E75); - break; - case 0x1E76: - bufpush(0x1E77); - break; - case 0x1E78: - bufpush(0x1E79); - break; - case 0x1E7A: - bufpush(0x1E7B); - break; - case 0x1E7C: - bufpush(0x1E7D); - break; - case 0x1E7E: - bufpush(0x1E7F); - break; - case 0x1E80: - bufpush(0x1E81); - break; - case 0x1E82: - bufpush(0x1E83); - break; - case 0x1E84: - bufpush(0x1E85); - break; - case 0x1E86: - bufpush(0x1E87); - break; - case 0x1E88: - bufpush(0x1E89); - break; - case 0x1E8A: - bufpush(0x1E8B); - break; - case 0x1E8C: - bufpush(0x1E8D); - break; - case 0x1E8E: - bufpush(0x1E8F); - break; - case 0x1E90: - bufpush(0x1E91); - break; - case 0x1E92: - bufpush(0x1E93); - break; - case 0x1E94: - bufpush(0x1E95); - break; - case 0x1E96: - bufpush(0x0068); - bufpush(0x0331); - break; - case 0x1E97: - bufpush(0x0074); - bufpush(0x0308); - break; - case 0x1E98: - bufpush(0x0077); - bufpush(0x030A); - break; - case 0x1E99: - bufpush(0x0079); - bufpush(0x030A); - break; - case 0x1E9A: - bufpush(0x0061); - bufpush(0x02BE); - break; - case 0x1E9B: - bufpush(0x1E61); - break; - case 0x1EA0: - bufpush(0x1EA1); - break; - case 0x1EA2: - bufpush(0x1EA3); - break; - case 0x1EA4: - bufpush(0x1EA5); - break; - case 0x1EA6: - bufpush(0x1EA7); - break; - case 0x1EA8: - bufpush(0x1EA9); - break; - case 0x1EAA: - bufpush(0x1EAB); - break; - case 0x1EAC: - bufpush(0x1EAD); - break; - case 0x1EAE: - bufpush(0x1EAF); - break; - case 0x1EB0: - bufpush(0x1EB1); - break; - case 0x1EB2: - bufpush(0x1EB3); - break; - case 0x1EB4: - bufpush(0x1EB5); - break; - case 0x1EB6: - bufpush(0x1EB7); - break; - case 0x1EB8: - bufpush(0x1EB9); - break; - case 0x1EBA: - bufpush(0x1EBB); - break; - case 0x1EBC: - bufpush(0x1EBD); - break; - case 0x1EBE: - bufpush(0x1EBF); - break; - case 0x1EC0: - bufpush(0x1EC1); - break; - case 0x1EC2: - bufpush(0x1EC3); - break; - case 0x1EC4: - bufpush(0x1EC5); - break; - case 0x1EC6: - bufpush(0x1EC7); - break; - case 0x1EC8: - bufpush(0x1EC9); - break; - case 0x1ECA: - bufpush(0x1ECB); - break; - case 0x1ECC: - bufpush(0x1ECD); - break; - case 0x1ECE: - bufpush(0x1ECF); - break; - case 0x1ED0: - bufpush(0x1ED1); - break; - case 0x1ED2: - bufpush(0x1ED3); - break; - case 0x1ED4: - bufpush(0x1ED5); - break; - case 0x1ED6: - bufpush(0x1ED7); - break; - case 0x1ED8: - bufpush(0x1ED9); - break; - case 0x1EDA: - bufpush(0x1EDB); - break; - case 0x1EDC: - bufpush(0x1EDD); - break; - case 0x1EDE: - bufpush(0x1EDF); - break; - case 0x1EE0: - bufpush(0x1EE1); - break; - case 0x1EE2: - bufpush(0x1EE3); - break; - case 0x1EE4: - bufpush(0x1EE5); - break; - case 0x1EE6: - bufpush(0x1EE7); - break; - case 0x1EE8: - bufpush(0x1EE9); - break; - case 0x1EEA: - bufpush(0x1EEB); - break; - case 0x1EEC: - bufpush(0x1EED); - break; - case 0x1EEE: - bufpush(0x1EEF); - break; - case 0x1EF0: - bufpush(0x1EF1); - break; - case 0x1EF2: - bufpush(0x1EF3); - break; - case 0x1EF4: - bufpush(0x1EF5); - break; - case 0x1EF6: - bufpush(0x1EF7); - break; - case 0x1EF8: - bufpush(0x1EF9); - break; - case 0x1F08: - bufpush(0x1F00); - break; - case 0x1F09: - bufpush(0x1F01); - break; - case 0x1F0A: - bufpush(0x1F02); - break; - case 0x1F0B: - bufpush(0x1F03); - break; - case 0x1F0C: - bufpush(0x1F04); - break; - case 0x1F0D: - bufpush(0x1F05); - break; - case 0x1F0E: - bufpush(0x1F06); - break; - case 0x1F0F: - bufpush(0x1F07); - break; - case 0x1F18: - bufpush(0x1F10); - break; - case 0x1F19: - bufpush(0x1F11); - break; - case 0x1F1A: - bufpush(0x1F12); - break; - case 0x1F1B: - bufpush(0x1F13); - break; - case 0x1F1C: - bufpush(0x1F14); - break; - case 0x1F1D: - bufpush(0x1F15); - break; - case 0x1F28: - bufpush(0x1F20); - break; - case 0x1F29: - bufpush(0x1F21); - break; - case 0x1F2A: - bufpush(0x1F22); - break; - case 0x1F2B: - bufpush(0x1F23); - break; - case 0x1F2C: - bufpush(0x1F24); - break; - case 0x1F2D: - bufpush(0x1F25); - break; - case 0x1F2E: - bufpush(0x1F26); - break; - case 0x1F2F: - bufpush(0x1F27); - break; - case 0x1F38: - bufpush(0x1F30); - break; - case 0x1F39: - bufpush(0x1F31); - break; - case 0x1F3A: - bufpush(0x1F32); - break; - case 0x1F3B: - bufpush(0x1F33); - break; - case 0x1F3C: - bufpush(0x1F34); - break; - case 0x1F3D: - bufpush(0x1F35); - break; - case 0x1F3E: - bufpush(0x1F36); - break; - case 0x1F3F: - bufpush(0x1F37); - break; - case 0x1F48: - bufpush(0x1F40); - break; - case 0x1F49: - bufpush(0x1F41); - break; - case 0x1F4A: - bufpush(0x1F42); - break; - case 0x1F4B: - bufpush(0x1F43); - break; - case 0x1F4C: - bufpush(0x1F44); - break; - case 0x1F4D: - bufpush(0x1F45); - break; - case 0x1F50: - bufpush(0x03C5); - bufpush(0x0313); - break; - case 0x1F52: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0300); - break; - case 0x1F54: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0301); - break; - case 0x1F56: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0342); - break; - case 0x1F59: - bufpush(0x1F51); - break; - case 0x1F5B: - bufpush(0x1F53); - break; - case 0x1F5D: - bufpush(0x1F55); - break; - case 0x1F5F: - bufpush(0x1F57); - break; - case 0x1F68: - bufpush(0x1F60); - break; - case 0x1F69: - bufpush(0x1F61); - break; - case 0x1F6A: - bufpush(0x1F62); - break; - case 0x1F6B: - bufpush(0x1F63); - break; - case 0x1F6C: - bufpush(0x1F64); - break; - case 0x1F6D: - bufpush(0x1F65); - break; - case 0x1F6E: - bufpush(0x1F66); - break; - case 0x1F6F: - bufpush(0x1F67); - break; - case 0x1F80: - bufpush(0x1F00); - bufpush(0x03B9); - break; - case 0x1F81: - bufpush(0x1F01); - bufpush(0x03B9); - break; - case 0x1F82: - bufpush(0x1F02); - bufpush(0x03B9); - break; - case 0x1F83: - bufpush(0x1F03); - bufpush(0x03B9); - break; - case 0x1F84: - bufpush(0x1F04); - bufpush(0x03B9); - break; - case 0x1F85: - bufpush(0x1F05); - bufpush(0x03B9); - break; - case 0x1F86: - bufpush(0x1F06); - bufpush(0x03B9); - break; - case 0x1F87: - bufpush(0x1F07); - bufpush(0x03B9); - break; - case 0x1F88: - bufpush(0x1F00); - bufpush(0x03B9); - break; - case 0x1F89: - bufpush(0x1F01); - bufpush(0x03B9); - break; - case 0x1F8A: - bufpush(0x1F02); - bufpush(0x03B9); - break; - case 0x1F8B: - bufpush(0x1F03); - bufpush(0x03B9); - break; - case 0x1F8C: - bufpush(0x1F04); - bufpush(0x03B9); - break; - case 0x1F8D: - bufpush(0x1F05); - bufpush(0x03B9); - break; - case 0x1F8E: - bufpush(0x1F06); - bufpush(0x03B9); - break; - case 0x1F8F: - bufpush(0x1F07); - bufpush(0x03B9); - break; - case 0x1F90: - bufpush(0x1F20); - bufpush(0x03B9); - break; - case 0x1F91: - bufpush(0x1F21); - bufpush(0x03B9); - break; - case 0x1F92: - bufpush(0x1F22); - bufpush(0x03B9); - break; - case 0x1F93: - bufpush(0x1F23); - bufpush(0x03B9); - break; - case 0x1F94: - bufpush(0x1F24); - bufpush(0x03B9); - break; - case 0x1F95: - bufpush(0x1F25); - bufpush(0x03B9); - break; - case 0x1F96: - bufpush(0x1F26); - bufpush(0x03B9); - break; - case 0x1F97: - bufpush(0x1F27); - bufpush(0x03B9); - break; - case 0x1F98: - bufpush(0x1F20); - bufpush(0x03B9); - break; - case 0x1F99: - bufpush(0x1F21); - bufpush(0x03B9); - break; - case 0x1F9A: - bufpush(0x1F22); - bufpush(0x03B9); - break; - case 0x1F9B: - bufpush(0x1F23); - bufpush(0x03B9); - break; - case 0x1F9C: - bufpush(0x1F24); - bufpush(0x03B9); - break; - case 0x1F9D: - bufpush(0x1F25); - bufpush(0x03B9); - break; - case 0x1F9E: - bufpush(0x1F26); - bufpush(0x03B9); - break; - case 0x1F9F: - bufpush(0x1F27); - bufpush(0x03B9); - break; - case 0x1FA0: - bufpush(0x1F60); - bufpush(0x03B9); - break; - case 0x1FA1: - bufpush(0x1F61); - bufpush(0x03B9); - break; - case 0x1FA2: - bufpush(0x1F62); - bufpush(0x03B9); - break; - case 0x1FA3: - bufpush(0x1F63); - bufpush(0x03B9); - break; - case 0x1FA4: - bufpush(0x1F64); - bufpush(0x03B9); - break; - case 0x1FA5: - bufpush(0x1F65); - bufpush(0x03B9); - break; - case 0x1FA6: - bufpush(0x1F66); - bufpush(0x03B9); - break; - case 0x1FA7: - bufpush(0x1F67); - bufpush(0x03B9); - break; - case 0x1FA8: - bufpush(0x1F60); - bufpush(0x03B9); - break; - case 0x1FA9: - bufpush(0x1F61); - bufpush(0x03B9); - break; - case 0x1FAA: - bufpush(0x1F62); - bufpush(0x03B9); - break; - case 0x1FAB: - bufpush(0x1F63); - bufpush(0x03B9); - break; - case 0x1FAC: - bufpush(0x1F64); - bufpush(0x03B9); - break; - case 0x1FAD: - bufpush(0x1F65); - bufpush(0x03B9); - break; - case 0x1FAE: - bufpush(0x1F66); - bufpush(0x03B9); - break; - case 0x1FAF: - bufpush(0x1F67); - bufpush(0x03B9); - break; - case 0x1FB2: - bufpush(0x1F70); - bufpush(0x03B9); - break; - case 0x1FB3: - bufpush(0x03B1); - bufpush(0x03B9); - break; - case 0x1FB4: - bufpush(0x03AC); - bufpush(0x03B9); - break; - case 0x1FB6: - bufpush(0x03B1); - bufpush(0x0342); - break; - case 0x1FB7: - bufpush(0x03B1); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FB8: - bufpush(0x1FB0); - break; - case 0x1FB9: - bufpush(0x1FB1); - break; - case 0x1FBA: - bufpush(0x1F70); - break; - case 0x1FBB: - bufpush(0x1F71); - break; - case 0x1FBC: - bufpush(0x03B1); - bufpush(0x03B9); - break; - case 0x1FBE: - bufpush(0x03B9); - break; - case 0x1FC2: - bufpush(0x1F74); - bufpush(0x03B9); - break; - case 0x1FC3: - bufpush(0x03B7); - bufpush(0x03B9); - break; - case 0x1FC4: - bufpush(0x03AE); - bufpush(0x03B9); - break; - case 0x1FC6: - bufpush(0x03B7); - bufpush(0x0342); - break; - case 0x1FC7: - bufpush(0x03B7); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FC8: - bufpush(0x1F72); - break; - case 0x1FC9: - bufpush(0x1F73); - break; - case 0x1FCA: - bufpush(0x1F74); - break; - case 0x1FCB: - bufpush(0x1F75); - break; - case 0x1FCC: - bufpush(0x03B7); - bufpush(0x03B9); - break; - case 0x1FD2: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0300); - break; - case 0x1FD3: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x1FD6: - bufpush(0x03B9); - bufpush(0x0342); - break; - case 0x1FD7: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0342); - break; - case 0x1FD8: - bufpush(0x1FD0); - break; - case 0x1FD9: - bufpush(0x1FD1); - break; - case 0x1FDA: - bufpush(0x1F76); - break; - case 0x1FDB: - bufpush(0x1F77); - break; - case 0x1FE2: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0300); - break; - case 0x1FE3: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x1FE4: - bufpush(0x03C1); - bufpush(0x0313); - break; - case 0x1FE6: - bufpush(0x03C5); - bufpush(0x0342); - break; - case 0x1FE7: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0342); - break; - case 0x1FE8: - bufpush(0x1FE0); - break; - case 0x1FE9: - bufpush(0x1FE1); - break; - case 0x1FEA: - bufpush(0x1F7A); - break; - case 0x1FEB: - bufpush(0x1F7B); - break; - case 0x1FEC: - bufpush(0x1FE5); - break; - case 0x1FF2: - bufpush(0x1F7C); - bufpush(0x03B9); - break; - case 0x1FF3: - bufpush(0x03C9); - bufpush(0x03B9); - break; - case 0x1FF4: - bufpush(0x03CE); - bufpush(0x03B9); - break; - case 0x1FF6: - bufpush(0x03C9); - bufpush(0x0342); - break; - case 0x1FF7: - bufpush(0x03C9); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FF8: - bufpush(0x1F78); - break; - case 0x1FF9: - bufpush(0x1F79); - break; - case 0x1FFA: - bufpush(0x1F7C); - break; - case 0x1FFB: - bufpush(0x1F7D); - break; - case 0x1FFC: - bufpush(0x03C9); - bufpush(0x03B9); - break; - case 0x2126: - bufpush(0x03C9); - break; - case 0x212A: - bufpush(0x006B); - break; - case 0x212B: - bufpush(0x00E5); - break; - case 0x2160: - bufpush(0x2170); - break; - case 0x2161: - bufpush(0x2171); - break; - case 0x2162: - bufpush(0x2172); - break; - case 0x2163: - bufpush(0x2173); - break; - case 0x2164: - bufpush(0x2174); - break; - case 0x2165: - bufpush(0x2175); - break; - case 0x2166: - bufpush(0x2176); - break; - case 0x2167: - bufpush(0x2177); - break; - case 0x2168: - bufpush(0x2178); - break; - case 0x2169: - bufpush(0x2179); - break; - case 0x216A: - bufpush(0x217A); - break; - case 0x216B: - bufpush(0x217B); - break; - case 0x216C: - bufpush(0x217C); - break; - case 0x216D: - bufpush(0x217D); - break; - case 0x216E: - bufpush(0x217E); - break; - case 0x216F: - bufpush(0x217F); - break; - case 0x24B6: - bufpush(0x24D0); - break; - case 0x24B7: - bufpush(0x24D1); - break; - case 0x24B8: - bufpush(0x24D2); - break; - case 0x24B9: - bufpush(0x24D3); - break; - case 0x24BA: - bufpush(0x24D4); - break; - case 0x24BB: - bufpush(0x24D5); - break; - case 0x24BC: - bufpush(0x24D6); - break; - case 0x24BD: - bufpush(0x24D7); - break; - case 0x24BE: - bufpush(0x24D8); - break; - case 0x24BF: - bufpush(0x24D9); - break; - case 0x24C0: - bufpush(0x24DA); - break; - case 0x24C1: - bufpush(0x24DB); - break; - case 0x24C2: - bufpush(0x24DC); - break; - case 0x24C3: - bufpush(0x24DD); - break; - case 0x24C4: - bufpush(0x24DE); - break; - case 0x24C5: - bufpush(0x24DF); - break; - case 0x24C6: - bufpush(0x24E0); - break; - case 0x24C7: - bufpush(0x24E1); - break; - case 0x24C8: - bufpush(0x24E2); - break; - case 0x24C9: - bufpush(0x24E3); - break; - case 0x24CA: - bufpush(0x24E4); - break; - case 0x24CB: - bufpush(0x24E5); - break; - case 0x24CC: - bufpush(0x24E6); - break; - case 0x24CD: - bufpush(0x24E7); - break; - case 0x24CE: - bufpush(0x24E8); - break; - case 0x24CF: - bufpush(0x24E9); - break; - case 0xFB00: - bufpush(0x0066); - bufpush(0x0066); - break; - case 0xFB01: - bufpush(0x0066); - bufpush(0x0069); - break; - case 0xFB02: - bufpush(0x0066); - bufpush(0x006C); - break; - case 0xFB03: - bufpush(0x0066); - bufpush(0x0066); - bufpush(0x0069); - break; - case 0xFB04: - bufpush(0x0066); - bufpush(0x0066); - bufpush(0x006C); - break; - case 0xFB05: - bufpush(0x0073); - bufpush(0x0074); - break; - case 0xFB06: - bufpush(0x0073); - bufpush(0x0074); - break; - case 0xFB13: - bufpush(0x0574); - bufpush(0x0576); - break; - case 0xFB14: - bufpush(0x0574); - bufpush(0x0565); - break; - case 0xFB15: - bufpush(0x0574); - bufpush(0x056B); - break; - case 0xFB16: - bufpush(0x057E); - bufpush(0x0576); - break; - case 0xFB17: - bufpush(0x0574); - bufpush(0x056D); - break; - case 0xFF21: - bufpush(0xFF41); - break; - case 0xFF22: - bufpush(0xFF42); - break; - case 0xFF23: - bufpush(0xFF43); - break; - case 0xFF24: - bufpush(0xFF44); - break; - case 0xFF25: - bufpush(0xFF45); - break; - case 0xFF26: - bufpush(0xFF46); - break; - case 0xFF27: - bufpush(0xFF47); - break; - case 0xFF28: - bufpush(0xFF48); - break; - case 0xFF29: - bufpush(0xFF49); - break; - case 0xFF2A: - bufpush(0xFF4A); - break; - case 0xFF2B: - bufpush(0xFF4B); - break; - case 0xFF2C: - bufpush(0xFF4C); - break; - case 0xFF2D: - bufpush(0xFF4D); - break; - case 0xFF2E: - bufpush(0xFF4E); - break; - case 0xFF2F: - bufpush(0xFF4F); - break; - case 0xFF30: - bufpush(0xFF50); - break; - case 0xFF31: - bufpush(0xFF51); - break; - case 0xFF32: - bufpush(0xFF52); - break; - case 0xFF33: - bufpush(0xFF53); - break; - case 0xFF34: - bufpush(0xFF54); - break; - case 0xFF35: - bufpush(0xFF55); - break; - case 0xFF36: - bufpush(0xFF56); - break; - case 0xFF37: - bufpush(0xFF57); - break; - case 0xFF38: - bufpush(0xFF58); - break; - case 0xFF39: - bufpush(0xFF59); - break; - case 0xFF3A: - bufpush(0xFF5A); - break; - case 0x10400: - bufpush(0x10428); - break; - case 0x10401: - bufpush(0x10429); - break; - case 0x10402: - bufpush(0x1042A); - break; - case 0x10403: - bufpush(0x1042B); - break; - case 0x10404: - bufpush(0x1042C); - break; - case 0x10405: - bufpush(0x1042D); - break; - case 0x10406: - bufpush(0x1042E); - break; - case 0x10407: - bufpush(0x1042F); - break; - case 0x10408: - bufpush(0x10430); - break; - case 0x10409: - bufpush(0x10431); - break; - case 0x1040A: - bufpush(0x10432); - break; - case 0x1040B: - bufpush(0x10433); - break; - case 0x1040C: - bufpush(0x10434); - break; - case 0x1040D: - bufpush(0x10435); - break; - case 0x1040E: - bufpush(0x10436); - break; - case 0x1040F: - bufpush(0x10437); - break; - case 0x10410: - bufpush(0x10438); - break; - case 0x10411: - bufpush(0x10439); - break; - case 0x10412: - bufpush(0x1043A); - break; - case 0x10413: - bufpush(0x1043B); - break; - case 0x10414: - bufpush(0x1043C); - break; - case 0x10415: - bufpush(0x1043D); - break; - case 0x10416: - bufpush(0x1043E); - break; - case 0x10417: - bufpush(0x1043F); - break; - case 0x10418: - bufpush(0x10440); - break; - case 0x10419: - bufpush(0x10441); - break; - case 0x1041A: - bufpush(0x10442); - break; - case 0x1041B: - bufpush(0x10443); - break; - case 0x1041C: - bufpush(0x10444); - break; - case 0x1041D: - bufpush(0x10445); - break; - case 0x1041E: - bufpush(0x10446); - break; - case 0x1041F: - bufpush(0x10447); - break; - case 0x10420: - bufpush(0x10448); - break; - case 0x10421: - bufpush(0x10449); - break; - case 0x10422: - bufpush(0x1044A); - break; - case 0x10423: - bufpush(0x1044B); - break; - case 0x10424: - bufpush(0x1044C); - break; - case 0x10425: - bufpush(0x1044D); - break; - default: - bufpush(c); - } diff --git a/src/case_fold_switch.inc b/src/case_fold_switch.inc new file mode 100644 index 0000000..70fdd75 --- /dev/null +++ b/src/case_fold_switch.inc @@ -0,0 +1,2637 @@ + switch (c) { + case 0x0041: + bufpush(0x0061); + break; + case 0x0042: + bufpush(0x0062); + break; + case 0x0043: + bufpush(0x0063); + break; + case 0x0044: + bufpush(0x0064); + break; + case 0x0045: + bufpush(0x0065); + break; + case 0x0046: + bufpush(0x0066); + break; + case 0x0047: + bufpush(0x0067); + break; + case 0x0048: + bufpush(0x0068); + break; + case 0x0049: + bufpush(0x0069); + break; + case 0x004A: + bufpush(0x006A); + break; + case 0x004B: + bufpush(0x006B); + break; + case 0x004C: + bufpush(0x006C); + break; + case 0x004D: + bufpush(0x006D); + break; + case 0x004E: + bufpush(0x006E); + break; + case 0x004F: + bufpush(0x006F); + break; + case 0x0050: + bufpush(0x0070); + break; + case 0x0051: + bufpush(0x0071); + break; + case 0x0052: + bufpush(0x0072); + break; + case 0x0053: + bufpush(0x0073); + break; + case 0x0054: + bufpush(0x0074); + break; + case 0x0055: + bufpush(0x0075); + break; + case 0x0056: + bufpush(0x0076); + break; + case 0x0057: + bufpush(0x0077); + break; + case 0x0058: + bufpush(0x0078); + break; + case 0x0059: + bufpush(0x0079); + break; + case 0x005A: + bufpush(0x007A); + break; + case 0x00B5: + bufpush(0x03BC); + break; + case 0x00C0: + bufpush(0x00E0); + break; + case 0x00C1: + bufpush(0x00E1); + break; + case 0x00C2: + bufpush(0x00E2); + break; + case 0x00C3: + bufpush(0x00E3); + break; + case 0x00C4: + bufpush(0x00E4); + break; + case 0x00C5: + bufpush(0x00E5); + break; + case 0x00C6: + bufpush(0x00E6); + break; + case 0x00C7: + bufpush(0x00E7); + break; + case 0x00C8: + bufpush(0x00E8); + break; + case 0x00C9: + bufpush(0x00E9); + break; + case 0x00CA: + bufpush(0x00EA); + break; + case 0x00CB: + bufpush(0x00EB); + break; + case 0x00CC: + bufpush(0x00EC); + break; + case 0x00CD: + bufpush(0x00ED); + break; + case 0x00CE: + bufpush(0x00EE); + break; + case 0x00CF: + bufpush(0x00EF); + break; + case 0x00D0: + bufpush(0x00F0); + break; + case 0x00D1: + bufpush(0x00F1); + break; + case 0x00D2: + bufpush(0x00F2); + break; + case 0x00D3: + bufpush(0x00F3); + break; + case 0x00D4: + bufpush(0x00F4); + break; + case 0x00D5: + bufpush(0x00F5); + break; + case 0x00D6: + bufpush(0x00F6); + break; + case 0x00D8: + bufpush(0x00F8); + break; + case 0x00D9: + bufpush(0x00F9); + break; + case 0x00DA: + bufpush(0x00FA); + break; + case 0x00DB: + bufpush(0x00FB); + break; + case 0x00DC: + bufpush(0x00FC); + break; + case 0x00DD: + bufpush(0x00FD); + break; + case 0x00DE: + bufpush(0x00FE); + break; + case 0x00DF: + bufpush(0x0073); + bufpush(0x0073); + break; + case 0x0100: + bufpush(0x0101); + break; + case 0x0102: + bufpush(0x0103); + break; + case 0x0104: + bufpush(0x0105); + break; + case 0x0106: + bufpush(0x0107); + break; + case 0x0108: + bufpush(0x0109); + break; + case 0x010A: + bufpush(0x010B); + break; + case 0x010C: + bufpush(0x010D); + break; + case 0x010E: + bufpush(0x010F); + break; + case 0x0110: + bufpush(0x0111); + break; + case 0x0112: + bufpush(0x0113); + break; + case 0x0114: + bufpush(0x0115); + break; + case 0x0116: + bufpush(0x0117); + break; + case 0x0118: + bufpush(0x0119); + break; + case 0x011A: + bufpush(0x011B); + break; + case 0x011C: + bufpush(0x011D); + break; + case 0x011E: + bufpush(0x011F); + break; + case 0x0120: + bufpush(0x0121); + break; + case 0x0122: + bufpush(0x0123); + break; + case 0x0124: + bufpush(0x0125); + break; + case 0x0126: + bufpush(0x0127); + break; + case 0x0128: + bufpush(0x0129); + break; + case 0x012A: + bufpush(0x012B); + break; + case 0x012C: + bufpush(0x012D); + break; + case 0x012E: + bufpush(0x012F); + break; + case 0x0130: + bufpush(0x0069); + bufpush(0x0307); + break; + case 0x0132: + bufpush(0x0133); + break; + case 0x0134: + bufpush(0x0135); + break; + case 0x0136: + bufpush(0x0137); + break; + case 0x0139: + bufpush(0x013A); + break; + case 0x013B: + bufpush(0x013C); + break; + case 0x013D: + bufpush(0x013E); + break; + case 0x013F: + bufpush(0x0140); + break; + case 0x0141: + bufpush(0x0142); + break; + case 0x0143: + bufpush(0x0144); + break; + case 0x0145: + bufpush(0x0146); + break; + case 0x0147: + bufpush(0x0148); + break; + case 0x0149: + bufpush(0x02BC); + bufpush(0x006E); + break; + case 0x014A: + bufpush(0x014B); + break; + case 0x014C: + bufpush(0x014D); + break; + case 0x014E: + bufpush(0x014F); + break; + case 0x0150: + bufpush(0x0151); + break; + case 0x0152: + bufpush(0x0153); + break; + case 0x0154: + bufpush(0x0155); + break; + case 0x0156: + bufpush(0x0157); + break; + case 0x0158: + bufpush(0x0159); + break; + case 0x015A: + bufpush(0x015B); + break; + case 0x015C: + bufpush(0x015D); + break; + case 0x015E: + bufpush(0x015F); + break; + case 0x0160: + bufpush(0x0161); + break; + case 0x0162: + bufpush(0x0163); + break; + case 0x0164: + bufpush(0x0165); + break; + case 0x0166: + bufpush(0x0167); + break; + case 0x0168: + bufpush(0x0169); + break; + case 0x016A: + bufpush(0x016B); + break; + case 0x016C: + bufpush(0x016D); + break; + case 0x016E: + bufpush(0x016F); + break; + case 0x0170: + bufpush(0x0171); + break; + case 0x0172: + bufpush(0x0173); + break; + case 0x0174: + bufpush(0x0175); + break; + case 0x0176: + bufpush(0x0177); + break; + case 0x0178: + bufpush(0x00FF); + break; + case 0x0179: + bufpush(0x017A); + break; + case 0x017B: + bufpush(0x017C); + break; + case 0x017D: + bufpush(0x017E); + break; + case 0x017F: + bufpush(0x0073); + break; + case 0x0181: + bufpush(0x0253); + break; + case 0x0182: + bufpush(0x0183); + break; + case 0x0184: + bufpush(0x0185); + break; + case 0x0186: + bufpush(0x0254); + break; + case 0x0187: + bufpush(0x0188); + break; + case 0x0189: + bufpush(0x0256); + break; + case 0x018A: + bufpush(0x0257); + break; + case 0x018B: + bufpush(0x018C); + break; + case 0x018E: + bufpush(0x01DD); + break; + case 0x018F: + bufpush(0x0259); + break; + case 0x0190: + bufpush(0x025B); + break; + case 0x0191: + bufpush(0x0192); + break; + case 0x0193: + bufpush(0x0260); + break; + case 0x0194: + bufpush(0x0263); + break; + case 0x0196: + bufpush(0x0269); + break; + case 0x0197: + bufpush(0x0268); + break; + case 0x0198: + bufpush(0x0199); + break; + case 0x019C: + bufpush(0x026F); + break; + case 0x019D: + bufpush(0x0272); + break; + case 0x019F: + bufpush(0x0275); + break; + case 0x01A0: + bufpush(0x01A1); + break; + case 0x01A2: + bufpush(0x01A3); + break; + case 0x01A4: + bufpush(0x01A5); + break; + case 0x01A6: + bufpush(0x0280); + break; + case 0x01A7: + bufpush(0x01A8); + break; + case 0x01A9: + bufpush(0x0283); + break; + case 0x01AC: + bufpush(0x01AD); + break; + case 0x01AE: + bufpush(0x0288); + break; + case 0x01AF: + bufpush(0x01B0); + break; + case 0x01B1: + bufpush(0x028A); + break; + case 0x01B2: + bufpush(0x028B); + break; + case 0x01B3: + bufpush(0x01B4); + break; + case 0x01B5: + bufpush(0x01B6); + break; + case 0x01B7: + bufpush(0x0292); + break; + case 0x01B8: + bufpush(0x01B9); + break; + case 0x01BC: + bufpush(0x01BD); + break; + case 0x01C4: + bufpush(0x01C6); + break; + case 0x01C5: + bufpush(0x01C6); + break; + case 0x01C7: + bufpush(0x01C9); + break; + case 0x01C8: + bufpush(0x01C9); + break; + case 0x01CA: + bufpush(0x01CC); + break; + case 0x01CB: + bufpush(0x01CC); + break; + case 0x01CD: + bufpush(0x01CE); + break; + case 0x01CF: + bufpush(0x01D0); + break; + case 0x01D1: + bufpush(0x01D2); + break; + case 0x01D3: + bufpush(0x01D4); + break; + case 0x01D5: + bufpush(0x01D6); + break; + case 0x01D7: + bufpush(0x01D8); + break; + case 0x01D9: + bufpush(0x01DA); + break; + case 0x01DB: + bufpush(0x01DC); + break; + case 0x01DE: + bufpush(0x01DF); + break; + case 0x01E0: + bufpush(0x01E1); + break; + case 0x01E2: + bufpush(0x01E3); + break; + case 0x01E4: + bufpush(0x01E5); + break; + case 0x01E6: + bufpush(0x01E7); + break; + case 0x01E8: + bufpush(0x01E9); + break; + case 0x01EA: + bufpush(0x01EB); + break; + case 0x01EC: + bufpush(0x01ED); + break; + case 0x01EE: + bufpush(0x01EF); + break; + case 0x01F0: + bufpush(0x006A); + bufpush(0x030C); + break; + case 0x01F1: + bufpush(0x01F3); + break; + case 0x01F2: + bufpush(0x01F3); + break; + case 0x01F4: + bufpush(0x01F5); + break; + case 0x01F6: + bufpush(0x0195); + break; + case 0x01F7: + bufpush(0x01BF); + break; + case 0x01F8: + bufpush(0x01F9); + break; + case 0x01FA: + bufpush(0x01FB); + break; + case 0x01FC: + bufpush(0x01FD); + break; + case 0x01FE: + bufpush(0x01FF); + break; + case 0x0200: + bufpush(0x0201); + break; + case 0x0202: + bufpush(0x0203); + break; + case 0x0204: + bufpush(0x0205); + break; + case 0x0206: + bufpush(0x0207); + break; + case 0x0208: + bufpush(0x0209); + break; + case 0x020A: + bufpush(0x020B); + break; + case 0x020C: + bufpush(0x020D); + break; + case 0x020E: + bufpush(0x020F); + break; + case 0x0210: + bufpush(0x0211); + break; + case 0x0212: + bufpush(0x0213); + break; + case 0x0214: + bufpush(0x0215); + break; + case 0x0216: + bufpush(0x0217); + break; + case 0x0218: + bufpush(0x0219); + break; + case 0x021A: + bufpush(0x021B); + break; + case 0x021C: + bufpush(0x021D); + break; + case 0x021E: + bufpush(0x021F); + break; + case 0x0220: + bufpush(0x019E); + break; + case 0x0222: + bufpush(0x0223); + break; + case 0x0224: + bufpush(0x0225); + break; + case 0x0226: + bufpush(0x0227); + break; + case 0x0228: + bufpush(0x0229); + break; + case 0x022A: + bufpush(0x022B); + break; + case 0x022C: + bufpush(0x022D); + break; + case 0x022E: + bufpush(0x022F); + break; + case 0x0230: + bufpush(0x0231); + break; + case 0x0232: + bufpush(0x0233); + break; + case 0x0345: + bufpush(0x03B9); + break; + case 0x0386: + bufpush(0x03AC); + break; + case 0x0388: + bufpush(0x03AD); + break; + case 0x0389: + bufpush(0x03AE); + break; + case 0x038A: + bufpush(0x03AF); + break; + case 0x038C: + bufpush(0x03CC); + break; + case 0x038E: + bufpush(0x03CD); + break; + case 0x038F: + bufpush(0x03CE); + break; + case 0x0390: + bufpush(0x03B9); + bufpush(0x0308); + bufpush(0x0301); + break; + case 0x0391: + bufpush(0x03B1); + break; + case 0x0392: + bufpush(0x03B2); + break; + case 0x0393: + bufpush(0x03B3); + break; + case 0x0394: + bufpush(0x03B4); + break; + case 0x0395: + bufpush(0x03B5); + break; + case 0x0396: + bufpush(0x03B6); + break; + case 0x0397: + bufpush(0x03B7); + break; + case 0x0398: + bufpush(0x03B8); + break; + case 0x0399: + bufpush(0x03B9); + break; + case 0x039A: + bufpush(0x03BA); + break; + case 0x039B: + bufpush(0x03BB); + break; + case 0x039C: + bufpush(0x03BC); + break; + case 0x039D: + bufpush(0x03BD); + break; + case 0x039E: + bufpush(0x03BE); + break; + case 0x039F: + bufpush(0x03BF); + break; + case 0x03A0: + bufpush(0x03C0); + break; + case 0x03A1: + bufpush(0x03C1); + break; + case 0x03A3: + bufpush(0x03C3); + break; + case 0x03A4: + bufpush(0x03C4); + break; + case 0x03A5: + bufpush(0x03C5); + break; + case 0x03A6: + bufpush(0x03C6); + break; + case 0x03A7: + bufpush(0x03C7); + break; + case 0x03A8: + bufpush(0x03C8); + break; + case 0x03A9: + bufpush(0x03C9); + break; + case 0x03AA: + bufpush(0x03CA); + break; + case 0x03AB: + bufpush(0x03CB); + break; + case 0x03B0: + bufpush(0x03C5); + bufpush(0x0308); + bufpush(0x0301); + break; + case 0x03C2: + bufpush(0x03C3); + break; + case 0x03D0: + bufpush(0x03B2); + break; + case 0x03D1: + bufpush(0x03B8); + break; + case 0x03D5: + bufpush(0x03C6); + break; + case 0x03D6: + bufpush(0x03C0); + break; + case 0x03D8: + bufpush(0x03D9); + break; + case 0x03DA: + bufpush(0x03DB); + break; + case 0x03DC: + bufpush(0x03DD); + break; + case 0x03DE: + bufpush(0x03DF); + break; + case 0x03E0: + bufpush(0x03E1); + break; + case 0x03E2: + bufpush(0x03E3); + break; + case 0x03E4: + bufpush(0x03E5); + break; + case 0x03E6: + bufpush(0x03E7); + break; + case 0x03E8: + bufpush(0x03E9); + break; + case 0x03EA: + bufpush(0x03EB); + break; + case 0x03EC: + bufpush(0x03ED); + break; + case 0x03EE: + bufpush(0x03EF); + break; + case 0x03F0: + bufpush(0x03BA); + break; + case 0x03F1: + bufpush(0x03C1); + break; + case 0x03F2: + bufpush(0x03C3); + break; + case 0x03F4: + bufpush(0x03B8); + break; + case 0x03F5: + bufpush(0x03B5); + break; + case 0x0400: + bufpush(0x0450); + break; + case 0x0401: + bufpush(0x0451); + break; + case 0x0402: + bufpush(0x0452); + break; + case 0x0403: + bufpush(0x0453); + break; + case 0x0404: + bufpush(0x0454); + break; + case 0x0405: + bufpush(0x0455); + break; + case 0x0406: + bufpush(0x0456); + break; + case 0x0407: + bufpush(0x0457); + break; + case 0x0408: + bufpush(0x0458); + break; + case 0x0409: + bufpush(0x0459); + break; + case 0x040A: + bufpush(0x045A); + break; + case 0x040B: + bufpush(0x045B); + break; + case 0x040C: + bufpush(0x045C); + break; + case 0x040D: + bufpush(0x045D); + break; + case 0x040E: + bufpush(0x045E); + break; + case 0x040F: + bufpush(0x045F); + break; + case 0x0410: + bufpush(0x0430); + break; + case 0x0411: + bufpush(0x0431); + break; + case 0x0412: + bufpush(0x0432); + break; + case 0x0413: + bufpush(0x0433); + break; + case 0x0414: + bufpush(0x0434); + break; + case 0x0415: + bufpush(0x0435); + break; + case 0x0416: + bufpush(0x0436); + break; + case 0x0417: + bufpush(0x0437); + break; + case 0x0418: + bufpush(0x0438); + break; + case 0x0419: + bufpush(0x0439); + break; + case 0x041A: + bufpush(0x043A); + break; + case 0x041B: + bufpush(0x043B); + break; + case 0x041C: + bufpush(0x043C); + break; + case 0x041D: + bufpush(0x043D); + break; + case 0x041E: + bufpush(0x043E); + break; + case 0x041F: + bufpush(0x043F); + break; + case 0x0420: + bufpush(0x0440); + break; + case 0x0421: + bufpush(0x0441); + break; + case 0x0422: + bufpush(0x0442); + break; + case 0x0423: + bufpush(0x0443); + break; + case 0x0424: + bufpush(0x0444); + break; + case 0x0425: + bufpush(0x0445); + break; + case 0x0426: + bufpush(0x0446); + break; + case 0x0427: + bufpush(0x0447); + break; + case 0x0428: + bufpush(0x0448); + break; + case 0x0429: + bufpush(0x0449); + break; + case 0x042A: + bufpush(0x044A); + break; + case 0x042B: + bufpush(0x044B); + break; + case 0x042C: + bufpush(0x044C); + break; + case 0x042D: + bufpush(0x044D); + break; + case 0x042E: + bufpush(0x044E); + break; + case 0x042F: + bufpush(0x044F); + break; + case 0x0460: + bufpush(0x0461); + break; + case 0x0462: + bufpush(0x0463); + break; + case 0x0464: + bufpush(0x0465); + break; + case 0x0466: + bufpush(0x0467); + break; + case 0x0468: + bufpush(0x0469); + break; + case 0x046A: + bufpush(0x046B); + break; + case 0x046C: + bufpush(0x046D); + break; + case 0x046E: + bufpush(0x046F); + break; + case 0x0470: + bufpush(0x0471); + break; + case 0x0472: + bufpush(0x0473); + break; + case 0x0474: + bufpush(0x0475); + break; + case 0x0476: + bufpush(0x0477); + break; + case 0x0478: + bufpush(0x0479); + break; + case 0x047A: + bufpush(0x047B); + break; + case 0x047C: + bufpush(0x047D); + break; + case 0x047E: + bufpush(0x047F); + break; + case 0x0480: + bufpush(0x0481); + break; + case 0x048A: + bufpush(0x048B); + break; + case 0x048C: + bufpush(0x048D); + break; + case 0x048E: + bufpush(0x048F); + break; + case 0x0490: + bufpush(0x0491); + break; + case 0x0492: + bufpush(0x0493); + break; + case 0x0494: + bufpush(0x0495); + break; + case 0x0496: + bufpush(0x0497); + break; + case 0x0498: + bufpush(0x0499); + break; + case 0x049A: + bufpush(0x049B); + break; + case 0x049C: + bufpush(0x049D); + break; + case 0x049E: + bufpush(0x049F); + break; + case 0x04A0: + bufpush(0x04A1); + break; + case 0x04A2: + bufpush(0x04A3); + break; + case 0x04A4: + bufpush(0x04A5); + break; + case 0x04A6: + bufpush(0x04A7); + break; + case 0x04A8: + bufpush(0x04A9); + break; + case 0x04AA: + bufpush(0x04AB); + break; + case 0x04AC: + bufpush(0x04AD); + break; + case 0x04AE: + bufpush(0x04AF); + break; + case 0x04B0: + bufpush(0x04B1); + break; + case 0x04B2: + bufpush(0x04B3); + break; + case 0x04B4: + bufpush(0x04B5); + break; + case 0x04B6: + bufpush(0x04B7); + break; + case 0x04B8: + bufpush(0x04B9); + break; + case 0x04BA: + bufpush(0x04BB); + break; + case 0x04BC: + bufpush(0x04BD); + break; + case 0x04BE: + bufpush(0x04BF); + break; + case 0x04C1: + bufpush(0x04C2); + break; + case 0x04C3: + bufpush(0x04C4); + break; + case 0x04C5: + bufpush(0x04C6); + break; + case 0x04C7: + bufpush(0x04C8); + break; + case 0x04C9: + bufpush(0x04CA); + break; + case 0x04CB: + bufpush(0x04CC); + break; + case 0x04CD: + bufpush(0x04CE); + break; + case 0x04D0: + bufpush(0x04D1); + break; + case 0x04D2: + bufpush(0x04D3); + break; + case 0x04D4: + bufpush(0x04D5); + break; + case 0x04D6: + bufpush(0x04D7); + break; + case 0x04D8: + bufpush(0x04D9); + break; + case 0x04DA: + bufpush(0x04DB); + break; + case 0x04DC: + bufpush(0x04DD); + break; + case 0x04DE: + bufpush(0x04DF); + break; + case 0x04E0: + bufpush(0x04E1); + break; + case 0x04E2: + bufpush(0x04E3); + break; + case 0x04E4: + bufpush(0x04E5); + break; + case 0x04E6: + bufpush(0x04E7); + break; + case 0x04E8: + bufpush(0x04E9); + break; + case 0x04EA: + bufpush(0x04EB); + break; + case 0x04EC: + bufpush(0x04ED); + break; + case 0x04EE: + bufpush(0x04EF); + break; + case 0x04F0: + bufpush(0x04F1); + break; + case 0x04F2: + bufpush(0x04F3); + break; + case 0x04F4: + bufpush(0x04F5); + break; + case 0x04F8: + bufpush(0x04F9); + break; + case 0x0500: + bufpush(0x0501); + break; + case 0x0502: + bufpush(0x0503); + break; + case 0x0504: + bufpush(0x0505); + break; + case 0x0506: + bufpush(0x0507); + break; + case 0x0508: + bufpush(0x0509); + break; + case 0x050A: + bufpush(0x050B); + break; + case 0x050C: + bufpush(0x050D); + break; + case 0x050E: + bufpush(0x050F); + break; + case 0x0531: + bufpush(0x0561); + break; + case 0x0532: + bufpush(0x0562); + break; + case 0x0533: + bufpush(0x0563); + break; + case 0x0534: + bufpush(0x0564); + break; + case 0x0535: + bufpush(0x0565); + break; + case 0x0536: + bufpush(0x0566); + break; + case 0x0537: + bufpush(0x0567); + break; + case 0x0538: + bufpush(0x0568); + break; + case 0x0539: + bufpush(0x0569); + break; + case 0x053A: + bufpush(0x056A); + break; + case 0x053B: + bufpush(0x056B); + break; + case 0x053C: + bufpush(0x056C); + break; + case 0x053D: + bufpush(0x056D); + break; + case 0x053E: + bufpush(0x056E); + break; + case 0x053F: + bufpush(0x056F); + break; + case 0x0540: + bufpush(0x0570); + break; + case 0x0541: + bufpush(0x0571); + break; + case 0x0542: + bufpush(0x0572); + break; + case 0x0543: + bufpush(0x0573); + break; + case 0x0544: + bufpush(0x0574); + break; + case 0x0545: + bufpush(0x0575); + break; + case 0x0546: + bufpush(0x0576); + break; + case 0x0547: + bufpush(0x0577); + break; + case 0x0548: + bufpush(0x0578); + break; + case 0x0549: + bufpush(0x0579); + break; + case 0x054A: + bufpush(0x057A); + break; + case 0x054B: + bufpush(0x057B); + break; + case 0x054C: + bufpush(0x057C); + break; + case 0x054D: + bufpush(0x057D); + break; + case 0x054E: + bufpush(0x057E); + break; + case 0x054F: + bufpush(0x057F); + break; + case 0x0550: + bufpush(0x0580); + break; + case 0x0551: + bufpush(0x0581); + break; + case 0x0552: + bufpush(0x0582); + break; + case 0x0553: + bufpush(0x0583); + break; + case 0x0554: + bufpush(0x0584); + break; + case 0x0555: + bufpush(0x0585); + break; + case 0x0556: + bufpush(0x0586); + break; + case 0x0587: + bufpush(0x0565); + bufpush(0x0582); + break; + case 0x1E00: + bufpush(0x1E01); + break; + case 0x1E02: + bufpush(0x1E03); + break; + case 0x1E04: + bufpush(0x1E05); + break; + case 0x1E06: + bufpush(0x1E07); + break; + case 0x1E08: + bufpush(0x1E09); + break; + case 0x1E0A: + bufpush(0x1E0B); + break; + case 0x1E0C: + bufpush(0x1E0D); + break; + case 0x1E0E: + bufpush(0x1E0F); + break; + case 0x1E10: + bufpush(0x1E11); + break; + case 0x1E12: + bufpush(0x1E13); + break; + case 0x1E14: + bufpush(0x1E15); + break; + case 0x1E16: + bufpush(0x1E17); + break; + case 0x1E18: + bufpush(0x1E19); + break; + case 0x1E1A: + bufpush(0x1E1B); + break; + case 0x1E1C: + bufpush(0x1E1D); + break; + case 0x1E1E: + bufpush(0x1E1F); + break; + case 0x1E20: + bufpush(0x1E21); + break; + case 0x1E22: + bufpush(0x1E23); + break; + case 0x1E24: + bufpush(0x1E25); + break; + case 0x1E26: + bufpush(0x1E27); + break; + case 0x1E28: + bufpush(0x1E29); + break; + case 0x1E2A: + bufpush(0x1E2B); + break; + case 0x1E2C: + bufpush(0x1E2D); + break; + case 0x1E2E: + bufpush(0x1E2F); + break; + case 0x1E30: + bufpush(0x1E31); + break; + case 0x1E32: + bufpush(0x1E33); + break; + case 0x1E34: + bufpush(0x1E35); + break; + case 0x1E36: + bufpush(0x1E37); + break; + case 0x1E38: + bufpush(0x1E39); + break; + case 0x1E3A: + bufpush(0x1E3B); + break; + case 0x1E3C: + bufpush(0x1E3D); + break; + case 0x1E3E: + bufpush(0x1E3F); + break; + case 0x1E40: + bufpush(0x1E41); + break; + case 0x1E42: + bufpush(0x1E43); + break; + case 0x1E44: + bufpush(0x1E45); + break; + case 0x1E46: + bufpush(0x1E47); + break; + case 0x1E48: + bufpush(0x1E49); + break; + case 0x1E4A: + bufpush(0x1E4B); + break; + case 0x1E4C: + bufpush(0x1E4D); + break; + case 0x1E4E: + bufpush(0x1E4F); + break; + case 0x1E50: + bufpush(0x1E51); + break; + case 0x1E52: + bufpush(0x1E53); + break; + case 0x1E54: + bufpush(0x1E55); + break; + case 0x1E56: + bufpush(0x1E57); + break; + case 0x1E58: + bufpush(0x1E59); + break; + case 0x1E5A: + bufpush(0x1E5B); + break; + case 0x1E5C: + bufpush(0x1E5D); + break; + case 0x1E5E: + bufpush(0x1E5F); + break; + case 0x1E60: + bufpush(0x1E61); + break; + case 0x1E62: + bufpush(0x1E63); + break; + case 0x1E64: + bufpush(0x1E65); + break; + case 0x1E66: + bufpush(0x1E67); + break; + case 0x1E68: + bufpush(0x1E69); + break; + case 0x1E6A: + bufpush(0x1E6B); + break; + case 0x1E6C: + bufpush(0x1E6D); + break; + case 0x1E6E: + bufpush(0x1E6F); + break; + case 0x1E70: + bufpush(0x1E71); + break; + case 0x1E72: + bufpush(0x1E73); + break; + case 0x1E74: + bufpush(0x1E75); + break; + case 0x1E76: + bufpush(0x1E77); + break; + case 0x1E78: + bufpush(0x1E79); + break; + case 0x1E7A: + bufpush(0x1E7B); + break; + case 0x1E7C: + bufpush(0x1E7D); + break; + case 0x1E7E: + bufpush(0x1E7F); + break; + case 0x1E80: + bufpush(0x1E81); + break; + case 0x1E82: + bufpush(0x1E83); + break; + case 0x1E84: + bufpush(0x1E85); + break; + case 0x1E86: + bufpush(0x1E87); + break; + case 0x1E88: + bufpush(0x1E89); + break; + case 0x1E8A: + bufpush(0x1E8B); + break; + case 0x1E8C: + bufpush(0x1E8D); + break; + case 0x1E8E: + bufpush(0x1E8F); + break; + case 0x1E90: + bufpush(0x1E91); + break; + case 0x1E92: + bufpush(0x1E93); + break; + case 0x1E94: + bufpush(0x1E95); + break; + case 0x1E96: + bufpush(0x0068); + bufpush(0x0331); + break; + case 0x1E97: + bufpush(0x0074); + bufpush(0x0308); + break; + case 0x1E98: + bufpush(0x0077); + bufpush(0x030A); + break; + case 0x1E99: + bufpush(0x0079); + bufpush(0x030A); + break; + case 0x1E9A: + bufpush(0x0061); + bufpush(0x02BE); + break; + case 0x1E9B: + bufpush(0x1E61); + break; + case 0x1EA0: + bufpush(0x1EA1); + break; + case 0x1EA2: + bufpush(0x1EA3); + break; + case 0x1EA4: + bufpush(0x1EA5); + break; + case 0x1EA6: + bufpush(0x1EA7); + break; + case 0x1EA8: + bufpush(0x1EA9); + break; + case 0x1EAA: + bufpush(0x1EAB); + break; + case 0x1EAC: + bufpush(0x1EAD); + break; + case 0x1EAE: + bufpush(0x1EAF); + break; + case 0x1EB0: + bufpush(0x1EB1); + break; + case 0x1EB2: + bufpush(0x1EB3); + break; + case 0x1EB4: + bufpush(0x1EB5); + break; + case 0x1EB6: + bufpush(0x1EB7); + break; + case 0x1EB8: + bufpush(0x1EB9); + break; + case 0x1EBA: + bufpush(0x1EBB); + break; + case 0x1EBC: + bufpush(0x1EBD); + break; + case 0x1EBE: + bufpush(0x1EBF); + break; + case 0x1EC0: + bufpush(0x1EC1); + break; + case 0x1EC2: + bufpush(0x1EC3); + break; + case 0x1EC4: + bufpush(0x1EC5); + break; + case 0x1EC6: + bufpush(0x1EC7); + break; + case 0x1EC8: + bufpush(0x1EC9); + break; + case 0x1ECA: + bufpush(0x1ECB); + break; + case 0x1ECC: + bufpush(0x1ECD); + break; + case 0x1ECE: + bufpush(0x1ECF); + break; + case 0x1ED0: + bufpush(0x1ED1); + break; + case 0x1ED2: + bufpush(0x1ED3); + break; + case 0x1ED4: + bufpush(0x1ED5); + break; + case 0x1ED6: + bufpush(0x1ED7); + break; + case 0x1ED8: + bufpush(0x1ED9); + break; + case 0x1EDA: + bufpush(0x1EDB); + break; + case 0x1EDC: + bufpush(0x1EDD); + break; + case 0x1EDE: + bufpush(0x1EDF); + break; + case 0x1EE0: + bufpush(0x1EE1); + break; + case 0x1EE2: + bufpush(0x1EE3); + break; + case 0x1EE4: + bufpush(0x1EE5); + break; + case 0x1EE6: + bufpush(0x1EE7); + break; + case 0x1EE8: + bufpush(0x1EE9); + break; + case 0x1EEA: + bufpush(0x1EEB); + break; + case 0x1EEC: + bufpush(0x1EED); + break; + case 0x1EEE: + bufpush(0x1EEF); + break; + case 0x1EF0: + bufpush(0x1EF1); + break; + case 0x1EF2: + bufpush(0x1EF3); + break; + case 0x1EF4: + bufpush(0x1EF5); + break; + case 0x1EF6: + bufpush(0x1EF7); + break; + case 0x1EF8: + bufpush(0x1EF9); + break; + case 0x1F08: + bufpush(0x1F00); + break; + case 0x1F09: + bufpush(0x1F01); + break; + case 0x1F0A: + bufpush(0x1F02); + break; + case 0x1F0B: + bufpush(0x1F03); + break; + case 0x1F0C: + bufpush(0x1F04); + break; + case 0x1F0D: + bufpush(0x1F05); + break; + case 0x1F0E: + bufpush(0x1F06); + break; + case 0x1F0F: + bufpush(0x1F07); + break; + case 0x1F18: + bufpush(0x1F10); + break; + case 0x1F19: + bufpush(0x1F11); + break; + case 0x1F1A: + bufpush(0x1F12); + break; + case 0x1F1B: + bufpush(0x1F13); + break; + case 0x1F1C: + bufpush(0x1F14); + break; + case 0x1F1D: + bufpush(0x1F15); + break; + case 0x1F28: + bufpush(0x1F20); + break; + case 0x1F29: + bufpush(0x1F21); + break; + case 0x1F2A: + bufpush(0x1F22); + break; + case 0x1F2B: + bufpush(0x1F23); + break; + case 0x1F2C: + bufpush(0x1F24); + break; + case 0x1F2D: + bufpush(0x1F25); + break; + case 0x1F2E: + bufpush(0x1F26); + break; + case 0x1F2F: + bufpush(0x1F27); + break; + case 0x1F38: + bufpush(0x1F30); + break; + case 0x1F39: + bufpush(0x1F31); + break; + case 0x1F3A: + bufpush(0x1F32); + break; + case 0x1F3B: + bufpush(0x1F33); + break; + case 0x1F3C: + bufpush(0x1F34); + break; + case 0x1F3D: + bufpush(0x1F35); + break; + case 0x1F3E: + bufpush(0x1F36); + break; + case 0x1F3F: + bufpush(0x1F37); + break; + case 0x1F48: + bufpush(0x1F40); + break; + case 0x1F49: + bufpush(0x1F41); + break; + case 0x1F4A: + bufpush(0x1F42); + break; + case 0x1F4B: + bufpush(0x1F43); + break; + case 0x1F4C: + bufpush(0x1F44); + break; + case 0x1F4D: + bufpush(0x1F45); + break; + case 0x1F50: + bufpush(0x03C5); + bufpush(0x0313); + break; + case 0x1F52: + bufpush(0x03C5); + bufpush(0x0313); + bufpush(0x0300); + break; + case 0x1F54: + bufpush(0x03C5); + bufpush(0x0313); + bufpush(0x0301); + break; + case 0x1F56: + bufpush(0x03C5); + bufpush(0x0313); + bufpush(0x0342); + break; + case 0x1F59: + bufpush(0x1F51); + break; + case 0x1F5B: + bufpush(0x1F53); + break; + case 0x1F5D: + bufpush(0x1F55); + break; + case 0x1F5F: + bufpush(0x1F57); + break; + case 0x1F68: + bufpush(0x1F60); + break; + case 0x1F69: + bufpush(0x1F61); + break; + case 0x1F6A: + bufpush(0x1F62); + break; + case 0x1F6B: + bufpush(0x1F63); + break; + case 0x1F6C: + bufpush(0x1F64); + break; + case 0x1F6D: + bufpush(0x1F65); + break; + case 0x1F6E: + bufpush(0x1F66); + break; + case 0x1F6F: + bufpush(0x1F67); + break; + case 0x1F80: + bufpush(0x1F00); + bufpush(0x03B9); + break; + case 0x1F81: + bufpush(0x1F01); + bufpush(0x03B9); + break; + case 0x1F82: + bufpush(0x1F02); + bufpush(0x03B9); + break; + case 0x1F83: + bufpush(0x1F03); + bufpush(0x03B9); + break; + case 0x1F84: + bufpush(0x1F04); + bufpush(0x03B9); + break; + case 0x1F85: + bufpush(0x1F05); + bufpush(0x03B9); + break; + case 0x1F86: + bufpush(0x1F06); + bufpush(0x03B9); + break; + case 0x1F87: + bufpush(0x1F07); + bufpush(0x03B9); + break; + case 0x1F88: + bufpush(0x1F00); + bufpush(0x03B9); + break; + case 0x1F89: + bufpush(0x1F01); + bufpush(0x03B9); + break; + case 0x1F8A: + bufpush(0x1F02); + bufpush(0x03B9); + break; + case 0x1F8B: + bufpush(0x1F03); + bufpush(0x03B9); + break; + case 0x1F8C: + bufpush(0x1F04); + bufpush(0x03B9); + break; + case 0x1F8D: + bufpush(0x1F05); + bufpush(0x03B9); + break; + case 0x1F8E: + bufpush(0x1F06); + bufpush(0x03B9); + break; + case 0x1F8F: + bufpush(0x1F07); + bufpush(0x03B9); + break; + case 0x1F90: + bufpush(0x1F20); + bufpush(0x03B9); + break; + case 0x1F91: + bufpush(0x1F21); + bufpush(0x03B9); + break; + case 0x1F92: + bufpush(0x1F22); + bufpush(0x03B9); + break; + case 0x1F93: + bufpush(0x1F23); + bufpush(0x03B9); + break; + case 0x1F94: + bufpush(0x1F24); + bufpush(0x03B9); + break; + case 0x1F95: + bufpush(0x1F25); + bufpush(0x03B9); + break; + case 0x1F96: + bufpush(0x1F26); + bufpush(0x03B9); + break; + case 0x1F97: + bufpush(0x1F27); + bufpush(0x03B9); + break; + case 0x1F98: + bufpush(0x1F20); + bufpush(0x03B9); + break; + case 0x1F99: + bufpush(0x1F21); + bufpush(0x03B9); + break; + case 0x1F9A: + bufpush(0x1F22); + bufpush(0x03B9); + break; + case 0x1F9B: + bufpush(0x1F23); + bufpush(0x03B9); + break; + case 0x1F9C: + bufpush(0x1F24); + bufpush(0x03B9); + break; + case 0x1F9D: + bufpush(0x1F25); + bufpush(0x03B9); + break; + case 0x1F9E: + bufpush(0x1F26); + bufpush(0x03B9); + break; + case 0x1F9F: + bufpush(0x1F27); + bufpush(0x03B9); + break; + case 0x1FA0: + bufpush(0x1F60); + bufpush(0x03B9); + break; + case 0x1FA1: + bufpush(0x1F61); + bufpush(0x03B9); + break; + case 0x1FA2: + bufpush(0x1F62); + bufpush(0x03B9); + break; + case 0x1FA3: + bufpush(0x1F63); + bufpush(0x03B9); + break; + case 0x1FA4: + bufpush(0x1F64); + bufpush(0x03B9); + break; + case 0x1FA5: + bufpush(0x1F65); + bufpush(0x03B9); + break; + case 0x1FA6: + bufpush(0x1F66); + bufpush(0x03B9); + break; + case 0x1FA7: + bufpush(0x1F67); + bufpush(0x03B9); + break; + case 0x1FA8: + bufpush(0x1F60); + bufpush(0x03B9); + break; + case 0x1FA9: + bufpush(0x1F61); + bufpush(0x03B9); + break; + case 0x1FAA: + bufpush(0x1F62); + bufpush(0x03B9); + break; + case 0x1FAB: + bufpush(0x1F63); + bufpush(0x03B9); + break; + case 0x1FAC: + bufpush(0x1F64); + bufpush(0x03B9); + break; + case 0x1FAD: + bufpush(0x1F65); + bufpush(0x03B9); + break; + case 0x1FAE: + bufpush(0x1F66); + bufpush(0x03B9); + break; + case 0x1FAF: + bufpush(0x1F67); + bufpush(0x03B9); + break; + case 0x1FB2: + bufpush(0x1F70); + bufpush(0x03B9); + break; + case 0x1FB3: + bufpush(0x03B1); + bufpush(0x03B9); + break; + case 0x1FB4: + bufpush(0x03AC); + bufpush(0x03B9); + break; + case 0x1FB6: + bufpush(0x03B1); + bufpush(0x0342); + break; + case 0x1FB7: + bufpush(0x03B1); + bufpush(0x0342); + bufpush(0x03B9); + break; + case 0x1FB8: + bufpush(0x1FB0); + break; + case 0x1FB9: + bufpush(0x1FB1); + break; + case 0x1FBA: + bufpush(0x1F70); + break; + case 0x1FBB: + bufpush(0x1F71); + break; + case 0x1FBC: + bufpush(0x03B1); + bufpush(0x03B9); + break; + case 0x1FBE: + bufpush(0x03B9); + break; + case 0x1FC2: + bufpush(0x1F74); + bufpush(0x03B9); + break; + case 0x1FC3: + bufpush(0x03B7); + bufpush(0x03B9); + break; + case 0x1FC4: + bufpush(0x03AE); + bufpush(0x03B9); + break; + case 0x1FC6: + bufpush(0x03B7); + bufpush(0x0342); + break; + case 0x1FC7: + bufpush(0x03B7); + bufpush(0x0342); + bufpush(0x03B9); + break; + case 0x1FC8: + bufpush(0x1F72); + break; + case 0x1FC9: + bufpush(0x1F73); + break; + case 0x1FCA: + bufpush(0x1F74); + break; + case 0x1FCB: + bufpush(0x1F75); + break; + case 0x1FCC: + bufpush(0x03B7); + bufpush(0x03B9); + break; + case 0x1FD2: + bufpush(0x03B9); + bufpush(0x0308); + bufpush(0x0300); + break; + case 0x1FD3: + bufpush(0x03B9); + bufpush(0x0308); + bufpush(0x0301); + break; + case 0x1FD6: + bufpush(0x03B9); + bufpush(0x0342); + break; + case 0x1FD7: + bufpush(0x03B9); + bufpush(0x0308); + bufpush(0x0342); + break; + case 0x1FD8: + bufpush(0x1FD0); + break; + case 0x1FD9: + bufpush(0x1FD1); + break; + case 0x1FDA: + bufpush(0x1F76); + break; + case 0x1FDB: + bufpush(0x1F77); + break; + case 0x1FE2: + bufpush(0x03C5); + bufpush(0x0308); + bufpush(0x0300); + break; + case 0x1FE3: + bufpush(0x03C5); + bufpush(0x0308); + bufpush(0x0301); + break; + case 0x1FE4: + bufpush(0x03C1); + bufpush(0x0313); + break; + case 0x1FE6: + bufpush(0x03C5); + bufpush(0x0342); + break; + case 0x1FE7: + bufpush(0x03C5); + bufpush(0x0308); + bufpush(0x0342); + break; + case 0x1FE8: + bufpush(0x1FE0); + break; + case 0x1FE9: + bufpush(0x1FE1); + break; + case 0x1FEA: + bufpush(0x1F7A); + break; + case 0x1FEB: + bufpush(0x1F7B); + break; + case 0x1FEC: + bufpush(0x1FE5); + break; + case 0x1FF2: + bufpush(0x1F7C); + bufpush(0x03B9); + break; + case 0x1FF3: + bufpush(0x03C9); + bufpush(0x03B9); + break; + case 0x1FF4: + bufpush(0x03CE); + bufpush(0x03B9); + break; + case 0x1FF6: + bufpush(0x03C9); + bufpush(0x0342); + break; + case 0x1FF7: + bufpush(0x03C9); + bufpush(0x0342); + bufpush(0x03B9); + break; + case 0x1FF8: + bufpush(0x1F78); + break; + case 0x1FF9: + bufpush(0x1F79); + break; + case 0x1FFA: + bufpush(0x1F7C); + break; + case 0x1FFB: + bufpush(0x1F7D); + break; + case 0x1FFC: + bufpush(0x03C9); + bufpush(0x03B9); + break; + case 0x2126: + bufpush(0x03C9); + break; + case 0x212A: + bufpush(0x006B); + break; + case 0x212B: + bufpush(0x00E5); + break; + case 0x2160: + bufpush(0x2170); + break; + case 0x2161: + bufpush(0x2171); + break; + case 0x2162: + bufpush(0x2172); + break; + case 0x2163: + bufpush(0x2173); + break; + case 0x2164: + bufpush(0x2174); + break; + case 0x2165: + bufpush(0x2175); + break; + case 0x2166: + bufpush(0x2176); + break; + case 0x2167: + bufpush(0x2177); + break; + case 0x2168: + bufpush(0x2178); + break; + case 0x2169: + bufpush(0x2179); + break; + case 0x216A: + bufpush(0x217A); + break; + case 0x216B: + bufpush(0x217B); + break; + case 0x216C: + bufpush(0x217C); + break; + case 0x216D: + bufpush(0x217D); + break; + case 0x216E: + bufpush(0x217E); + break; + case 0x216F: + bufpush(0x217F); + break; + case 0x24B6: + bufpush(0x24D0); + break; + case 0x24B7: + bufpush(0x24D1); + break; + case 0x24B8: + bufpush(0x24D2); + break; + case 0x24B9: + bufpush(0x24D3); + break; + case 0x24BA: + bufpush(0x24D4); + break; + case 0x24BB: + bufpush(0x24D5); + break; + case 0x24BC: + bufpush(0x24D6); + break; + case 0x24BD: + bufpush(0x24D7); + break; + case 0x24BE: + bufpush(0x24D8); + break; + case 0x24BF: + bufpush(0x24D9); + break; + case 0x24C0: + bufpush(0x24DA); + break; + case 0x24C1: + bufpush(0x24DB); + break; + case 0x24C2: + bufpush(0x24DC); + break; + case 0x24C3: + bufpush(0x24DD); + break; + case 0x24C4: + bufpush(0x24DE); + break; + case 0x24C5: + bufpush(0x24DF); + break; + case 0x24C6: + bufpush(0x24E0); + break; + case 0x24C7: + bufpush(0x24E1); + break; + case 0x24C8: + bufpush(0x24E2); + break; + case 0x24C9: + bufpush(0x24E3); + break; + case 0x24CA: + bufpush(0x24E4); + break; + case 0x24CB: + bufpush(0x24E5); + break; + case 0x24CC: + bufpush(0x24E6); + break; + case 0x24CD: + bufpush(0x24E7); + break; + case 0x24CE: + bufpush(0x24E8); + break; + case 0x24CF: + bufpush(0x24E9); + break; + case 0xFB00: + bufpush(0x0066); + bufpush(0x0066); + break; + case 0xFB01: + bufpush(0x0066); + bufpush(0x0069); + break; + case 0xFB02: + bufpush(0x0066); + bufpush(0x006C); + break; + case 0xFB03: + bufpush(0x0066); + bufpush(0x0066); + bufpush(0x0069); + break; + case 0xFB04: + bufpush(0x0066); + bufpush(0x0066); + bufpush(0x006C); + break; + case 0xFB05: + bufpush(0x0073); + bufpush(0x0074); + break; + case 0xFB06: + bufpush(0x0073); + bufpush(0x0074); + break; + case 0xFB13: + bufpush(0x0574); + bufpush(0x0576); + break; + case 0xFB14: + bufpush(0x0574); + bufpush(0x0565); + break; + case 0xFB15: + bufpush(0x0574); + bufpush(0x056B); + break; + case 0xFB16: + bufpush(0x057E); + bufpush(0x0576); + break; + case 0xFB17: + bufpush(0x0574); + bufpush(0x056D); + break; + case 0xFF21: + bufpush(0xFF41); + break; + case 0xFF22: + bufpush(0xFF42); + break; + case 0xFF23: + bufpush(0xFF43); + break; + case 0xFF24: + bufpush(0xFF44); + break; + case 0xFF25: + bufpush(0xFF45); + break; + case 0xFF26: + bufpush(0xFF46); + break; + case 0xFF27: + bufpush(0xFF47); + break; + case 0xFF28: + bufpush(0xFF48); + break; + case 0xFF29: + bufpush(0xFF49); + break; + case 0xFF2A: + bufpush(0xFF4A); + break; + case 0xFF2B: + bufpush(0xFF4B); + break; + case 0xFF2C: + bufpush(0xFF4C); + break; + case 0xFF2D: + bufpush(0xFF4D); + break; + case 0xFF2E: + bufpush(0xFF4E); + break; + case 0xFF2F: + bufpush(0xFF4F); + break; + case 0xFF30: + bufpush(0xFF50); + break; + case 0xFF31: + bufpush(0xFF51); + break; + case 0xFF32: + bufpush(0xFF52); + break; + case 0xFF33: + bufpush(0xFF53); + break; + case 0xFF34: + bufpush(0xFF54); + break; + case 0xFF35: + bufpush(0xFF55); + break; + case 0xFF36: + bufpush(0xFF56); + break; + case 0xFF37: + bufpush(0xFF57); + break; + case 0xFF38: + bufpush(0xFF58); + break; + case 0xFF39: + bufpush(0xFF59); + break; + case 0xFF3A: + bufpush(0xFF5A); + break; + case 0x10400: + bufpush(0x10428); + break; + case 0x10401: + bufpush(0x10429); + break; + case 0x10402: + bufpush(0x1042A); + break; + case 0x10403: + bufpush(0x1042B); + break; + case 0x10404: + bufpush(0x1042C); + break; + case 0x10405: + bufpush(0x1042D); + break; + case 0x10406: + bufpush(0x1042E); + break; + case 0x10407: + bufpush(0x1042F); + break; + case 0x10408: + bufpush(0x10430); + break; + case 0x10409: + bufpush(0x10431); + break; + case 0x1040A: + bufpush(0x10432); + break; + case 0x1040B: + bufpush(0x10433); + break; + case 0x1040C: + bufpush(0x10434); + break; + case 0x1040D: + bufpush(0x10435); + break; + case 0x1040E: + bufpush(0x10436); + break; + case 0x1040F: + bufpush(0x10437); + break; + case 0x10410: + bufpush(0x10438); + break; + case 0x10411: + bufpush(0x10439); + break; + case 0x10412: + bufpush(0x1043A); + break; + case 0x10413: + bufpush(0x1043B); + break; + case 0x10414: + bufpush(0x1043C); + break; + case 0x10415: + bufpush(0x1043D); + break; + case 0x10416: + bufpush(0x1043E); + break; + case 0x10417: + bufpush(0x1043F); + break; + case 0x10418: + bufpush(0x10440); + break; + case 0x10419: + bufpush(0x10441); + break; + case 0x1041A: + bufpush(0x10442); + break; + case 0x1041B: + bufpush(0x10443); + break; + case 0x1041C: + bufpush(0x10444); + break; + case 0x1041D: + bufpush(0x10445); + break; + case 0x1041E: + bufpush(0x10446); + break; + case 0x1041F: + bufpush(0x10447); + break; + case 0x10420: + bufpush(0x10448); + break; + case 0x10421: + bufpush(0x10449); + break; + case 0x10422: + bufpush(0x1044A); + break; + case 0x10423: + bufpush(0x1044B); + break; + case 0x10424: + bufpush(0x1044C); + break; + case 0x10425: + bufpush(0x1044D); + break; + default: + bufpush(c); + } diff --git a/src/casefold.c b/src/casefold.c deleted file mode 100644 index 33f18aa..0000000 --- a/src/casefold.c +++ /dev/null @@ -1,2699 +0,0 @@ -#include -#include - - - switch c { - case 0x0041: - bufpush(0x0061); - break; - case 0x0042: - bufpush(0x0062); - break; - case 0x0043: - bufpush(0x0063); - break; - case 0x0044: - bufpush(0x0064); - break; - case 0x0045: - bufpush(0x0065); - break; - case 0x0046: - bufpush(0x0066); - break; - case 0x0047: - bufpush(0x0067); - break; - case 0x0048: - bufpush(0x0068); - break; - case 0x0049: - bufpush(0x0069); - break; - case 0x0049: - bufpush(0x0131); - break; - case 0x004A: - bufpush(0x006A); - break; - case 0x004B: - bufpush(0x006B); - break; - case 0x004C: - bufpush(0x006C); - break; - case 0x004D: - bufpush(0x006D); - break; - case 0x004E: - bufpush(0x006E); - break; - case 0x004F: - bufpush(0x006F); - break; - case 0x0050: - bufpush(0x0070); - break; - case 0x0051: - bufpush(0x0071); - break; - case 0x0052: - bufpush(0x0072); - break; - case 0x0053: - bufpush(0x0073); - break; - case 0x0054: - bufpush(0x0074); - break; - case 0x0055: - bufpush(0x0075); - break; - case 0x0056: - bufpush(0x0076); - break; - case 0x0057: - bufpush(0x0077); - break; - case 0x0058: - bufpush(0x0078); - break; - case 0x0059: - bufpush(0x0079); - break; - case 0x005A: - bufpush(0x007A); - break; - case 0x00B5: - bufpush(0x03BC); - break; - case 0x00C0: - bufpush(0x00E0); - break; - case 0x00C1: - bufpush(0x00E1); - break; - case 0x00C2: - bufpush(0x00E2); - break; - case 0x00C3: - bufpush(0x00E3); - break; - case 0x00C4: - bufpush(0x00E4); - break; - case 0x00C5: - bufpush(0x00E5); - break; - case 0x00C6: - bufpush(0x00E6); - break; - case 0x00C7: - bufpush(0x00E7); - break; - case 0x00C8: - bufpush(0x00E8); - break; - case 0x00C9: - bufpush(0x00E9); - break; - case 0x00CA: - bufpush(0x00EA); - break; - case 0x00CB: - bufpush(0x00EB); - break; - case 0x00CC: - bufpush(0x00EC); - break; - case 0x00CD: - bufpush(0x00ED); - break; - case 0x00CE: - bufpush(0x00EE); - break; - case 0x00CF: - bufpush(0x00EF); - break; - case 0x00D0: - bufpush(0x00F0); - break; - case 0x00D1: - bufpush(0x00F1); - break; - case 0x00D2: - bufpush(0x00F2); - break; - case 0x00D3: - bufpush(0x00F3); - break; - case 0x00D4: - bufpush(0x00F4); - break; - case 0x00D5: - bufpush(0x00F5); - break; - case 0x00D6: - bufpush(0x00F6); - break; - case 0x00D8: - bufpush(0x00F8); - break; - case 0x00D9: - bufpush(0x00F9); - break; - case 0x00DA: - bufpush(0x00FA); - break; - case 0x00DB: - bufpush(0x00FB); - break; - case 0x00DC: - bufpush(0x00FC); - break; - case 0x00DD: - bufpush(0x00FD); - break; - case 0x00DE: - bufpush(0x00FE); - break; - case 0x00DF: - bufpush(0x0073); - bufpush(0x0073); - break; - case 0x0100: - bufpush(0x0101); - break; - case 0x0102: - bufpush(0x0103); - break; - case 0x0104: - bufpush(0x0105); - break; - case 0x0106: - bufpush(0x0107); - break; - case 0x0108: - bufpush(0x0109); - break; - case 0x010A: - bufpush(0x010B); - break; - case 0x010C: - bufpush(0x010D); - break; - case 0x010E: - bufpush(0x010F); - break; - case 0x0110: - bufpush(0x0111); - break; - case 0x0112: - bufpush(0x0113); - break; - case 0x0114: - bufpush(0x0115); - break; - case 0x0116: - bufpush(0x0117); - break; - case 0x0118: - bufpush(0x0119); - break; - case 0x011A: - bufpush(0x011B); - break; - case 0x011C: - bufpush(0x011D); - break; - case 0x011E: - bufpush(0x011F); - break; - case 0x0120: - bufpush(0x0121); - break; - case 0x0122: - bufpush(0x0123); - break; - case 0x0124: - bufpush(0x0125); - break; - case 0x0126: - bufpush(0x0127); - break; - case 0x0128: - bufpush(0x0129); - break; - case 0x012A: - bufpush(0x012B); - break; - case 0x012C: - bufpush(0x012D); - break; - case 0x012E: - bufpush(0x012F); - break; - case 0x0130: - bufpush(0x0069); - bufpush(0x0307); - break; - case 0x0130: - bufpush(0x0069); - break; - case 0x0132: - bufpush(0x0133); - break; - case 0x0134: - bufpush(0x0135); - break; - case 0x0136: - bufpush(0x0137); - break; - case 0x0139: - bufpush(0x013A); - break; - case 0x013B: - bufpush(0x013C); - break; - case 0x013D: - bufpush(0x013E); - break; - case 0x013F: - bufpush(0x0140); - break; - case 0x0141: - bufpush(0x0142); - break; - case 0x0143: - bufpush(0x0144); - break; - case 0x0145: - bufpush(0x0146); - break; - case 0x0147: - bufpush(0x0148); - break; - case 0x0149: - bufpush(0x02BC); - bufpush(0x006E); - break; - case 0x014A: - bufpush(0x014B); - break; - case 0x014C: - bufpush(0x014D); - break; - case 0x014E: - bufpush(0x014F); - break; - case 0x0150: - bufpush(0x0151); - break; - case 0x0152: - bufpush(0x0153); - break; - case 0x0154: - bufpush(0x0155); - break; - case 0x0156: - bufpush(0x0157); - break; - case 0x0158: - bufpush(0x0159); - break; - case 0x015A: - bufpush(0x015B); - break; - case 0x015C: - bufpush(0x015D); - break; - case 0x015E: - bufpush(0x015F); - break; - case 0x0160: - bufpush(0x0161); - break; - case 0x0162: - bufpush(0x0163); - break; - case 0x0164: - bufpush(0x0165); - break; - case 0x0166: - bufpush(0x0167); - break; - case 0x0168: - bufpush(0x0169); - break; - case 0x016A: - bufpush(0x016B); - break; - case 0x016C: - bufpush(0x016D); - break; - case 0x016E: - bufpush(0x016F); - break; - case 0x0170: - bufpush(0x0171); - break; - case 0x0172: - bufpush(0x0173); - break; - case 0x0174: - bufpush(0x0175); - break; - case 0x0176: - bufpush(0x0177); - break; - case 0x0178: - bufpush(0x00FF); - break; - case 0x0179: - bufpush(0x017A); - break; - case 0x017B: - bufpush(0x017C); - break; - case 0x017D: - bufpush(0x017E); - break; - case 0x017F: - bufpush(0x0073); - break; - case 0x0181: - bufpush(0x0253); - break; - case 0x0182: - bufpush(0x0183); - break; - case 0x0184: - bufpush(0x0185); - break; - case 0x0186: - bufpush(0x0254); - break; - case 0x0187: - bufpush(0x0188); - break; - case 0x0189: - bufpush(0x0256); - break; - case 0x018A: - bufpush(0x0257); - break; - case 0x018B: - bufpush(0x018C); - break; - case 0x018E: - bufpush(0x01DD); - break; - case 0x018F: - bufpush(0x0259); - break; - case 0x0190: - bufpush(0x025B); - break; - case 0x0191: - bufpush(0x0192); - break; - case 0x0193: - bufpush(0x0260); - break; - case 0x0194: - bufpush(0x0263); - break; - case 0x0196: - bufpush(0x0269); - break; - case 0x0197: - bufpush(0x0268); - break; - case 0x0198: - bufpush(0x0199); - break; - case 0x019C: - bufpush(0x026F); - break; - case 0x019D: - bufpush(0x0272); - break; - case 0x019F: - bufpush(0x0275); - break; - case 0x01A0: - bufpush(0x01A1); - break; - case 0x01A2: - bufpush(0x01A3); - break; - case 0x01A4: - bufpush(0x01A5); - break; - case 0x01A6: - bufpush(0x0280); - break; - case 0x01A7: - bufpush(0x01A8); - break; - case 0x01A9: - bufpush(0x0283); - break; - case 0x01AC: - bufpush(0x01AD); - break; - case 0x01AE: - bufpush(0x0288); - break; - case 0x01AF: - bufpush(0x01B0); - break; - case 0x01B1: - bufpush(0x028A); - break; - case 0x01B2: - bufpush(0x028B); - break; - case 0x01B3: - bufpush(0x01B4); - break; - case 0x01B5: - bufpush(0x01B6); - break; - case 0x01B7: - bufpush(0x0292); - break; - case 0x01B8: - bufpush(0x01B9); - break; - case 0x01BC: - bufpush(0x01BD); - break; - case 0x01C4: - bufpush(0x01C6); - break; - case 0x01C5: - bufpush(0x01C6); - break; - case 0x01C7: - bufpush(0x01C9); - break; - case 0x01C8: - bufpush(0x01C9); - break; - case 0x01CA: - bufpush(0x01CC); - break; - case 0x01CB: - bufpush(0x01CC); - break; - case 0x01CD: - bufpush(0x01CE); - break; - case 0x01CF: - bufpush(0x01D0); - break; - case 0x01D1: - bufpush(0x01D2); - break; - case 0x01D3: - bufpush(0x01D4); - break; - case 0x01D5: - bufpush(0x01D6); - break; - case 0x01D7: - bufpush(0x01D8); - break; - case 0x01D9: - bufpush(0x01DA); - break; - case 0x01DB: - bufpush(0x01DC); - break; - case 0x01DE: - bufpush(0x01DF); - break; - case 0x01E0: - bufpush(0x01E1); - break; - case 0x01E2: - bufpush(0x01E3); - break; - case 0x01E4: - bufpush(0x01E5); - break; - case 0x01E6: - bufpush(0x01E7); - break; - case 0x01E8: - bufpush(0x01E9); - break; - case 0x01EA: - bufpush(0x01EB); - break; - case 0x01EC: - bufpush(0x01ED); - break; - case 0x01EE: - bufpush(0x01EF); - break; - case 0x01F0: - bufpush(0x006A); - bufpush(0x030C); - break; - case 0x01F1: - bufpush(0x01F3); - break; - case 0x01F2: - bufpush(0x01F3); - break; - case 0x01F4: - bufpush(0x01F5); - break; - case 0x01F6: - bufpush(0x0195); - break; - case 0x01F7: - bufpush(0x01BF); - break; - case 0x01F8: - bufpush(0x01F9); - break; - case 0x01FA: - bufpush(0x01FB); - break; - case 0x01FC: - bufpush(0x01FD); - break; - case 0x01FE: - bufpush(0x01FF); - break; - case 0x0200: - bufpush(0x0201); - break; - case 0x0202: - bufpush(0x0203); - break; - case 0x0204: - bufpush(0x0205); - break; - case 0x0206: - bufpush(0x0207); - break; - case 0x0208: - bufpush(0x0209); - break; - case 0x020A: - bufpush(0x020B); - break; - case 0x020C: - bufpush(0x020D); - break; - case 0x020E: - bufpush(0x020F); - break; - case 0x0210: - bufpush(0x0211); - break; - case 0x0212: - bufpush(0x0213); - break; - case 0x0214: - bufpush(0x0215); - break; - case 0x0216: - bufpush(0x0217); - break; - case 0x0218: - bufpush(0x0219); - break; - case 0x021A: - bufpush(0x021B); - break; - case 0x021C: - bufpush(0x021D); - break; - case 0x021E: - bufpush(0x021F); - break; - case 0x0220: - bufpush(0x019E); - break; - case 0x0222: - bufpush(0x0223); - break; - case 0x0224: - bufpush(0x0225); - break; - case 0x0226: - bufpush(0x0227); - break; - case 0x0228: - bufpush(0x0229); - break; - case 0x022A: - bufpush(0x022B); - break; - case 0x022C: - bufpush(0x022D); - break; - case 0x022E: - bufpush(0x022F); - break; - case 0x0230: - bufpush(0x0231); - break; - case 0x0232: - bufpush(0x0233); - break; - case 0x0345: - bufpush(0x03B9); - break; - case 0x0386: - bufpush(0x03AC); - break; - case 0x0388: - bufpush(0x03AD); - break; - case 0x0389: - bufpush(0x03AE); - break; - case 0x038A: - bufpush(0x03AF); - break; - case 0x038C: - bufpush(0x03CC); - break; - case 0x038E: - bufpush(0x03CD); - break; - case 0x038F: - bufpush(0x03CE); - break; - case 0x0390: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x0391: - bufpush(0x03B1); - break; - case 0x0392: - bufpush(0x03B2); - break; - case 0x0393: - bufpush(0x03B3); - break; - case 0x0394: - bufpush(0x03B4); - break; - case 0x0395: - bufpush(0x03B5); - break; - case 0x0396: - bufpush(0x03B6); - break; - case 0x0397: - bufpush(0x03B7); - break; - case 0x0398: - bufpush(0x03B8); - break; - case 0x0399: - bufpush(0x03B9); - break; - case 0x039A: - bufpush(0x03BA); - break; - case 0x039B: - bufpush(0x03BB); - break; - case 0x039C: - bufpush(0x03BC); - break; - case 0x039D: - bufpush(0x03BD); - break; - case 0x039E: - bufpush(0x03BE); - break; - case 0x039F: - bufpush(0x03BF); - break; - case 0x03A0: - bufpush(0x03C0); - break; - case 0x03A1: - bufpush(0x03C1); - break; - case 0x03A3: - bufpush(0x03C3); - break; - case 0x03A4: - bufpush(0x03C4); - break; - case 0x03A5: - bufpush(0x03C5); - break; - case 0x03A6: - bufpush(0x03C6); - break; - case 0x03A7: - bufpush(0x03C7); - break; - case 0x03A8: - bufpush(0x03C8); - break; - case 0x03A9: - bufpush(0x03C9); - break; - case 0x03AA: - bufpush(0x03CA); - break; - case 0x03AB: - bufpush(0x03CB); - break; - case 0x03B0: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x03C2: - bufpush(0x03C3); - break; - case 0x03D0: - bufpush(0x03B2); - break; - case 0x03D1: - bufpush(0x03B8); - break; - case 0x03D5: - bufpush(0x03C6); - break; - case 0x03D6: - bufpush(0x03C0); - break; - case 0x03D8: - bufpush(0x03D9); - break; - case 0x03DA: - bufpush(0x03DB); - break; - case 0x03DC: - bufpush(0x03DD); - break; - case 0x03DE: - bufpush(0x03DF); - break; - case 0x03E0: - bufpush(0x03E1); - break; - case 0x03E2: - bufpush(0x03E3); - break; - case 0x03E4: - bufpush(0x03E5); - break; - case 0x03E6: - bufpush(0x03E7); - break; - case 0x03E8: - bufpush(0x03E9); - break; - case 0x03EA: - bufpush(0x03EB); - break; - case 0x03EC: - bufpush(0x03ED); - break; - case 0x03EE: - bufpush(0x03EF); - break; - case 0x03F0: - bufpush(0x03BA); - break; - case 0x03F1: - bufpush(0x03C1); - break; - case 0x03F2: - bufpush(0x03C3); - break; - case 0x03F4: - bufpush(0x03B8); - break; - case 0x03F5: - bufpush(0x03B5); - break; - case 0x0400: - bufpush(0x0450); - break; - case 0x0401: - bufpush(0x0451); - break; - case 0x0402: - bufpush(0x0452); - break; - case 0x0403: - bufpush(0x0453); - break; - case 0x0404: - bufpush(0x0454); - break; - case 0x0405: - bufpush(0x0455); - break; - case 0x0406: - bufpush(0x0456); - break; - case 0x0407: - bufpush(0x0457); - break; - case 0x0408: - bufpush(0x0458); - break; - case 0x0409: - bufpush(0x0459); - break; - case 0x040A: - bufpush(0x045A); - break; - case 0x040B: - bufpush(0x045B); - break; - case 0x040C: - bufpush(0x045C); - break; - case 0x040D: - bufpush(0x045D); - break; - case 0x040E: - bufpush(0x045E); - break; - case 0x040F: - bufpush(0x045F); - break; - case 0x0410: - bufpush(0x0430); - break; - case 0x0411: - bufpush(0x0431); - break; - case 0x0412: - bufpush(0x0432); - break; - case 0x0413: - bufpush(0x0433); - break; - case 0x0414: - bufpush(0x0434); - break; - case 0x0415: - bufpush(0x0435); - break; - case 0x0416: - bufpush(0x0436); - break; - case 0x0417: - bufpush(0x0437); - break; - case 0x0418: - bufpush(0x0438); - break; - case 0x0419: - bufpush(0x0439); - break; - case 0x041A: - bufpush(0x043A); - break; - case 0x041B: - bufpush(0x043B); - break; - case 0x041C: - bufpush(0x043C); - break; - case 0x041D: - bufpush(0x043D); - break; - case 0x041E: - bufpush(0x043E); - break; - case 0x041F: - bufpush(0x043F); - break; - case 0x0420: - bufpush(0x0440); - break; - case 0x0421: - bufpush(0x0441); - break; - case 0x0422: - bufpush(0x0442); - break; - case 0x0423: - bufpush(0x0443); - break; - case 0x0424: - bufpush(0x0444); - break; - case 0x0425: - bufpush(0x0445); - break; - case 0x0426: - bufpush(0x0446); - break; - case 0x0427: - bufpush(0x0447); - break; - case 0x0428: - bufpush(0x0448); - break; - case 0x0429: - bufpush(0x0449); - break; - case 0x042A: - bufpush(0x044A); - break; - case 0x042B: - bufpush(0x044B); - break; - case 0x042C: - bufpush(0x044C); - break; - case 0x042D: - bufpush(0x044D); - break; - case 0x042E: - bufpush(0x044E); - break; - case 0x042F: - bufpush(0x044F); - break; - case 0x0460: - bufpush(0x0461); - break; - case 0x0462: - bufpush(0x0463); - break; - case 0x0464: - bufpush(0x0465); - break; - case 0x0466: - bufpush(0x0467); - break; - case 0x0468: - bufpush(0x0469); - break; - case 0x046A: - bufpush(0x046B); - break; - case 0x046C: - bufpush(0x046D); - break; - case 0x046E: - bufpush(0x046F); - break; - case 0x0470: - bufpush(0x0471); - break; - case 0x0472: - bufpush(0x0473); - break; - case 0x0474: - bufpush(0x0475); - break; - case 0x0476: - bufpush(0x0477); - break; - case 0x0478: - bufpush(0x0479); - break; - case 0x047A: - bufpush(0x047B); - break; - case 0x047C: - bufpush(0x047D); - break; - case 0x047E: - bufpush(0x047F); - break; - case 0x0480: - bufpush(0x0481); - break; - case 0x048A: - bufpush(0x048B); - break; - case 0x048C: - bufpush(0x048D); - break; - case 0x048E: - bufpush(0x048F); - break; - case 0x0490: - bufpush(0x0491); - break; - case 0x0492: - bufpush(0x0493); - break; - case 0x0494: - bufpush(0x0495); - break; - case 0x0496: - bufpush(0x0497); - break; - case 0x0498: - bufpush(0x0499); - break; - case 0x049A: - bufpush(0x049B); - break; - case 0x049C: - bufpush(0x049D); - break; - case 0x049E: - bufpush(0x049F); - break; - case 0x04A0: - bufpush(0x04A1); - break; - case 0x04A2: - bufpush(0x04A3); - break; - case 0x04A4: - bufpush(0x04A5); - break; - case 0x04A6: - bufpush(0x04A7); - break; - case 0x04A8: - bufpush(0x04A9); - break; - case 0x04AA: - bufpush(0x04AB); - break; - case 0x04AC: - bufpush(0x04AD); - break; - case 0x04AE: - bufpush(0x04AF); - break; - case 0x04B0: - bufpush(0x04B1); - break; - case 0x04B2: - bufpush(0x04B3); - break; - case 0x04B4: - bufpush(0x04B5); - break; - case 0x04B6: - bufpush(0x04B7); - break; - case 0x04B8: - bufpush(0x04B9); - break; - case 0x04BA: - bufpush(0x04BB); - break; - case 0x04BC: - bufpush(0x04BD); - break; - case 0x04BE: - bufpush(0x04BF); - break; - case 0x04C1: - bufpush(0x04C2); - break; - case 0x04C3: - bufpush(0x04C4); - break; - case 0x04C5: - bufpush(0x04C6); - break; - case 0x04C7: - bufpush(0x04C8); - break; - case 0x04C9: - bufpush(0x04CA); - break; - case 0x04CB: - bufpush(0x04CC); - break; - case 0x04CD: - bufpush(0x04CE); - break; - case 0x04D0: - bufpush(0x04D1); - break; - case 0x04D2: - bufpush(0x04D3); - break; - case 0x04D4: - bufpush(0x04D5); - break; - case 0x04D6: - bufpush(0x04D7); - break; - case 0x04D8: - bufpush(0x04D9); - break; - case 0x04DA: - bufpush(0x04DB); - break; - case 0x04DC: - bufpush(0x04DD); - break; - case 0x04DE: - bufpush(0x04DF); - break; - case 0x04E0: - bufpush(0x04E1); - break; - case 0x04E2: - bufpush(0x04E3); - break; - case 0x04E4: - bufpush(0x04E5); - break; - case 0x04E6: - bufpush(0x04E7); - break; - case 0x04E8: - bufpush(0x04E9); - break; - case 0x04EA: - bufpush(0x04EB); - break; - case 0x04EC: - bufpush(0x04ED); - break; - case 0x04EE: - bufpush(0x04EF); - break; - case 0x04F0: - bufpush(0x04F1); - break; - case 0x04F2: - bufpush(0x04F3); - break; - case 0x04F4: - bufpush(0x04F5); - break; - case 0x04F8: - bufpush(0x04F9); - break; - case 0x0500: - bufpush(0x0501); - break; - case 0x0502: - bufpush(0x0503); - break; - case 0x0504: - bufpush(0x0505); - break; - case 0x0506: - bufpush(0x0507); - break; - case 0x0508: - bufpush(0x0509); - break; - case 0x050A: - bufpush(0x050B); - break; - case 0x050C: - bufpush(0x050D); - break; - case 0x050E: - bufpush(0x050F); - break; - case 0x0531: - bufpush(0x0561); - break; - case 0x0532: - bufpush(0x0562); - break; - case 0x0533: - bufpush(0x0563); - break; - case 0x0534: - bufpush(0x0564); - break; - case 0x0535: - bufpush(0x0565); - break; - case 0x0536: - bufpush(0x0566); - break; - case 0x0537: - bufpush(0x0567); - break; - case 0x0538: - bufpush(0x0568); - break; - case 0x0539: - bufpush(0x0569); - break; - case 0x053A: - bufpush(0x056A); - break; - case 0x053B: - bufpush(0x056B); - break; - case 0x053C: - bufpush(0x056C); - break; - case 0x053D: - bufpush(0x056D); - break; - case 0x053E: - bufpush(0x056E); - break; - case 0x053F: - bufpush(0x056F); - break; - case 0x0540: - bufpush(0x0570); - break; - case 0x0541: - bufpush(0x0571); - break; - case 0x0542: - bufpush(0x0572); - break; - case 0x0543: - bufpush(0x0573); - break; - case 0x0544: - bufpush(0x0574); - break; - case 0x0545: - bufpush(0x0575); - break; - case 0x0546: - bufpush(0x0576); - break; - case 0x0547: - bufpush(0x0577); - break; - case 0x0548: - bufpush(0x0578); - break; - case 0x0549: - bufpush(0x0579); - break; - case 0x054A: - bufpush(0x057A); - break; - case 0x054B: - bufpush(0x057B); - break; - case 0x054C: - bufpush(0x057C); - break; - case 0x054D: - bufpush(0x057D); - break; - case 0x054E: - bufpush(0x057E); - break; - case 0x054F: - bufpush(0x057F); - break; - case 0x0550: - bufpush(0x0580); - break; - case 0x0551: - bufpush(0x0581); - break; - case 0x0552: - bufpush(0x0582); - break; - case 0x0553: - bufpush(0x0583); - break; - case 0x0554: - bufpush(0x0584); - break; - case 0x0555: - bufpush(0x0585); - break; - case 0x0556: - bufpush(0x0586); - break; - case 0x0587: - bufpush(0x0565); - bufpush(0x0582); - break; - case 0x1E00: - bufpush(0x1E01); - break; - case 0x1E02: - bufpush(0x1E03); - break; - case 0x1E04: - bufpush(0x1E05); - break; - case 0x1E06: - bufpush(0x1E07); - break; - case 0x1E08: - bufpush(0x1E09); - break; - case 0x1E0A: - bufpush(0x1E0B); - break; - case 0x1E0C: - bufpush(0x1E0D); - break; - case 0x1E0E: - bufpush(0x1E0F); - break; - case 0x1E10: - bufpush(0x1E11); - break; - case 0x1E12: - bufpush(0x1E13); - break; - case 0x1E14: - bufpush(0x1E15); - break; - case 0x1E16: - bufpush(0x1E17); - break; - case 0x1E18: - bufpush(0x1E19); - break; - case 0x1E1A: - bufpush(0x1E1B); - break; - case 0x1E1C: - bufpush(0x1E1D); - break; - case 0x1E1E: - bufpush(0x1E1F); - break; - case 0x1E20: - bufpush(0x1E21); - break; - case 0x1E22: - bufpush(0x1E23); - break; - case 0x1E24: - bufpush(0x1E25); - break; - case 0x1E26: - bufpush(0x1E27); - break; - case 0x1E28: - bufpush(0x1E29); - break; - case 0x1E2A: - bufpush(0x1E2B); - break; - case 0x1E2C: - bufpush(0x1E2D); - break; - case 0x1E2E: - bufpush(0x1E2F); - break; - case 0x1E30: - bufpush(0x1E31); - break; - case 0x1E32: - bufpush(0x1E33); - break; - case 0x1E34: - bufpush(0x1E35); - break; - case 0x1E36: - bufpush(0x1E37); - break; - case 0x1E38: - bufpush(0x1E39); - break; - case 0x1E3A: - bufpush(0x1E3B); - break; - case 0x1E3C: - bufpush(0x1E3D); - break; - case 0x1E3E: - bufpush(0x1E3F); - break; - case 0x1E40: - bufpush(0x1E41); - break; - case 0x1E42: - bufpush(0x1E43); - break; - case 0x1E44: - bufpush(0x1E45); - break; - case 0x1E46: - bufpush(0x1E47); - break; - case 0x1E48: - bufpush(0x1E49); - break; - case 0x1E4A: - bufpush(0x1E4B); - break; - case 0x1E4C: - bufpush(0x1E4D); - break; - case 0x1E4E: - bufpush(0x1E4F); - break; - case 0x1E50: - bufpush(0x1E51); - break; - case 0x1E52: - bufpush(0x1E53); - break; - case 0x1E54: - bufpush(0x1E55); - break; - case 0x1E56: - bufpush(0x1E57); - break; - case 0x1E58: - bufpush(0x1E59); - break; - case 0x1E5A: - bufpush(0x1E5B); - break; - case 0x1E5C: - bufpush(0x1E5D); - break; - case 0x1E5E: - bufpush(0x1E5F); - break; - case 0x1E60: - bufpush(0x1E61); - break; - case 0x1E62: - bufpush(0x1E63); - break; - case 0x1E64: - bufpush(0x1E65); - break; - case 0x1E66: - bufpush(0x1E67); - break; - case 0x1E68: - bufpush(0x1E69); - break; - case 0x1E6A: - bufpush(0x1E6B); - break; - case 0x1E6C: - bufpush(0x1E6D); - break; - case 0x1E6E: - bufpush(0x1E6F); - break; - case 0x1E70: - bufpush(0x1E71); - break; - case 0x1E72: - bufpush(0x1E73); - break; - case 0x1E74: - bufpush(0x1E75); - break; - case 0x1E76: - bufpush(0x1E77); - break; - case 0x1E78: - bufpush(0x1E79); - break; - case 0x1E7A: - bufpush(0x1E7B); - break; - case 0x1E7C: - bufpush(0x1E7D); - break; - case 0x1E7E: - bufpush(0x1E7F); - break; - case 0x1E80: - bufpush(0x1E81); - break; - case 0x1E82: - bufpush(0x1E83); - break; - case 0x1E84: - bufpush(0x1E85); - break; - case 0x1E86: - bufpush(0x1E87); - break; - case 0x1E88: - bufpush(0x1E89); - break; - case 0x1E8A: - bufpush(0x1E8B); - break; - case 0x1E8C: - bufpush(0x1E8D); - break; - case 0x1E8E: - bufpush(0x1E8F); - break; - case 0x1E90: - bufpush(0x1E91); - break; - case 0x1E92: - bufpush(0x1E93); - break; - case 0x1E94: - bufpush(0x1E95); - break; - case 0x1E96: - bufpush(0x0068); - bufpush(0x0331); - break; - case 0x1E97: - bufpush(0x0074); - bufpush(0x0308); - break; - case 0x1E98: - bufpush(0x0077); - bufpush(0x030A); - break; - case 0x1E99: - bufpush(0x0079); - bufpush(0x030A); - break; - case 0x1E9A: - bufpush(0x0061); - bufpush(0x02BE); - break; - case 0x1E9B: - bufpush(0x1E61); - break; - case 0x1EA0: - bufpush(0x1EA1); - break; - case 0x1EA2: - bufpush(0x1EA3); - break; - case 0x1EA4: - bufpush(0x1EA5); - break; - case 0x1EA6: - bufpush(0x1EA7); - break; - case 0x1EA8: - bufpush(0x1EA9); - break; - case 0x1EAA: - bufpush(0x1EAB); - break; - case 0x1EAC: - bufpush(0x1EAD); - break; - case 0x1EAE: - bufpush(0x1EAF); - break; - case 0x1EB0: - bufpush(0x1EB1); - break; - case 0x1EB2: - bufpush(0x1EB3); - break; - case 0x1EB4: - bufpush(0x1EB5); - break; - case 0x1EB6: - bufpush(0x1EB7); - break; - case 0x1EB8: - bufpush(0x1EB9); - break; - case 0x1EBA: - bufpush(0x1EBB); - break; - case 0x1EBC: - bufpush(0x1EBD); - break; - case 0x1EBE: - bufpush(0x1EBF); - break; - case 0x1EC0: - bufpush(0x1EC1); - break; - case 0x1EC2: - bufpush(0x1EC3); - break; - case 0x1EC4: - bufpush(0x1EC5); - break; - case 0x1EC6: - bufpush(0x1EC7); - break; - case 0x1EC8: - bufpush(0x1EC9); - break; - case 0x1ECA: - bufpush(0x1ECB); - break; - case 0x1ECC: - bufpush(0x1ECD); - break; - case 0x1ECE: - bufpush(0x1ECF); - break; - case 0x1ED0: - bufpush(0x1ED1); - break; - case 0x1ED2: - bufpush(0x1ED3); - break; - case 0x1ED4: - bufpush(0x1ED5); - break; - case 0x1ED6: - bufpush(0x1ED7); - break; - case 0x1ED8: - bufpush(0x1ED9); - break; - case 0x1EDA: - bufpush(0x1EDB); - break; - case 0x1EDC: - bufpush(0x1EDD); - break; - case 0x1EDE: - bufpush(0x1EDF); - break; - case 0x1EE0: - bufpush(0x1EE1); - break; - case 0x1EE2: - bufpush(0x1EE3); - break; - case 0x1EE4: - bufpush(0x1EE5); - break; - case 0x1EE6: - bufpush(0x1EE7); - break; - case 0x1EE8: - bufpush(0x1EE9); - break; - case 0x1EEA: - bufpush(0x1EEB); - break; - case 0x1EEC: - bufpush(0x1EED); - break; - case 0x1EEE: - bufpush(0x1EEF); - break; - case 0x1EF0: - bufpush(0x1EF1); - break; - case 0x1EF2: - bufpush(0x1EF3); - break; - case 0x1EF4: - bufpush(0x1EF5); - break; - case 0x1EF6: - bufpush(0x1EF7); - break; - case 0x1EF8: - bufpush(0x1EF9); - break; - case 0x1F08: - bufpush(0x1F00); - break; - case 0x1F09: - bufpush(0x1F01); - break; - case 0x1F0A: - bufpush(0x1F02); - break; - case 0x1F0B: - bufpush(0x1F03); - break; - case 0x1F0C: - bufpush(0x1F04); - break; - case 0x1F0D: - bufpush(0x1F05); - break; - case 0x1F0E: - bufpush(0x1F06); - break; - case 0x1F0F: - bufpush(0x1F07); - break; - case 0x1F18: - bufpush(0x1F10); - break; - case 0x1F19: - bufpush(0x1F11); - break; - case 0x1F1A: - bufpush(0x1F12); - break; - case 0x1F1B: - bufpush(0x1F13); - break; - case 0x1F1C: - bufpush(0x1F14); - break; - case 0x1F1D: - bufpush(0x1F15); - break; - case 0x1F28: - bufpush(0x1F20); - break; - case 0x1F29: - bufpush(0x1F21); - break; - case 0x1F2A: - bufpush(0x1F22); - break; - case 0x1F2B: - bufpush(0x1F23); - break; - case 0x1F2C: - bufpush(0x1F24); - break; - case 0x1F2D: - bufpush(0x1F25); - break; - case 0x1F2E: - bufpush(0x1F26); - break; - case 0x1F2F: - bufpush(0x1F27); - break; - case 0x1F38: - bufpush(0x1F30); - break; - case 0x1F39: - bufpush(0x1F31); - break; - case 0x1F3A: - bufpush(0x1F32); - break; - case 0x1F3B: - bufpush(0x1F33); - break; - case 0x1F3C: - bufpush(0x1F34); - break; - case 0x1F3D: - bufpush(0x1F35); - break; - case 0x1F3E: - bufpush(0x1F36); - break; - case 0x1F3F: - bufpush(0x1F37); - break; - case 0x1F48: - bufpush(0x1F40); - break; - case 0x1F49: - bufpush(0x1F41); - break; - case 0x1F4A: - bufpush(0x1F42); - break; - case 0x1F4B: - bufpush(0x1F43); - break; - case 0x1F4C: - bufpush(0x1F44); - break; - case 0x1F4D: - bufpush(0x1F45); - break; - case 0x1F50: - bufpush(0x03C5); - bufpush(0x0313); - break; - case 0x1F52: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0300); - break; - case 0x1F54: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0301); - break; - case 0x1F56: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0342); - break; - case 0x1F59: - bufpush(0x1F51); - break; - case 0x1F5B: - bufpush(0x1F53); - break; - case 0x1F5D: - bufpush(0x1F55); - break; - case 0x1F5F: - bufpush(0x1F57); - break; - case 0x1F68: - bufpush(0x1F60); - break; - case 0x1F69: - bufpush(0x1F61); - break; - case 0x1F6A: - bufpush(0x1F62); - break; - case 0x1F6B: - bufpush(0x1F63); - break; - case 0x1F6C: - bufpush(0x1F64); - break; - case 0x1F6D: - bufpush(0x1F65); - break; - case 0x1F6E: - bufpush(0x1F66); - break; - case 0x1F6F: - bufpush(0x1F67); - break; - case 0x1F80: - bufpush(0x1F00); - bufpush(0x03B9); - break; - case 0x1F81: - bufpush(0x1F01); - bufpush(0x03B9); - break; - case 0x1F82: - bufpush(0x1F02); - bufpush(0x03B9); - break; - case 0x1F83: - bufpush(0x1F03); - bufpush(0x03B9); - break; - case 0x1F84: - bufpush(0x1F04); - bufpush(0x03B9); - break; - case 0x1F85: - bufpush(0x1F05); - bufpush(0x03B9); - break; - case 0x1F86: - bufpush(0x1F06); - bufpush(0x03B9); - break; - case 0x1F87: - bufpush(0x1F07); - bufpush(0x03B9); - break; - case 0x1F88: - bufpush(0x1F00); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F89: - bufpush(0x1F01); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8A: - bufpush(0x1F02); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8B: - bufpush(0x1F03); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8C: - bufpush(0x1F04); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8D: - bufpush(0x1F05); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8E: - bufpush(0x1F06); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F8F: - bufpush(0x1F07); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F90: - bufpush(0x1F20); - bufpush(0x03B9); - break; - case 0x1F91: - bufpush(0x1F21); - bufpush(0x03B9); - break; - case 0x1F92: - bufpush(0x1F22); - bufpush(0x03B9); - break; - case 0x1F93: - bufpush(0x1F23); - bufpush(0x03B9); - break; - case 0x1F94: - bufpush(0x1F24); - bufpush(0x03B9); - break; - case 0x1F95: - bufpush(0x1F25); - bufpush(0x03B9); - break; - case 0x1F96: - bufpush(0x1F26); - bufpush(0x03B9); - break; - case 0x1F97: - bufpush(0x1F27); - bufpush(0x03B9); - break; - case 0x1F98: - bufpush(0x1F20); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F99: - bufpush(0x1F21); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9A: - bufpush(0x1F22); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9B: - bufpush(0x1F23); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9C: - bufpush(0x1F24); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9D: - bufpush(0x1F25); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9E: - bufpush(0x1F26); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1F9F: - bufpush(0x1F27); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FA0: - bufpush(0x1F60); - bufpush(0x03B9); - break; - case 0x1FA1: - bufpush(0x1F61); - bufpush(0x03B9); - break; - case 0x1FA2: - bufpush(0x1F62); - bufpush(0x03B9); - break; - case 0x1FA3: - bufpush(0x1F63); - bufpush(0x03B9); - break; - case 0x1FA4: - bufpush(0x1F64); - bufpush(0x03B9); - break; - case 0x1FA5: - bufpush(0x1F65); - bufpush(0x03B9); - break; - case 0x1FA6: - bufpush(0x1F66); - bufpush(0x03B9); - break; - case 0x1FA7: - bufpush(0x1F67); - bufpush(0x03B9); - break; - case 0x1FA8: - bufpush(0x1F60); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FA9: - bufpush(0x1F61); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAA: - bufpush(0x1F62); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAB: - bufpush(0x1F63); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAC: - bufpush(0x1F64); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAD: - bufpush(0x1F65); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAE: - bufpush(0x1F66); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FAF: - bufpush(0x1F67); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FB2: - bufpush(0x1F70); - bufpush(0x03B9); - break; - case 0x1FB3: - bufpush(0x03B1); - bufpush(0x03B9); - break; - case 0x1FB4: - bufpush(0x03AC); - bufpush(0x03B9); - break; - case 0x1FB6: - bufpush(0x03B1); - bufpush(0x0342); - break; - case 0x1FB7: - bufpush(0x03B1); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FB8: - bufpush(0x1FB0); - break; - case 0x1FB9: - bufpush(0x1FB1); - break; - case 0x1FBA: - bufpush(0x1F70); - break; - case 0x1FBB: - bufpush(0x1F71); - break; - case 0x1FBC: - bufpush(0x03B1); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FBE: - bufpush(0x03B9); - break; - case 0x1FC2: - bufpush(0x1F74); - bufpush(0x03B9); - break; - case 0x1FC3: - bufpush(0x03B7); - bufpush(0x03B9); - break; - case 0x1FC4: - bufpush(0x03AE); - bufpush(0x03B9); - break; - case 0x1FC6: - bufpush(0x03B7); - bufpush(0x0342); - break; - case 0x1FC7: - bufpush(0x03B7); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FC8: - bufpush(0x1F72); - break; - case 0x1FC9: - bufpush(0x1F73); - break; - case 0x1FCA: - bufpush(0x1F74); - break; - case 0x1FCB: - bufpush(0x1F75); - break; - case 0x1FCC: - bufpush(0x03B7); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x1FD2: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0300); - break; - case 0x1FD3: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x1FD6: - bufpush(0x03B9); - bufpush(0x0342); - break; - case 0x1FD7: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0342); - break; - case 0x1FD8: - bufpush(0x1FD0); - break; - case 0x1FD9: - bufpush(0x1FD1); - break; - case 0x1FDA: - bufpush(0x1F76); - break; - case 0x1FDB: - bufpush(0x1F77); - break; - case 0x1FE2: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0300); - break; - case 0x1FE3: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x1FE4: - bufpush(0x03C1); - bufpush(0x0313); - break; - case 0x1FE6: - bufpush(0x03C5); - bufpush(0x0342); - break; - case 0x1FE7: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0342); - break; - case 0x1FE8: - bufpush(0x1FE0); - break; - case 0x1FE9: - bufpush(0x1FE1); - break; - case 0x1FEA: - bufpush(0x1F7A); - break; - case 0x1FEB: - bufpush(0x1F7B); - break; - case 0x1FEC: - bufpush(0x1FE5); - break; - case 0x1FF2: - bufpush(0x1F7C); - bufpush(0x03B9); - break; - case 0x1FF3: - bufpush(0x03C9); - bufpush(0x03B9); - break; - case 0x1FF4: - bufpush(0x03CE); - bufpush(0x03B9); - break; - case 0x1FF6: - bufpush(0x03C9); - bufpush(0x0342); - break; - case 0x1FF7: - bufpush(0x03C9); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FF8: - bufpush(0x1F78); - break; - case 0x1FF9: - bufpush(0x1F79); - break; - case 0x1FFA: - bufpush(0x1F7C); - break; - case 0x1FFB: - bufpush(0x1F7D); - break; - case 0x1FFC: - bufpush(0x03C9); - bufpush(0x03B9); - break; - case 0x: - break; - case 0x2126: - bufpush(0x03C9); - break; - case 0x212A: - bufpush(0x006B); - break; - case 0x212B: - bufpush(0x00E5); - break; - case 0x2160: - bufpush(0x2170); - break; - case 0x2161: - bufpush(0x2171); - break; - case 0x2162: - bufpush(0x2172); - break; - case 0x2163: - bufpush(0x2173); - break; - case 0x2164: - bufpush(0x2174); - break; - case 0x2165: - bufpush(0x2175); - break; - case 0x2166: - bufpush(0x2176); - break; - case 0x2167: - bufpush(0x2177); - break; - case 0x2168: - bufpush(0x2178); - break; - case 0x2169: - bufpush(0x2179); - break; - case 0x216A: - bufpush(0x217A); - break; - case 0x216B: - bufpush(0x217B); - break; - case 0x216C: - bufpush(0x217C); - break; - case 0x216D: - bufpush(0x217D); - break; - case 0x216E: - bufpush(0x217E); - break; - case 0x216F: - bufpush(0x217F); - break; - case 0x24B6: - bufpush(0x24D0); - break; - case 0x24B7: - bufpush(0x24D1); - break; - case 0x24B8: - bufpush(0x24D2); - break; - case 0x24B9: - bufpush(0x24D3); - break; - case 0x24BA: - bufpush(0x24D4); - break; - case 0x24BB: - bufpush(0x24D5); - break; - case 0x24BC: - bufpush(0x24D6); - break; - case 0x24BD: - bufpush(0x24D7); - break; - case 0x24BE: - bufpush(0x24D8); - break; - case 0x24BF: - bufpush(0x24D9); - break; - case 0x24C0: - bufpush(0x24DA); - break; - case 0x24C1: - bufpush(0x24DB); - break; - case 0x24C2: - bufpush(0x24DC); - break; - case 0x24C3: - bufpush(0x24DD); - break; - case 0x24C4: - bufpush(0x24DE); - break; - case 0x24C5: - bufpush(0x24DF); - break; - case 0x24C6: - bufpush(0x24E0); - break; - case 0x24C7: - bufpush(0x24E1); - break; - case 0x24C8: - bufpush(0x24E2); - break; - case 0x24C9: - bufpush(0x24E3); - break; - case 0x24CA: - bufpush(0x24E4); - break; - case 0x24CB: - bufpush(0x24E5); - break; - case 0x24CC: - bufpush(0x24E6); - break; - case 0x24CD: - bufpush(0x24E7); - break; - case 0x24CE: - bufpush(0x24E8); - break; - case 0x24CF: - bufpush(0x24E9); - break; - case 0xFB00: - bufpush(0x0066); - bufpush(0x0066); - break; - case 0xFB01: - bufpush(0x0066); - bufpush(0x0069); - break; - case 0xFB02: - bufpush(0x0066); - bufpush(0x006C); - break; - case 0xFB03: - bufpush(0x0066); - bufpush(0x0066); - bufpush(0x0069); - break; - case 0xFB04: - bufpush(0x0066); - bufpush(0x0066); - bufpush(0x006C); - break; - case 0xFB05: - bufpush(0x0073); - bufpush(0x0074); - break; - case 0xFB06: - bufpush(0x0073); - bufpush(0x0074); - break; - case 0xFB13: - bufpush(0x0574); - bufpush(0x0576); - break; - case 0xFB14: - bufpush(0x0574); - bufpush(0x0565); - break; - case 0xFB15: - bufpush(0x0574); - bufpush(0x056B); - break; - case 0xFB16: - bufpush(0x057E); - bufpush(0x0576); - break; - case 0xFB17: - bufpush(0x0574); - bufpush(0x056D); - break; - case 0xFF21: - bufpush(0xFF41); - break; - case 0xFF22: - bufpush(0xFF42); - break; - case 0xFF23: - bufpush(0xFF43); - break; - case 0xFF24: - bufpush(0xFF44); - break; - case 0xFF25: - bufpush(0xFF45); - break; - case 0xFF26: - bufpush(0xFF46); - break; - case 0xFF27: - bufpush(0xFF47); - break; - case 0xFF28: - bufpush(0xFF48); - break; - case 0xFF29: - bufpush(0xFF49); - break; - case 0xFF2A: - bufpush(0xFF4A); - break; - case 0xFF2B: - bufpush(0xFF4B); - break; - case 0xFF2C: - bufpush(0xFF4C); - break; - case 0xFF2D: - bufpush(0xFF4D); - break; - case 0xFF2E: - bufpush(0xFF4E); - break; - case 0xFF2F: - bufpush(0xFF4F); - break; - case 0xFF30: - bufpush(0xFF50); - break; - case 0xFF31: - bufpush(0xFF51); - break; - case 0xFF32: - bufpush(0xFF52); - break; - case 0xFF33: - bufpush(0xFF53); - break; - case 0xFF34: - bufpush(0xFF54); - break; - case 0xFF35: - bufpush(0xFF55); - break; - case 0xFF36: - bufpush(0xFF56); - break; - case 0xFF37: - bufpush(0xFF57); - break; - case 0xFF38: - bufpush(0xFF58); - break; - case 0xFF39: - bufpush(0xFF59); - break; - case 0xFF3A: - bufpush(0xFF5A); - break; - case 0x10400: - bufpush(0x10428); - break; - case 0x10401: - bufpush(0x10429); - break; - case 0x10402: - bufpush(0x1042A); - break; - case 0x10403: - bufpush(0x1042B); - break; - case 0x10404: - bufpush(0x1042C); - break; - case 0x10405: - bufpush(0x1042D); - break; - case 0x10406: - bufpush(0x1042E); - break; - case 0x10407: - bufpush(0x1042F); - break; - case 0x10408: - bufpush(0x10430); - break; - case 0x10409: - bufpush(0x10431); - break; - case 0x1040A: - bufpush(0x10432); - break; - case 0x1040B: - bufpush(0x10433); - break; - case 0x1040C: - bufpush(0x10434); - break; - case 0x1040D: - bufpush(0x10435); - break; - case 0x1040E: - bufpush(0x10436); - break; - case 0x1040F: - bufpush(0x10437); - break; - case 0x10410: - bufpush(0x10438); - break; - case 0x10411: - bufpush(0x10439); - break; - case 0x10412: - bufpush(0x1043A); - break; - case 0x10413: - bufpush(0x1043B); - break; - case 0x10414: - bufpush(0x1043C); - break; - case 0x10415: - bufpush(0x1043D); - break; - case 0x10416: - bufpush(0x1043E); - break; - case 0x10417: - bufpush(0x1043F); - break; - case 0x10418: - bufpush(0x10440); - break; - case 0x10419: - bufpush(0x10441); - break; - case 0x1041A: - bufpush(0x10442); - break; - case 0x1041B: - bufpush(0x10443); - break; - case 0x1041C: - bufpush(0x10444); - break; - case 0x1041D: - bufpush(0x10445); - break; - case 0x1041E: - bufpush(0x10446); - break; - case 0x1041F: - bufpush(0x10447); - break; - case 0x10420: - bufpush(0x10448); - break; - case 0x10421: - bufpush(0x10449); - break; - case 0x10422: - bufpush(0x1044A); - break; - case 0x10423: - bufpush(0x1044B); - break; - case 0x10424: - bufpush(0x1044C); - break; - case 0x10425: - bufpush(0x1044D); - break; - } diff --git a/src/detab.c b/src/detab.c deleted file mode 100644 index e03fcf7..0000000 --- a/src/detab.c +++ /dev/null @@ -1,48 +0,0 @@ -#include "bstrlib.h" - -// UTF-8 aware detab: assumes s has no newlines, or only a final newline. -// Return 0 on success, BSTR_ERR if invalid UTF-8. -extern int bdetab(bstring s, int utf8) -{ - unsigned char c; - int pos = 0; // a count of characters - int byte = 0; // a count of bytes - int high_chars_to_skip = 0; - int numspaces = 0; - while ((c = bchar(s, byte))) { - if (utf8 && high_chars_to_skip > 0) { - if (c >= 0x80) { - high_chars_to_skip--; - byte++; - } else { - return BSTR_ERR; // invalid utf-8 - } - } else if (c == '\t') { - bdelete(s, byte, 1); // delete tab character - numspaces = 4 - (pos % 4); - binsertch(s, byte, numspaces, ' '); - byte += numspaces; - pos += numspaces; - } else if (c <= 0x80 || !utf8) { - byte++; - pos++; - } else { // multibyte utf8 sequences - if (c >> 1 == 0176) { - high_chars_to_skip = 5; - } else if (c >> 2 == 076) { - high_chars_to_skip = 4; - } else if (c >> 3 == 036) { - high_chars_to_skip = 3; - } else if (c >> 4 == 016) { - high_chars_to_skip = 2; - } else if (c >> 5 == 06) { - high_chars_to_skip = 1; - } else { - return BSTR_ERR; // invalid utf-8 - } - pos++; - byte++; - } - } - return 0; -} diff --git a/src/getopt.c b/src/getopt.c deleted file mode 100644 index 321dd9f..0000000 --- a/src/getopt.c +++ /dev/null @@ -1,199 +0,0 @@ -/* $Id: getopt.c 4022 2008-03-31 06:11:07Z rra $ - * - * Replacement implementation of getopt. - * - * This is a replacement implementation for getopt based on the my_getopt - * distribution by Benjamin Sittler. Only the getopt interface is included, - * since remctl doesn't use GNU long options, and the code has been rearranged - * and reworked somewhat to fit with the remctl coding style. - * - * Copyright 1997, 2000, 2001, 2002 Benjamin Sittler - * Copyright 2008 Russ Allbery - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include - -/* - * If we're running the test suite, rename getopt and the global variables to - * avoid conflicts with the system version. - */ -#if TESTING -# define getopt test_getopt -int test_getopt(int, char **, const char *); -# define optind test_optind -# define opterr test_opterr -# define optopt test_optopt -# define optarg test_optarg -#endif - -/* Initialize global interface variables. */ -int optind = 1; -int opterr = 1; -int optopt = 0; -char *optarg = NULL; - -/* - * This is the plain old UNIX getopt, with GNU-style extensions. If you're - * porting some piece of UNIX software, this is all you need. It supports - * GNU-style permutation and optional arguments, but does not support the GNU - * -W extension. - * - * This function is not re-entrant or thread-safe, has static variables, and - * generally isn't a great interface, but normally you only call it once. - */ -int -getopt(int argc, char *argv[], const char *optstring) -{ - const char *p; - size_t offset = 0; - char mode = '\0'; - int colon_mode = 0; - int option = -1; - - /* Holds the current position in the parameter being parsed. */ - static int charind = 0; - - /* - * By default, getopt permutes argv as it scans and leaves all non-options - * at the end. This can be changed with the first character of optstring - * or the environment variable POSIXLY_CORRECT. With a first character of - * '+' or when POSIXLY_CORRECT is set, option processing stops at the - * first non-option. If the first character is '-', each non-option argv - * element is handled as if it were the argument of an option with - * character code 1. mode holds this character. - * - * After the optional leading '+' and '-', optstring may contain ':'. If - * present, missing arguments return ':' instead of '?'. colon_mode holds - * this setting. - */ - if (getenv("POSIXLY_CORRECT") != NULL) { - mode = '+'; - colon_mode = '+'; - } else { - if (optstring[offset] == '+' || optstring[offset] == '-') { - mode = optstring[offset]; - offset++; - } - if (optstring[offset] == ':') { - colon_mode = 1; - offset++; - } - } - - /* - * charind holds where we left off. If it's set, we were in the middle - * of an argv element; if not, we pick up with the next element of - * optind. - */ - optarg = NULL; - if (charind == 0) { - if (optind >= argc) - option = -1; - else if (strcmp(argv[optind], "--") == 0) { - optind++; - option = -1; - } else if (argv[optind][0] != '-' || argv[optind][1] == '\0') { - char *tmp; - int i, j, k, end; - - if (mode == '+') - option = -1; - else if (mode == '-') { - optarg = argv[optind]; - optind++; - option = 1; - } else { - for (i = optind + 1, j = optind; i < argc; i++) - if ((argv[i][0] == '-') && (argv[i][1] != '\0')) { - optind = i; - option = getopt(argc, argv, optstring); - while (i > j) { - --i; - tmp = argv[i]; - end = (charind == 0) ? optind - 1 : optind; - for (k = i; k + 1 <= end; k++) { - argv[k] = argv[k + 1]; - } - argv[end] = tmp; - --optind; - } - break; - } - if (i == argc) - option = -1; - } - return option; - } else { - charind = 1; - } - } - if (charind != 0) { - optopt = argv[optind][charind]; - for (p = optstring + offset; *p != '\0'; p++) - if (optopt == *p) { - p++; - if (*p == ':') { - if (argv[optind][charind + 1] != '\0') { - optarg = &argv[optind][charind + 1]; - optind++; - charind = 0; - } else { - p++; - if (*p != ':') { - charind = 0; - optind++; - if (optind >= argc) { - if (opterr) - fprintf(stderr, "%s: option requires" - " an argument -- %c\n", argv[0], - optopt); - option = colon_mode ? ':' : '?'; - goto done; - } else { - optarg = argv[optind]; - optind++; - } - } - } - } - option = optopt; - } - if (option == -1) { - if (opterr) - fprintf(stderr, "%s: illegal option -- %c\n", argv[0], optopt); - option = '?'; - } - } - -done: - if (charind != 0) { - charind++; - if (argv[optind][charind] == '\0') { - optind++; - charind = 0; - } - } - if (optind > argc) - optind = argc; - return option; -} diff --git a/src/inlines.c b/src/inlines.c index f75c846..4ff45ad 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -2,133 +2,154 @@ #include #include #include -#include "bstrlib.h" +#include + #include "stmd.h" #include "uthash.h" #include "debug.h" #include "scanners.h" #include "utf8.h" +typedef struct Subject { + const gh_buf *buffer; + int pos; + reference** reference_map; + int label_nestlevel; +} subject; + +reference* lookup_reference(reference** refmap, chunk *label); +reference* make_reference(chunk *label, chunk *url, chunk *title); + +static unsigned char *clean_url(chunk *url); +static unsigned char *clean_title(chunk *title); + +inline static unsigned char *chunk_to_cstr(chunk *c); +inline static void chunk_free(chunk *c); +inline static void chunk_trim(chunk *c); + +inline static chunk chunk_literal(const char *data); +inline static chunk chunk_buf_detach(gh_buf *buf); +inline static chunk chunk_buf(const gh_buf *buf, int pos, int len); + +static inl *parse_chunk_inlines(chunk *chunk, reference** refmap); +static inl *parse_inlines_while(subject* subj, int (*f)(subject*)); +static int parse_inline(subject* subj, inl ** last); + extern void free_reference(reference *ref) { - bdestroy(ref->label); - bdestroy(ref->url); - bdestroy(ref->title); - free(ref); + free(ref->label); + free(ref->url); + free(ref->title); + free(ref); } extern void free_reference_map(reference **refmap) { - /* free the hash table contents */ - reference *s; - reference *tmp; - if (refmap != NULL) { - HASH_ITER(hh, *refmap, s, tmp) { - HASH_DEL(*refmap, s); - free_reference(s); - } - free(refmap); - } + /* free the hash table contents */ + reference *s; + reference *tmp; + if (refmap != NULL) { + HASH_ITER(hh, *refmap, s, tmp) { + HASH_DEL(*refmap, s); + free_reference(s); + } + free(refmap); + } } // normalize reference: collapse internal whitespace to single space, // remove leading/trailing whitespace, case fold -static bstring normalize_reference(bstring s) -{ - bstring normalized = case_fold(s); - int pos = 0; - int startpos; - char c; - while ((c = bchar(normalized, pos))) { - if (isspace(c)) { - startpos = pos; - // skip til next non-space - pos++; - while (isspace(bchar(s, pos))) { - pos++; - } - bdelete(normalized, startpos, pos - startpos); - binsertch(normalized, startpos, 1, ' '); - pos = startpos + 1; - } - pos++; - } - btrimws(normalized); - return normalized; +static unsigned char *normalize_reference(chunk *ref) +{ + gh_buf normalized = GH_BUF_INIT; + int r, w; + + utf8proc_case_fold(&normalized, ref->data, ref->len); + gh_buf_trim(&normalized); + + for (r = 0, w = 0; r < normalized.size; ++r) { + if (r && gh_buf_at(&normalized, r - 1) == ' ') { + while (gh_buf_at(&normalized, r) == ' ') + r++; + } + + normalized.ptr[w++] = normalized.ptr[r]; + } + + return gh_buf_detach(&normalized); } // Returns reference if refmap contains a reference with matching // label, otherwise NULL. -extern reference* lookup_reference(reference** refmap, bstring lab) +extern reference* lookup_reference(reference** refmap, chunk *label) { - reference * ref = NULL; - bstring label = normalize_reference(lab); - if (refmap != NULL) { - HASH_FIND_STR(*refmap, (char*) label->data, ref); - } - bdestroy(label); - return ref; + reference *ref = NULL; + unsigned char *norm = normalize_reference(label); + if (refmap != NULL) { + HASH_FIND_STR(*refmap, (char*)norm, ref); + } + free(label); + return ref; } -extern reference* make_reference(bstring label, bstring url, bstring title) +extern reference* make_reference(chunk *label, chunk *url, chunk *title) { - reference * ref; - ref = malloc(sizeof(reference)); - ref->label = normalize_reference(label); - ref->url = bstrcpy(url); - ref->title = bstrcpy(title); - return ref; + reference *ref; + ref = malloc(sizeof(reference)); + ref->label = normalize_reference(label); + ref->url = clean_url(url); + ref->title = clean_title(title); + return ref; } extern void add_reference(reference** refmap, reference* ref) { - reference * t = NULL; - HASH_FIND(hh, *refmap, (char*) ref->label->data, - (unsigned) blength(ref->label), t); - if (t == NULL) { - HASH_ADD_KEYPTR(hh, *refmap, (char*) ref->label->data, - (unsigned) blength(ref->label), ref); - } else { - free_reference(ref); // we free this now since it won't be in the refmap - } + reference * t = NULL; + HASH_FIND(hh, *refmap, (char*)ref->label, (unsigned)strlen(ref->label), t); + + if (t == NULL) { + HASH_ADD_KEYPTR(hh, *refmap, (char*)ref->label, (unsigned)strlen(ref->label), ref); + } else { + free_reference(ref); // we free this now since it won't be in the refmap + } } // Create an inline with a linkable string value. -inline static inl* make_linkable(int t, inl* label, bstring url, bstring title) +inline static inl* make_linkable(int t, inl* label, chunk url, chunk title) { - inl* e = (inl*) malloc(sizeof(inl)); - e->tag = t; - e->content.linkable.label = label; - e->content.linkable.url = url; - e->content.linkable.title = title; - e->next = NULL; - return e; + inl* e = (inl*) malloc(sizeof(inl)); + e->tag = t; + e->content.linkable.label = label; + e->content.linkable.url = chunk_to_cstr(&url); + e->content.linkable.title = chunk_to_cstr(&title); + e->next = NULL; + return e; } inline static inl* make_inlines(int t, inl* contents) { - inl* e = (inl*) malloc(sizeof(inl)); - e->tag = t; - e->content.inlines = contents; - e->next = NULL; - return e; + inl* e = (inl*) malloc(sizeof(inl)); + e->tag = t; + e->content.inlines = contents; + e->next = NULL; + return e; } // Create an inline with a literal string value. -inline static inl* make_literal(int t, bstring s) +inline static inl* make_literal(int t, chunk s) { - inl* e = (inl*) malloc(sizeof(inl)); - e->tag = t; - e->content.literal = s; - e->next = NULL; - return e; + inl* e = (inl*) malloc(sizeof(inl)); + e->tag = t; + e->content.literal = s; + e->next = NULL; + return e; } // Create an inline with no value. inline static inl* make_simple(int t) { - inl* e = (inl*) malloc(sizeof(inl)); - e->tag = t; - e->next = NULL; - return e; + inl* e = (inl*) malloc(sizeof(inl)); + e->tag = t; + e->next = NULL; + return e; } // Macros for creating various kinds of inlines. @@ -139,113 +160,157 @@ inline static inl* make_simple(int t) #define make_linebreak() make_simple(linebreak) #define make_softbreak() make_simple(softbreak) #define make_link(label, url, title) make_linkable(link, label, url, title) -#define make_image(alt, url, title) make_linkable(image, alt, url, title) #define make_emph(contents) make_inlines(emph, contents) #define make_strong(contents) make_inlines(strong, contents) // Free an inline list. extern void free_inlines(inl* e) { - inl * next; - while (e != NULL) { - switch (e->tag){ - case str: - case raw_html: - case code: - case entity: - bdestroy(e->content.literal); - break; - case linebreak: - case softbreak: - break; - case link: - case image: - bdestroy(e->content.linkable.url); - bdestroy(e->content.linkable.title); - free_inlines(e->content.linkable.label); - break; - case emph: - case strong: - free_inlines(e->content.inlines); - break; - default: - break; - } - next = e->next; - free(e); - e = next; - } + inl * next; + while (e != NULL) { + switch (e->tag){ + case str: + case raw_html: + case code: + case entity: + chunk_free(&e->content.literal); + break; + case linebreak: + case softbreak: + break; + case link: + case image: + free(e->content.linkable.url); + free(e->content.linkable.title); + free_inlines(e->content.linkable.label); + break; + case emph: + case strong: + free_inlines(e->content.inlines); + break; + default: + break; + } + next = e->next; + free(e); + e = next; + } } // Append inline list b to the end of inline list a. // Return pointer to head of new list. inline static inl* append_inlines(inl* a, inl* b) { - if (a == NULL) { // NULL acts like an empty list - return b; - } - inl* cur = a; - while (cur->next) { - cur = cur->next; - } - cur->next = b; - return a; + if (a == NULL) { // NULL acts like an empty list + return b; + } + inl* cur = a; + while (cur->next) { + cur = cur->next; + } + cur->next = b; + return a; } // Make a 'subject' from an input string. -static subject* make_subject(bstring s, reference** refmap) +static void init_subject(subject *e, gh_buf *buffer, int input_pos, reference** refmap) { - subject* e = (subject*) malloc(sizeof(subject)); - // remove final whitespace - brtrimws(s); - e->buffer = s; - e->pos = 0; - e->label_nestlevel = 0; - e->reference_map = refmap; - return e; + e->buffer = buffer; + e->pos = input_pos; + e->label_nestlevel = 0; + e->reference_map = refmap; } inline static int isbacktick(int c) { - return (c == '`'); + return (c == '`'); +} + +inline static void chunk_free(chunk *c) +{ + if (c->alloc) + free((char *)c->data); + + c->data = NULL; + c->alloc = 0; + c->len = 0; +} + +inline static void chunk_trim(chunk *c) +{ + while (c->len && isspace(c->data[0])) { + c->data++; + c->len--; + } + + while (c->len > 0) { + if (!isspace(c->data[c->len - 1])) + break; + + c->len--; + } +} + +inline static unsigned char *chunk_to_cstr(chunk *c) +{ + unsigned char *str; + + str = malloc(c->len + 1); + memcpy(str, c->data, c->len); + str[c->len] = 0; + + return str; +} + +inline static chunk chunk_literal(const char *data) +{ + chunk c = {data, strlen(data), 0}; + return c; +} + +inline static chunk chunk_buf(const gh_buf *buf, int pos, int len) +{ + chunk c = {buf->ptr + pos, len, 0}; + return c; +} + +inline static chunk chunk_buf_detach(gh_buf *buf) +{ + chunk c; + + c.len = buf->size; + c.data = gh_buf_detach(buf); + c.alloc = 1; + + return c; } // Return the next character in the subject, without advancing. // Return 0 if at the end of the subject. -#define peek_char(subj) bchar(subj->buffer, subj->pos) +#define peek_char(subj) gh_buf_at((subj)->buffer, (subj)->pos) // Return true if there are more characters in the subject. inline static int is_eof(subject* subj) { - return (subj->pos >= blength(subj->buffer)); + return (subj->pos >= gh_buf_len(subj->buffer)); } // Advance the subject. Doesn't check for eof. -#define advance(subj) subj->pos += 1 +#define advance(subj) (subj)->pos += 1 // Take characters while a predicate holds, and return a string. -inline static bstring take_while(subject* subj, int (*f)(int)) +inline static chunk take_while(subject* subj, int (*f)(int)) { - unsigned char c; - int startpos = subj->pos; - int len = 0; - while ((c = peek_char(subj)) && (*f)(c)) { - advance(subj); - len++; - } - return bmidstr(subj->buffer, startpos, len); -} + unsigned char c; + int startpos = subj->pos; + int len = 0; -// Take one character and return a string, or NULL if eof. -inline static bstring take_one(subject* subj) -{ - int startpos = subj->pos; - if (is_eof(subj)){ - return NULL; - } else { - advance(subj); - return bmidstr(subj->buffer, startpos, 1); - } + while ((c = peek_char(subj)) && (*f)(c)) { + advance(subj); + len++; + } + + return chunk_buf(subj->buffer, startpos, len); } // Try to process a backtick code span that began with a @@ -255,381 +320,406 @@ inline static bstring take_one(subject* subj) // after the closing backticks. static int scan_to_closing_backticks(subject* subj, int openticklength) { - // read non backticks - char c; - while ((c = peek_char(subj)) && c != '`') { - advance(subj); - } - if (is_eof(subj)) { - return 0; // did not find closing ticks, return 0 - } - int numticks = 0; - while (peek_char(subj) == '`') { - advance(subj); - numticks++; - } - if (numticks != openticklength){ - return(scan_to_closing_backticks(subj, openticklength)); - } - return (subj->pos); -} - -// Destructively modify bstring, collapsing consecutive + // read non backticks + char c; + while ((c = peek_char(subj)) && c != '`') { + advance(subj); + } + if (is_eof(subj)) { + return 0; // did not find closing ticks, return 0 + } + int numticks = 0; + while (peek_char(subj) == '`') { + advance(subj); + numticks++; + } + if (numticks != openticklength){ + return(scan_to_closing_backticks(subj, openticklength)); + } + return (subj->pos); +} + +// Destructively modify string, collapsing consecutive // space and newline characters into a single space. -static int normalize_whitespace(bstring s) -{ - bool last_char_was_space = false; - int pos = 0; - char c; - while ((c = bchar(s, pos))) { - switch (c) { - case ' ': - if (last_char_was_space) { - bdelete(s, pos, 1); - } else { - pos++; - } - last_char_was_space = true; - break; - case '\n': - if (last_char_was_space) { - bdelete(s, pos, 1); - } else { - bdelete(s, pos, 1); - binsertch(s, pos, 1, ' '); - pos++; - } - last_char_was_space = true; - break; - default: - pos++; - last_char_was_space = false; - } - } - return 0; +static void normalize_whitespace(gh_buf *s) +{ + /* TODO */ +#if 0 + bool last_char_was_space = false; + int pos = 0; + char c; + while ((c = gh_buf_at(s, pos))) { + switch (c) { + case ' ': + if (last_char_was_space) { + bdelete(s, pos, 1); + } else { + pos++; + } + last_char_was_space = true; + break; + case '\n': + if (last_char_was_space) { + bdelete(s, pos, 1); + } else { + bdelete(s, pos, 1); + binsertch(s, pos, 1, ' '); + pos++; + } + last_char_was_space = true; + break; + default: + pos++; + last_char_was_space = false; + } + } +#endif } // Parse backtick code section or raw backticks, return an inline. // Assumes that the subject has a backtick at the current position. static inl* handle_backticks(subject *subj) { - bstring openticks = take_while(subj, isbacktick); - bstring result; - int ticklength = blength(openticks); - int startpos = subj->pos; - int endpos = scan_to_closing_backticks(subj, ticklength); - if (endpos == 0) { // not found - subj->pos = startpos; // rewind - return make_str(openticks); - } else { - bdestroy(openticks); - result = bmidstr(subj->buffer, startpos, endpos - startpos - ticklength); - btrimws(result); - normalize_whitespace(result); - return make_code(result); - } + chunk openticks = take_while(subj, isbacktick); + int startpos = subj->pos; + int endpos = scan_to_closing_backticks(subj, openticks.len); + + if (endpos == 0) { // not found + subj->pos = startpos; // rewind + return make_str(openticks); + } else { + gh_buf buf = GH_BUF_INIT; + + gh_buf_set(&buf, subj->buffer->ptr + startpos, endpos - startpos - openticks.len); + gh_buf_trim(&buf); + normalize_whitespace(&buf); + + return make_code(chunk_buf_detach(&buf)); + } } // Scan ***, **, or * and return number scanned, or 0. // Don't advance position. static int scan_delims(subject* subj, char c, bool * can_open, bool * can_close) { - int numdelims = 0; - char char_before, char_after; - int startpos = subj->pos; - - char_before = subj->pos == 0 ? '\n' : bchar(subj->buffer, subj->pos - 1); - while (peek_char(subj) == c) { - numdelims++; - advance(subj); - } - char_after = peek_char(subj); - *can_open = numdelims > 0 && numdelims <= 3 && !isspace(char_after); - *can_close = numdelims > 0 && numdelims <= 3 && !isspace(char_before); - if (c == '_') { - *can_open = *can_open && !isalnum(char_before); - *can_close = *can_close && !isalnum(char_after); - } - subj->pos = startpos; - return numdelims; + int numdelims = 0; + char char_before, char_after; + int startpos = subj->pos; + + char_before = subj->pos == 0 ? '\n' : gh_buf_at(subj->buffer, subj->pos - 1); + while (peek_char(subj) == c) { + numdelims++; + advance(subj); + } + char_after = peek_char(subj); + *can_open = numdelims > 0 && numdelims <= 3 && !isspace(char_after); + *can_close = numdelims > 0 && numdelims <= 3 && !isspace(char_before); + if (c == '_') { + *can_open = *can_open && !isalnum(char_before); + *can_close = *can_close && !isalnum(char_after); + } + subj->pos = startpos; + return numdelims; } // Parse strong/emph or a fallback. // Assumes the subject has '_' or '*' at the current position. static inl* handle_strong_emph(subject* subj, char c) { - bool can_open, can_close; - inl * result = NULL; - inl ** last = malloc(sizeof(inl *)); - inl * new; - inl * il; - inl * first_head = NULL; - inl * first_close = NULL; - int first_close_delims = 0; - int numdelims; - - *last = NULL; - - numdelims = scan_delims(subj, c, &can_open, &can_close); - subj->pos += numdelims; - - new = make_str(bmidstr(subj->buffer, subj->pos - numdelims, numdelims)); - *last = new; - first_head = new; - result = new; - - if (!can_open || numdelims == 0) { - goto done; - } - - switch (numdelims) { - case 1: - while (true) { - numdelims = scan_delims(subj, c, &can_open, &can_close); - if (numdelims >= 1 && can_close) { - subj->pos += 1; - first_head->tag = emph; - bdestroy(first_head->content.literal); - first_head->content.inlines = first_head->next; - first_head->next = NULL; - goto done; - } else { - if (!parse_inline(subj, last)) { - goto done; - } - } - } - break; - case 2: - while (true) { - numdelims = scan_delims(subj, c, &can_open, &can_close); - if (numdelims >= 2 && can_close) { - subj->pos += 2; - first_head->tag = strong; - bdestroy(first_head->content.literal); - first_head->content.inlines = first_head->next; - first_head->next = NULL; - goto done; - } else { - if (!parse_inline(subj, last)) { - goto done; - } - } - } - break; - case 3: - while (true) { - numdelims = scan_delims(subj, c, &can_open, &can_close); - if (can_close && numdelims >= 1 && numdelims <= 3 && - numdelims != first_close_delims) { - new = make_str(bmidstr(subj->buffer, subj->pos, numdelims)); - append_inlines(*last, new); - *last = new; - - if (first_close_delims == 1 && numdelims > 2) { - numdelims = 2; - } else if (first_close_delims == 2) { - numdelims = 1; - } else if (numdelims == 3) { - // If we opened with ***, we interpret it as ** followed by * - // giving us - numdelims = 1; - } - - subj->pos += numdelims; - if (first_close) { - first_head->tag = first_close_delims == 1 ? strong : emph; - bdestroy(first_head->content.literal); - first_head->content.inlines = - make_inlines(first_close_delims == 1 ? emph : strong, - first_head->next); - - il = first_head->next; - while (il->next && il->next != first_close) { - il = il->next; - } - il->next = NULL; - - first_head->content.inlines->next = first_close->next; - - il = first_head->content.inlines; - while (il->next && il->next != *last) { - il = il->next; - } - il->next = NULL; - free_inlines(*last); - - first_close->next = NULL; - free_inlines(first_close); - first_head->next = NULL; - goto done; - } else { - first_close = *last; - first_close_delims = numdelims; - } - } else { - if (!parse_inline(subj, last)) { - goto done; - } - } - } - break; - default: - goto done; - } - - done: - free(last); - return result; + bool can_open, can_close; + inl * result = NULL; + inl ** last = malloc(sizeof(inl *)); + inl * new; + inl * il; + inl * first_head = NULL; + inl * first_close = NULL; + int first_close_delims = 0; + int numdelims; + + *last = NULL; + + numdelims = scan_delims(subj, c, &can_open, &can_close); + subj->pos += numdelims; + + new = make_str(chunk_buf(subj->buffer, subj->pos - numdelims, numdelims)); + *last = new; + first_head = new; + result = new; + + if (!can_open || numdelims == 0) { + goto done; + } + + switch (numdelims) { + case 1: + while (true) { + numdelims = scan_delims(subj, c, &can_open, &can_close); + if (numdelims >= 1 && can_close) { + subj->pos += 1; + first_head->tag = emph; + chunk_free(&first_head->content.literal); + first_head->content.inlines = first_head->next; + first_head->next = NULL; + goto done; + } else { + if (!parse_inline(subj, last)) { + goto done; + } + } + } + break; + case 2: + while (true) { + numdelims = scan_delims(subj, c, &can_open, &can_close); + if (numdelims >= 2 && can_close) { + subj->pos += 2; + first_head->tag = strong; + chunk_free(&first_head->content.literal); + first_head->content.inlines = first_head->next; + first_head->next = NULL; + goto done; + } else { + if (!parse_inline(subj, last)) { + goto done; + } + } + } + break; + case 3: + while (true) { + numdelims = scan_delims(subj, c, &can_open, &can_close); + if (can_close && numdelims >= 1 && numdelims <= 3 && + numdelims != first_close_delims) { + new = make_str(chunk_buf(subj->buffer, subj->pos, numdelims)); + append_inlines(*last, new); + *last = new; + if (first_close_delims == 1 && numdelims > 2) { + numdelims = 2; + } else if (first_close_delims == 2) { + numdelims = 1; + } else if (numdelims == 3) { + // If we opened with ***, we interpret it as ** followed by * + // giving us + numdelims = 1; + } + subj->pos += numdelims; + if (first_close) { + first_head->tag = first_close_delims == 1 ? strong : emph; + chunk_free(&first_head->content.literal); + first_head->content.inlines = + make_inlines(first_close_delims == 1 ? emph : strong, + first_head->next); + + il = first_head->next; + while (il->next && il->next != first_close) { + il = il->next; + } + il->next = NULL; + + first_head->content.inlines->next = first_close->next; + + il = first_head->content.inlines; + while (il->next && il->next != *last) { + il = il->next; + } + il->next = NULL; + free_inlines(*last); + + first_close->next = NULL; + free_inlines(first_close); + first_head->next = NULL; + goto done; + } else { + first_close = *last; + first_close_delims = numdelims; + } + } else { + if (!parse_inline(subj, last)) { + goto done; + } + } + } + break; + default: + goto done; + } + +done: + free(last); + return result; } // Parse backslash-escape or just a backslash, returning an inline. static inl* handle_backslash(subject *subj) { - advance(subj); - unsigned char nextchar = peek_char(subj); - if (ispunct(nextchar)) { // only ascii symbols and newline can be escaped - advance(subj); - return make_str(bformat("%c", nextchar)); - } else if (nextchar == '\n') { - advance(subj); - return make_linebreak(); - } else { - return make_str(bfromcstr("\\")); - } + advance(subj); + unsigned char nextchar = peek_char(subj); + if (ispunct(nextchar)) { // only ascii symbols and newline can be escaped + advance(subj); + return make_str(chunk_buf(subj->buffer, subj->pos - 1, 1)); + } else if (nextchar == '\n') { + advance(subj); + return make_linebreak(); + } else { + return make_str(chunk_literal("\\")); + } } // Parse an entity or a regular "&" string. // Assumes the subject has an '&' character at the current position. static inl* handle_entity(subject* subj) { - int match; - inl * result; - match = scan_entity(subj->buffer, subj->pos); - if (match) { - result = make_entity(bmidstr(subj->buffer, subj->pos, match)); - subj->pos += match; - } else { - advance(subj); - result = make_str(bfromcstr("&")); - } - return result; + int match; + inl *result; + match = scan_entity(subj->buffer, subj->pos); + if (match) { + result = make_entity(chunk_buf(subj->buffer, subj->pos, match)); + subj->pos += match; + } else { + advance(subj); + result = make_str(chunk_literal("&")); + } + return result; } // Like make_str, but parses entities. // Returns an inline sequence consisting of str and entity elements. -static inl * make_str_with_entities(bstring s) -{ - inl * result = NULL; - inl * new; - int searchpos; - char c; - subject * subj = make_subject(s, NULL); - - while ((c = peek_char(subj))) { - switch (c) { - case '&': - new = handle_entity(subj); - break; - default: - searchpos = bstrchrp(subj->buffer, '&', subj->pos); - if (searchpos == BSTR_ERR) { - searchpos = blength(subj->buffer); - } - new = make_str(bmidstr(subj->buffer, subj->pos, searchpos - subj->pos)); - subj->pos = searchpos; - } - result = append_inlines(result, new); - } - free(subj); - return result; +static inl *make_str_with_entities(chunk *content) +{ + inl * result = NULL; + inl * new; + int searchpos; + char c; + subject subj; + gh_buf content_buf = GH_BUF_INIT; + + gh_buf_set(&content_buf, content->data, content->len); + init_subject(&subj, &content_buf, 0, NULL); + + while ((c = peek_char(&subj))) { + switch (c) { + case '&': + new = handle_entity(&subj); + break; + default: + searchpos = gh_buf_strchr(subj.buffer, '&', subj.pos); + if (searchpos < 0) { + searchpos = gh_buf_len(subj.buffer); + } + + new = make_str(chunk_buf(subj.buffer, subj.pos, searchpos - subj.pos)); + subj.pos = searchpos; + } + result = append_inlines(result, new); + } + + gh_buf_free(&content_buf); + return result; } // Destructively unescape a string: remove backslashes before punctuation chars. -extern int unescape(bstring url) +extern void unescape_buffer(gh_buf *buf) { - // remove backslashes before punctuation chars: - int searchpos = 0; - while ((searchpos = bstrchrp(url, '\\', searchpos)) != BSTR_ERR) { - if (ispunct(bchar(url, searchpos + 1))) { - bdelete(url, searchpos, 1); - } else { - searchpos++; - } - } - return 0; + int r, w; + + for (r = 0, w = 0; r < buf->size; ++r) { + if (buf->ptr[r] == '\\' && ispunct(buf->ptr[r + 1])) + continue; + + buf->ptr[w++] = buf->ptr[r]; + } + + gh_buf_truncate(buf, w); } // Clean a URL: remove surrounding whitespace and surrounding <>, // and remove \ that escape punctuation. -static int clean_url(bstring url) +static unsigned char *clean_url(chunk *url) { - // remove surrounding <> if any: - int urllength = blength(url); - btrimws(url); - if (bchar(url, 0) == '<' && bchar(url, urllength - 1) == '>') { - bdelete(url, 0, 1); - bdelete(url, urllength - 2, 1); - } - unescape(url); - return 0; + gh_buf buf = GH_BUF_INIT; + + chunk_trim(url); + + if (url->data[0] == '<' && url->data[url->len - 1] == '>') { + gh_buf_set(&buf, url->data + 1, url->len - 2); + } else { + gh_buf_set(&buf, url->data, url->len); + } + + unescape_buffer(&buf); + return gh_buf_detach(&buf); } // Clean a title: remove surrounding quotes and remove \ that escape punctuation. -static int clean_title(bstring title) +static unsigned char *clean_title(chunk *title) { - // remove surrounding quotes if any: - int titlelength = blength(title); - if ((bchar(title, 0) == '\'' && bchar(title, titlelength - 1) == '\'') || - (bchar(title, 0) == '(' && bchar(title, titlelength - 1) == ')') || - (bchar(title, 0) == '"' && bchar(title, titlelength - 1) == '"')) { - bdelete(title, 0, 1); - bdelete(title, titlelength - 2, 1); - } - unescape(title); - return 0; + gh_buf buf = GH_BUF_INIT; + unsigned char first = title->data[0]; + unsigned char last = title->data[title->len - 1]; + + // remove surrounding quotes if any: + if ((first == '\'' && last == '\'') || + (first == '(' && last == ')') || + (first == '"' && last == '"')) { + gh_buf_set(&buf, title->data + 1, title->len - 2); + } else { + gh_buf_set(&buf, title->data, title->len); + } + + unescape_buffer(&buf); + return gh_buf_detach(&buf); } // Parse an autolink or HTML tag. // Assumes the subject has a '<' character at the current position. static inl* handle_pointy_brace(subject* subj) { - int matchlen = 0; - bstring contents; - inl* result; - - advance(subj); // advance past first < - // first try to match a URL autolink - matchlen = scan_autolink_uri(subj->buffer, subj->pos); - if (matchlen > 0) { - contents = bmidstr(subj->buffer, subj->pos, matchlen - 1); - subj->pos += matchlen; - result = make_link(make_str_with_entities(contents), - bstrcpy(contents), bfromcstr("")); - bdestroy(contents); - return result; - } - // next try to match an email autolink - matchlen = scan_autolink_email(subj->buffer, subj->pos); - if (matchlen > 0) { - contents = bmidstr(subj->buffer, subj->pos, matchlen - 1); - subj->pos += matchlen; - result = make_link(make_str_with_entities(contents), - bformat("mailto:%s", contents->data), - bfromcstr("")); - bdestroy(contents); - return result; - } - // finally, try to match an html tag - matchlen = scan_html_tag(subj->buffer, subj->pos); - if (matchlen > 0) { - contents = bmidstr(subj->buffer, subj->pos, matchlen); - binsertch(contents, 0, 1, '<'); - subj->pos += matchlen; - return make_raw_html(contents); - } else {// if nothing matches, just return the opening <: - return make_str(bfromcstr("<")); - } + int matchlen = 0; + chunk contents; + + advance(subj); // advance past first < + + // first try to match a URL autolink + matchlen = scan_autolink_uri(subj->buffer, subj->pos); + if (matchlen > 0) { + contents = chunk_buf(subj->buffer, subj->pos, matchlen - 1); + subj->pos += matchlen; + + return make_link( + make_str_with_entities(&contents), + contents, + chunk_literal("") + ); + } + + // next try to match an email autolink + matchlen = scan_autolink_email(subj->buffer, subj->pos); + if (matchlen > 0) { + gh_buf mail_url = GH_BUF_INIT; + + contents = chunk_buf(subj->buffer, subj->pos, matchlen - 1); + subj->pos += matchlen; + + gh_buf_puts(&mail_url, "mailto:"); + gh_buf_put(&mail_url, contents.data, contents.len); + + return make_link( + make_str_with_entities(&contents), + chunk_buf_detach(&mail_url), + chunk_literal("") + ); + } + + // finally, try to match an html tag + matchlen = scan_html_tag(subj->buffer, subj->pos); + if (matchlen > 0) { + contents = chunk_buf(subj->buffer, subj->pos - 1, matchlen + 1); + subj->pos += matchlen; + return make_raw_html(contents); + } + + // if nothing matches, just return the opening <: + return make_str(chunk_literal("<")); } // Parse a link label. Returns 1 if successful. @@ -641,366 +731,381 @@ static inl* handle_pointy_brace(subject* subj) // markers. So, 2 below contains a link while 1 does not: // 1. [a link `with a ](/url)` character // 2. [a link *with emphasized ](/url) text* -static int link_label(subject* subj, bstring* raw_label) -{ - int nestlevel = 0; - inl* tmp = NULL; - bstring raw; - int startpos = subj->pos; - if (subj->label_nestlevel) { - // if we've already checked to the end of the subject - // for a label, even with a different starting [, we - // know we won't find one here and we can just return. - // Note: nestlevel 1 would be: [foo [bar] - // nestlevel 2 would be: [foo [bar [baz] - subj->label_nestlevel--; - return 0; - } - advance(subj); // advance past [ - char c; - while ((c = peek_char(subj)) && (c != ']' || nestlevel > 0)) { - switch (c) { - case '`': - tmp = handle_backticks(subj); - free_inlines(tmp); - break; - case '<': - tmp = handle_pointy_brace(subj); - free_inlines(tmp); - break; - case '[': // nested [] - nestlevel++; - advance(subj); - break; - case ']': // nested [] - nestlevel--; - advance(subj); - break; - case '\\': - advance(subj); - if (ispunct(peek_char(subj))) { - advance(subj); - } - break; - default: - advance(subj); - } - } - if (c == ']') { - if (raw_label != NULL) { - raw = bmidstr(subj->buffer, startpos + 1, subj->pos - (startpos + 1)); - *raw_label = raw; - } - subj->label_nestlevel = 0; - advance(subj); // advance past ] - return 1; - } else { - if (c == 0) { - subj->label_nestlevel = nestlevel; - } - subj->pos = startpos; // rewind - return 0; - } +static int link_label(subject* subj, chunk *raw_label) +{ + int nestlevel = 0; + inl* tmp = NULL; + int startpos = subj->pos; + + if (subj->label_nestlevel) { + // if we've already checked to the end of the subject + // for a label, even with a different starting [, we + // know we won't find one here and we can just return. + // Note: nestlevel 1 would be: [foo [bar] + // nestlevel 2 would be: [foo [bar [baz] + subj->label_nestlevel--; + return 0; + } + + advance(subj); // advance past [ + char c; + while ((c = peek_char(subj)) && (c != ']' || nestlevel > 0)) { + switch (c) { + case '`': + tmp = handle_backticks(subj); + free_inlines(tmp); + break; + case '<': + tmp = handle_pointy_brace(subj); + free_inlines(tmp); + break; + case '[': // nested [] + nestlevel++; + advance(subj); + break; + case ']': // nested [] + nestlevel--; + advance(subj); + break; + case '\\': + advance(subj); + if (ispunct(peek_char(subj))) { + advance(subj); + } + break; + default: + advance(subj); + } + } + if (c == ']') { + *raw_label = chunk_buf( + subj->buffer, + startpos + 1, + subj->pos - (startpos + 1) + ); + + subj->label_nestlevel = 0; + advance(subj); // advance past ] + return 1; + } else { + if (c == 0) { + subj->label_nestlevel = nestlevel; + } + subj->pos = startpos; // rewind + return 0; + } } // Parse a link or the link portion of an image, or return a fallback. static inl* handle_left_bracket(subject* subj) { - inl* lab = NULL; - inl* result = NULL; - reference* ref; - int n; - int sps; - int found_label; - int endlabel, starturl, endurl, starttitle, endtitle, endall; - bstring url, title, rawlabel, reflabel; - bstring rawlabel2 = NULL; - found_label = link_label(subj, &rawlabel); - endlabel = subj->pos; - if (found_label) { - if (peek_char(subj) == '(' && - ((sps = scan_spacechars(subj->buffer, subj->pos + 1)) > -1) && - ((n = scan_link_url(subj->buffer, subj->pos + 1 + sps)) > -1)) { - // try to parse an explicit link: - starturl = subj->pos + 1 + sps; // after ( - endurl = starturl + n; - starttitle = endurl + scan_spacechars(subj->buffer, endurl); - // ensure there are spaces btw url and title - endtitle = (starttitle == endurl) ? starttitle : - starttitle + scan_link_title(subj->buffer, starttitle); - endall = endtitle + scan_spacechars(subj->buffer, endtitle); - if (bchar(subj->buffer, endall) == ')') { - subj->pos = endall + 1; - url = bmidstr(subj->buffer, starturl, endurl - starturl); - clean_url(url); - title = bmidstr(subj->buffer, starttitle, endtitle - starttitle); - clean_title(title); - lab = parse_inlines(rawlabel, NULL); - bdestroy(rawlabel); - return make_link(lab, url, title); - } else { - // if we get here, we matched a label but didn't get further: - subj->pos = endlabel; - lab = parse_inlines(rawlabel, subj->reference_map); - bdestroy(rawlabel); - result = append_inlines(make_str(bfromcstr("[")), - append_inlines(lab, - make_str(bfromcstr("]")))); - return result; - } - } else { - // Check for reference link. - // First, see if there's another label: - subj->pos = subj->pos + scan_spacechars(subj->buffer, endlabel); - reflabel = rawlabel; - // if followed by a nonempty link label, we change reflabel to it: - if (peek_char(subj) == '[' && - link_label(subj, &rawlabel2)) { - if (blength(rawlabel2) > 0) { - reflabel = rawlabel2; - } - } else { - subj->pos = endlabel; - } - // lookup rawlabel in subject->reference_map: - ref = lookup_reference(subj->reference_map, reflabel); - if (ref != NULL) { // found - lab = parse_inlines(rawlabel, NULL); - result = make_link(lab, bstrcpy(ref->url), bstrcpy(ref->title)); - } else { - subj->pos = endlabel; - lab = parse_inlines(rawlabel, subj->reference_map); - result = append_inlines(make_str(bfromcstr("[")), - append_inlines(lab, make_str(bfromcstr("]")))); - } - bdestroy(rawlabel); - bdestroy(rawlabel2); - return result; - } - } - // If we fall through to here, it means we didn't match a link: - advance(subj); // advance past [ - return make_str(bfromcstr("[")); + inl *lab = NULL; + inl *result = NULL; + reference *ref; + int n; + int sps; + int found_label; + int endlabel, starturl, endurl, starttitle, endtitle, endall; + + chunk rawlabel; + chunk url, title; + + found_label = link_label(subj, &rawlabel); + endlabel = subj->pos; + + if (found_label) { + if (peek_char(subj) == '(' && + ((sps = scan_spacechars(subj->buffer, subj->pos + 1)) > -1) && + ((n = scan_link_url(subj->buffer, subj->pos + 1 + sps)) > -1)) { + + // try to parse an explicit link: + starturl = subj->pos + 1 + sps; // after ( + endurl = starturl + n; + starttitle = endurl + scan_spacechars(subj->buffer, endurl); + + // ensure there are spaces btw url and title + endtitle = (starttitle == endurl) ? starttitle : + starttitle + scan_link_title(subj->buffer, starttitle); + + endall = endtitle + scan_spacechars(subj->buffer, endtitle); + + if (gh_buf_at(subj->buffer, endall) == ')') { + subj->pos = endall + 1; + + url = chunk_buf(subj->buffer, starturl, endurl - starturl); + title = chunk_buf(subj->buffer, starttitle, endtitle - starttitle); + lab = parse_chunk_inlines(&rawlabel, NULL); + + return make_link(lab, url, title); + } else { + // if we get here, we matched a label but didn't get further: + subj->pos = endlabel; + lab = parse_chunk_inlines(&rawlabel, subj->reference_map); + result = append_inlines(make_str(chunk_literal("[")), + append_inlines(lab, + make_str(chunk_literal("]")))); + return result; + } + } else { + chunk rawlabel_tmp; + chunk reflabel; + + // Check for reference link. + // First, see if there's another label: + subj->pos = subj->pos + scan_spacechars(subj->buffer, endlabel); + reflabel = rawlabel; + + // if followed by a nonempty link label, we change reflabel to it: + if (peek_char(subj) == '[' && link_label(subj, &rawlabel_tmp)) { + if (rawlabel_tmp.len > 0) + reflabel = rawlabel_tmp; + } else { + subj->pos = endlabel; + } + + // lookup rawlabel in subject->reference_map: + ref = lookup_reference(subj->reference_map, &reflabel); + if (ref != NULL) { // found + lab = parse_chunk_inlines(&rawlabel, NULL); + result = make_link(lab, chunk_literal(ref->url), chunk_literal(ref->title)); + } else { + subj->pos = endlabel; + lab = parse_chunk_inlines(&rawlabel, subj->reference_map); + result = append_inlines(make_str(chunk_literal("[")), + append_inlines(lab, make_str(chunk_literal("]")))); + } + return result; + } + } + // If we fall through to here, it means we didn't match a link: + advance(subj); // advance past [ + return make_str(chunk_literal("[")); } // Parse a hard or soft linebreak, returning an inline. // Assumes the subject has a newline at the current position. static inl* handle_newline(subject *subj) { - int nlpos = subj->pos; - // skip over newline - advance(subj); - // skip spaces at beginning of line - while (peek_char(subj) == ' ') { - advance(subj); - } - if (nlpos > 1 && - bchar(subj->buffer, nlpos - 1) == ' ' && - bchar(subj->buffer, nlpos - 2) == ' ') { - return make_linebreak(); - } else { - return make_softbreak(); - } + int nlpos = subj->pos; + // skip over newline + advance(subj); + // skip spaces at beginning of line + while (peek_char(subj) == ' ') { + advance(subj); + } + if (nlpos > 1 && + gh_buf_at(subj->buffer, nlpos - 1) == ' ' && + gh_buf_at(subj->buffer, nlpos - 2) == ' ') { + return make_linebreak(); + } else { + return make_softbreak(); + } } inline static int not_eof(subject* subj) { - return !is_eof(subj); + return !is_eof(subj); } // Parse inlines while a predicate is satisfied. Return inlines. extern inl* parse_inlines_while(subject* subj, int (*f)(subject*)) { - inl* result = NULL; - inl** last = &result; - while ((*f)(subj) && parse_inline(subj, last)) { - } - return result; + inl* result = NULL; + inl** last = &result; + while ((*f)(subj) && parse_inline(subj, last)) { + } + return result; +} + +inl *parse_chunk_inlines(chunk *chunk, reference** refmap) +{ + inl *result; + subject subj; + gh_buf full_chunk = GH_BUF_INIT; + + gh_buf_set(&full_chunk, chunk->data, chunk->len); + init_subject(&subj, &full_chunk, 0, refmap); + result = parse_inlines_while(&subj, not_eof); + + gh_buf_free(&full_chunk); + return result; +} + +static int find_special_char(subject *subj) +{ + int n = subj->pos + 1; + int size = (int)gh_buf_len(subj->buffer); + + while (n < size) { + if (strchr("\n\\`&_*[]buffer, n))) + return n; + } + + return -1; } // Parse an inline, advancing subject, and add it to last element. // Adjust tail to point to new last element of list. // Return 0 if no inline can be parsed, 1 otherwise. -extern int parse_inline(subject* subj, inl ** last) -{ - inl* new = NULL; - bstring contents; - bstring special_chars; - unsigned char c; - int endpos; - c = peek_char(subj); - if (c == 0) { - return 0; - } - switch(c){ - case '\n': - new = handle_newline(subj); - break; - case '`': - new = handle_backticks(subj); - break; - case '\\': - new = handle_backslash(subj); - break; - case '&': - new = handle_entity(subj); - break; - case '<': - new = handle_pointy_brace(subj); - break; - case '_': - if (subj->pos > 0 && (isalnum(bchar(subj->buffer, subj->pos - 1)) || - bchar(subj->buffer, subj->pos - 1) == '_')) { - new = make_str(take_one(subj)); - } else { - new = handle_strong_emph(subj, '_'); - } - break; - case '*': - new = handle_strong_emph(subj, '*'); - break; - case '[': - new = handle_left_bracket(subj); - break; - case '!': - advance(subj); - if (peek_char(subj) == '[') { - new = handle_left_bracket(subj); - if (new != NULL && new->tag == link) { - new->tag = image; - } else { - new = append_inlines(make_str(bfromcstr("!")), new); - } - } else { - new = make_str(bfromcstr("!")); - } - break; - default: - // we read until we hit a special character - special_chars = bfromcstr("\n\\`&_*[]buffer, subj->pos, special_chars); - bdestroy(special_chars); - if (endpos == subj->pos) { - // current char is special: read a 1-character str - contents = take_one(subj); - } else if (endpos == BSTR_ERR) { - // special char not found, take whole rest of buffer: - endpos = subj->buffer->slen; - contents = bmidstr(subj->buffer, subj->pos, endpos - subj->pos); - subj->pos = endpos; - } else { - // take buffer from subj->pos to endpos to str. - contents = bmidstr(subj->buffer, subj->pos, endpos - subj->pos); - subj->pos = endpos; - // if we're at a newline, strip trailing spaces. - if (peek_char(subj) == '\n') { - brtrimws(contents); - } - } - new = make_str(contents); - } - if (*last == NULL) { - *last = new; - } else { - append_inlines(*last, new); - } - return 1; -} - -extern inl* parse_inlines(bstring input, reference** refmap) -{ - subject * subj = make_subject(input, refmap); - inl * result = parse_inlines_while(subj, not_eof); - free(subj); - return result; +static int parse_inline(subject* subj, inl ** last) +{ + inl* new = NULL; + chunk contents; + unsigned char c; + int endpos; + c = peek_char(subj); + if (c == 0) { + return 0; + } + switch(c){ + case '\n': + new = handle_newline(subj); + break; + case '`': + new = handle_backticks(subj); + break; + case '\\': + new = handle_backslash(subj); + break; + case '&': + new = handle_entity(subj); + break; + case '<': + new = handle_pointy_brace(subj); + break; + case '_': + if (subj->pos > 0 && (isalnum(gh_buf_at(subj->buffer, subj->pos - 1)) || + gh_buf_at(subj->buffer, subj->pos - 1) == '_')) { + goto text_literal; + } + + new = handle_strong_emph(subj, '_'); + break; + case '*': + new = handle_strong_emph(subj, '*'); + break; + case '[': + new = handle_left_bracket(subj); + break; + case '!': + advance(subj); + if (peek_char(subj) == '[') { + new = handle_left_bracket(subj); + if (new != NULL && new->tag == link) { + new->tag = image; + } else { + new = append_inlines(make_str(chunk_literal("!")), new); + } + } else { + new = make_str(chunk_literal("!")); + } + break; + default: + text_literal: + endpos = find_special_char(subj); + if (endpos < 0) { + endpos = gh_buf_len(subj->buffer); + } + + contents = chunk_buf(subj->buffer, subj->pos, endpos - subj->pos); + subj->pos = endpos; + + // if we're at a newline, strip trailing spaces. + if (peek_char(subj) == '\n') { + chunk_trim(&contents); + } + + new = make_str(contents); + } + if (*last == NULL) { + *last = new; + } else { + append_inlines(*last, new); + } + return 1; +} + +extern inl* parse_inlines(gh_buf *input, int input_pos, reference** refmap) +{ + subject subj; + init_subject(&subj, input, input_pos, refmap); + return parse_inlines_while(&subj, not_eof); } // Parse zero or more space characters, including at most one newline. void spnl(subject* subj) { - bool seen_newline = false; - while (peek_char(subj) == ' ' || - (!seen_newline && - (seen_newline = peek_char(subj) == '\n'))) { - advance(subj); - } + bool seen_newline = false; + while (peek_char(subj) == ' ' || + (!seen_newline && + (seen_newline = peek_char(subj) == '\n'))) { + advance(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. -extern int parse_reference(bstring input, reference** refmap) -{ - subject * subj = make_subject(input, NULL); - bstring lab = NULL; - bstring url = NULL; - bstring title = NULL; - int matchlen = 0; - int beforetitle; - reference * new = NULL; - int newpos; - - // parse label: - if (!link_label(subj, &lab)) { - free(subj); - return 0; - } - // colon: - if (peek_char(subj) == ':') { - advance(subj); - } else { - free(subj); - bdestroy(lab); - return 0; - } - // parse link url: - spnl(subj); - matchlen = scan_link_url(subj->buffer, subj->pos); - if (matchlen) { - url = bmidstr(subj->buffer, subj->pos, matchlen); - clean_url(url); - subj->pos += matchlen; - } else { - free(subj); - bdestroy(lab); - bdestroy(url); - return 0; - } - // parse optional link_title - beforetitle = subj->pos; - spnl(subj); - matchlen = scan_link_title(subj->buffer, subj->pos); - if (matchlen) { - title = bmidstr(subj->buffer, subj->pos, matchlen); - clean_title(title); - subj->pos += matchlen; - } else { - subj->pos = beforetitle; - title = bfromcstr(""); - } - // parse final spaces and newline: - while (peek_char(subj) == ' ') { - advance(subj); - } - if (peek_char(subj) == '\n') { - advance(subj); - } else if (peek_char(subj) != 0) { - free(subj); - bdestroy(lab); - bdestroy(url); - bdestroy(title); - return 0; - } - // insert reference into refmap - new = make_reference(lab, url, title); - add_reference(refmap, new); - - newpos = subj->pos; - free(subj); - bdestroy(lab); - bdestroy(url); - bdestroy(title); - return newpos; +extern int parse_reference(gh_buf *input, int input_pos, reference** refmap) +{ + subject subj; + + chunk lab; + chunk url; + chunk title; + + int matchlen = 0; + int beforetitle; + reference * new = NULL; + + init_subject(&subj, input, input_pos, NULL); + + // parse label: + if (!link_label(&subj, &lab)) + return 0; + + // colon: + if (peek_char(&subj) == ':') { + advance(&subj); + } else { + return 0; + } + + // parse link url: + spnl(&subj); + matchlen = scan_link_url(subj.buffer, subj.pos); + if (matchlen) { + url = chunk_buf(subj.buffer, subj.pos, matchlen); + subj.pos += matchlen; + } else { + return 0; + } + + // parse optional link_title + beforetitle = subj.pos; + spnl(&subj); + matchlen = scan_link_title(subj.buffer, subj.pos); + if (matchlen) { + title = chunk_buf(subj.buffer, subj.pos, matchlen); + subj.pos += matchlen; + } else { + subj.pos = beforetitle; + title = chunk_literal(""); + } + // parse final spaces and newline: + while (peek_char(&subj) == ' ') { + advance(&subj); + } + if (peek_char(&subj) == '\n') { + advance(&subj); + } else if (peek_char(&subj) != 0) { + return 0; + } + // insert reference into refmap + new = make_reference(&lab, &url, &title); + add_reference(refmap, new); + + return subj.pos; } diff --git a/src/main.c b/src/main.c index f0ecb82..9e0a3c8 100644 --- a/src/main.c +++ b/src/main.c @@ -88,7 +88,7 @@ int main(int argc, char *argv[]) { print_blocks(cur, 0); } else { check(blocks_to_html(cur, &html, false) == 0, "could not format as HTML"); - printf("%s", html->data); + // printf("%s", html->data); bdestroy(html); } free_blocks(cur); diff --git a/src/scanners.h b/src/scanners.h index 71e0520..b6e586b 100644 --- a/src/scanners.h +++ b/src/scanners.h @@ -1,15 +1,15 @@ -#include "bstrlib.h" +#include "buffer.h" -int scan_autolink_uri(bstring s, int pos); -int scan_autolink_email(bstring s, int pos); -int scan_html_tag(bstring s, int pos); -int scan_html_block_tag(bstring s, int pos); -int scan_link_url(bstring s, int pos); -int scan_link_title(bstring s, int pos); -int scan_spacechars(bstring s, int pos); -int scan_atx_header_start(bstring s, int pos); -int scan_setext_header_line(bstring s, int pos); -int scan_hrule(bstring s, int pos); -int scan_open_code_fence(bstring s, int pos); -int scan_close_code_fence(bstring s, int pos, int len); -int scan_entity(bstring s, int pos); +int scan_autolink_uri(const gh_buf *s, int pos); +int scan_autolink_email(const gh_buf *s, int pos); +int scan_html_tag(const gh_buf *s, int pos); +int scan_html_block_tag(const gh_buf *s, int pos); +int scan_link_url(const gh_buf *s, int pos); +int scan_link_title(const gh_buf *s, int pos); +int scan_spacechars(const gh_buf *s, int pos); +int scan_atx_header_start(const gh_buf *s, int pos); +int scan_setext_header_line(const gh_buf *s, int pos); +int scan_hrule(const gh_buf *s, int pos); +int scan_open_code_fence(const gh_buf *s, int pos); +int scan_close_code_fence(const gh_buf *s, int pos, int len); +int scan_entity(const gh_buf *s, int pos); diff --git a/src/scanners.re b/src/scanners.re index 305d1ea..7323ef9 100644 --- a/src/scanners.re +++ b/src/scanners.re @@ -1,4 +1,4 @@ -#include "bstrlib.h" +#include "buffer.h" /*!re2c re2c:define:YYCTYPE = "unsigned char"; @@ -55,10 +55,10 @@ */ // Try to match URI autolink after first <, returning number of chars matched. -extern int scan_autolink_uri(bstring s, int pos) +extern int scan_autolink_uri(const gh_buf *s, int pos) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c scheme [:]([^\x00-\x20<>\\]|escaped_char)*[>] { return (p - start); } @@ -67,10 +67,10 @@ extern int scan_autolink_uri(bstring s, int pos) } // Try to match email autolink after first <, returning num of chars matched. -extern int scan_autolink_email(bstring s, int pos) +extern int scan_autolink_email(const gh_buf *s, int pos) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c [a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+ @@ -83,10 +83,10 @@ extern int scan_autolink_email(bstring s, int pos) } // Try to match an HTML tag after first <, returning num of chars matched. -extern int scan_html_tag(bstring s, int pos) +extern int scan_html_tag(const gh_buf *s, int pos) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c htmltag { return (p - start); } @@ -96,10 +96,10 @@ extern int scan_html_tag(bstring s, int pos) // Try to match an HTML block tag including first <, // returning num of chars matched. -extern int scan_html_block_tag(bstring s, int pos) +extern int scan_html_block_tag(const gh_buf *s, int pos) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c [<] [/] blocktagname (spacechar | [>]) { return (p - start); } @@ -113,10 +113,10 @@ extern int scan_html_block_tag(bstring s, int pos) // This may optionally be contained in <..>; otherwise // whitespace and unbalanced right parentheses aren't allowed. // Newlines aren't ever allowed. -extern int scan_link_url(bstring s, int pos) +extern int scan_link_url(const gh_buf *s, int pos) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c [ \n]* [<] ([^<>\n\\\x00] | escaped_char | [\\])* [>] { return (p - start); } @@ -128,10 +128,10 @@ extern int scan_link_url(bstring s, int pos) // Try to match a link title (in single quotes, in double quotes, or // in parentheses), returning number of chars matched. Allow one // level of internal nesting (quotes within quotes). -extern int scan_link_title(bstring s, int pos) +extern int scan_link_title(const gh_buf *s, int pos) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c ["] (escaped_char|[^"\x00])* ["] { return (p - start); } @@ -142,9 +142,9 @@ extern int scan_link_title(bstring s, int pos) } // Match space characters, including newlines. -extern int scan_spacechars(bstring s, int pos) +extern int scan_spacechars(const gh_buf *s, int pos) { - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c [ \t\n]* { return (p - start); } @@ -153,10 +153,10 @@ extern int scan_spacechars(bstring s, int pos) } // Match ATX header start. -extern int scan_atx_header_start(bstring s, int pos) +extern int scan_atx_header_start(const gh_buf *s, int pos) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c [#]{1,6} ([ ]+|[\n]) { return (p - start); } @@ -166,10 +166,10 @@ extern int scan_atx_header_start(bstring s, int pos) // Match sexext header line. Return 1 for level-1 header, // 2 for level-2, 0 for no match. -extern int scan_setext_header_line(bstring s, int pos) +extern int scan_setext_header_line(const gh_buf *s, int pos) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); /*!re2c [=]+ [ ]* [\n] { return 1; } [-]+ [ ]* [\n] { return 2; } @@ -180,10 +180,10 @@ extern int scan_setext_header_line(bstring s, int pos) // Scan a horizontal rule line: "...three or more hyphens, asterisks, // or underscores on a line by themselves. If you wish, you may use // spaces between the hyphens or asterisks." -extern int scan_hrule(bstring s, int pos) +extern int scan_hrule(const gh_buf *s, int pos) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c ([*][ ]*){3,} [ \t]* [\n] { return (p - start); } @@ -194,10 +194,10 @@ extern int scan_hrule(bstring s, int pos) } // Scan an opening code fence. -extern int scan_open_code_fence(bstring s, int pos) +extern int scan_open_code_fence(const gh_buf *s, int pos) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c [`]{3,} / [^`\n\x00]*[\n] { return (p - start); } @@ -207,10 +207,10 @@ extern int scan_open_code_fence(bstring s, int pos) } // Scan a closing code fence with length at least len. -extern int scan_close_code_fence(bstring s, int pos, int len) +extern int scan_close_code_fence(const gh_buf *s, int pos, int len) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c ([`]{3,} | [~]{3,}) / spacechar* [\n] @@ -225,10 +225,10 @@ extern int scan_close_code_fence(bstring s, int pos, int len) // Scans an entity. // Returns number of chars matched. -extern int scan_entity(bstring s, int pos) +extern int scan_entity(const gh_buf *s, int pos) { unsigned char * marker = NULL; - unsigned char * p = &(s->data[pos]); + unsigned char * p = &(s->ptr[pos]); unsigned char * start = p; /*!re2c [&] ([#] ([Xx][A-Fa-f0-9]{1,8}|[0-9]{1,8}) |[A-Za-z][A-Za-z0-9]{1,31} ) [;] diff --git a/src/stmd.h b/src/stmd.h index 5e34399..eb1b989 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -1,38 +1,38 @@ #include -#include "bstrlib.h" +#include "buffer.h" #include "uthash.h" #define VERSION "0.1" #define CODE_INDENT 4 +typedef struct { + const unsigned char *data; + int len; + int alloc; +} chunk; + typedef struct Inline { - enum { str, softbreak, linebreak, code, raw_html, entity, - emph, strong, link, image } tag; - union { - bstring literal; - struct Inline* inlines; - struct { struct Inline* label; - bstring url; - bstring title; - } linkable; - } content; - struct Inline* next; + enum { str, softbreak, linebreak, code, raw_html, entity, + emph, strong, link, image } tag; + union { + chunk literal; + struct Inline *inlines; + struct { + struct Inline *label; + unsigned char *url; + unsigned char *title; + } linkable; + } content; + struct Inline *next; } inl; typedef struct Reference { - bstring label; - bstring url; - bstring title; + unsigned char *label; + unsigned char *url; + unsigned char *title; UT_hash_handle hh; // used by uthash } reference; -typedef struct Subject { - bstring buffer; - int pos; - reference** reference_map; - int label_nestlevel; -} subject; - // Types for blocks struct ListData { @@ -51,7 +51,7 @@ struct FencedCodeData { int fence_length; int fence_offset; char fence_char; - bstring info; + gh_buf info; }; typedef struct Block { @@ -77,7 +77,8 @@ typedef struct Block { struct Block* last_child; struct Block* parent; struct Block* top; - bstring string_content; + gh_buf string_content; + int string_pos; inl* inline_content; union { struct ListData list_data; @@ -89,33 +90,34 @@ typedef struct Block { struct Block * prev; } block; -int parse_inline(subject* subj, inl ** last); -inl* parse_inlines(bstring input, reference** refmap); -inl* parse_inlines_while(subject* subj, int (*f)(subject*)); +inl* parse_inlines(gh_buf *input, int input_pos, reference** refmap); void free_inlines(inl* e); -int parse_reference(bstring input, reference** refmap); + +int parse_reference(gh_buf *input, int input_pos, reference** refmap); void free_reference(reference *ref); void free_reference_map(reference **refmap); -reference* make_reference(bstring label, bstring url, bstring title); -reference* lookup_reference(reference** refmap, bstring label); + void add_reference(reference** refmap, reference* ref); -int unescape(bstring s); +void unescape_buffer(gh_buf *buf); extern block* make_document(); extern block* add_child(block* parent, int block_type, int start_line, int start_column); void free_blocks(block* e); +block *stmd_parse_document(const char *buffer, size_t len); + // FOR NOW: -int process_inlines(block* cur, reference** refmap); -int incorporate_line(bstring ln, int line_number, block** curptr); -int finalize(block* b, int line_number); +void process_inlines(block* cur, reference** refmap); +void incorporate_line(gh_buf *ln, int line_number, block** curptr); +void finalize(block* b, int line_number); void print_inlines(inl* ils, int indent); void print_blocks(block* blk, int indent); -int blocks_to_html(block* b, bstring* result, bool tight); -int inlines_to_html(inl* b, bstring* result); +/* TODO */ +// int blocks_to_html(block* b, bstring* result, bool tight); +// int inlines_to_html(inl* b, bstring* result); -int bdetab(bstring s, int utf8); +void utf8proc_case_fold(gh_buf *dest, const unsigned char *str, int len); diff --git a/src/utf8.c b/src/utf8.c index 4bb3b35..1a5df9e 100644 --- a/src/utf8.c +++ b/src/utf8.c @@ -2,105 +2,142 @@ #include "bstrlib.h" #include "debug.h" -#define advance(s) \ - s++; \ - check(*s >> 6 == 0x02, "UTF-8 decode error on byte %x", *s); - -// Reads a unicode code point from a UTF8-encoded string, and -// puts it in the pointer n. If something illegal -// is encountered, 0xFFFD is emitted. -// Returns a pointer to next position in string, or NULL if no -// more characters remain. -extern unsigned char * from_utf8(unsigned char * s, unsigned int *n) +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 }; + +ssize_t utf8proc_charlen(const uint8_t *str, ssize_t str_len) { - int x = 0; - - if (*s == 0) { - return NULL; - } else if (*s < 0x80) { - x = *s; - } else if (*s >> 5 == 0x06) { - x = *s & 0x1F; - advance(s); - x = (x << 6) + (*s & 0x3F); - } else if (*s >> 4 == 0x0E) { - x = *s & 0x0F; - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - } else if (*s >> 3 == 0x1E) { - x = *s & 0x07; - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - } else if (*s >> 2 == 0x3E) { - x = *s & 0x03; - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - advance(s); - x = (x << 6) + (*s & 0x3F); - } else { - log_err("UTF-8 decode error on byte %x", *s); - goto error; - } - *n = x; - s++; - return s; - error: - *n = 0xFFFD; - return s; + ssize_t length, i; + + if (!str_len) + return 0; + + length = utf8proc_utf8class[str[0]]; + + if (!length) + return -1; + + if (str_len >= 0 && length > str_len) + return -1; + + for (i = 1; i < length; i++) { + if ((str[i] & 0xC0) != 0x80) + return -1; + } + + return length; +} + +ssize_t utf8proc_iterate(const uint8_t *str, ssize_t str_len, int32_t *dst) +{ + ssize_t 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 >= 0xFDD0 && uc < 0xFDF0)) 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 || ((uc & 0xFFFF) >= 0xFFFE)) + return -1; + + *dst = uc; + return length; } -// Converts the unicode code point c to UTF-8, -// putting the result in dest. Returns 0 on success, -1 on error. -extern int to_utf8(unsigned int c, bstring dest) +void utf8_encode_char(int32_t uc, gh_buf *buf) { - if (c < 0x80) { - bconchar(dest, c); - } else if (c < 0x800) { - bconchar(dest, 192 + c/64); - bconchar(dest, 128 + c%64); - } else if (c - 0xd800u < 0x800) { - goto error; - } else if (c < 0x10000) { - bconchar(dest, 224 + c / 4096); - bconchar(dest, 128 + c /64%64); - bconchar(dest, 128 + c%64); - } else if (c < 0x110000) { - bconchar(dest, 240 + c/262144); - bconchar(dest, 128 + c/4096%64); - bconchar(dest, 128 + c/64%64); - bconchar(dest, 128 + c%64); - } else { - goto error; - } - return 0; -error: - return -1; + char dst[4]; + int len = 0; + + if (uc < 0x00) { + assert(false); + } else if (uc < 0x80) { + dst[0] = uc; + len = 1; + } else if (uc < 0x800) { + dst[0] = 0xC0 + (uc >> 6); + dst[1] = 0x80 + (uc & 0x3F); + len = 2; + } else if (uc == 0xFFFF) { + dst[0] = 0xFF; + return 1; + } else if (uc == 0xFFFE) { + dst[0] = 0xFE; + len = 1; + } else if (uc < 0x10000) { + dst[0] = 0xE0 + (uc >> 12); + dst[1] = 0x80 + ((uc >> 6) & 0x3F); + dst[2] = 0x80 + (uc & 0x3F); + len = 3; + } else if (uc < 0x110000) { + dst[0] = 0xF0 + (uc >> 18); + dst[1] = 0x80 + ((uc >> 12) & 0x3F); + dst[2] = 0x80 + ((uc >> 6) & 0x3F); + dst[3] = 0x80 + (uc & 0x3F); + len = 4; + } else { + assert(false); + } + + gh_buf_put(buf, dst, len); } +void utf8proc_case_fold(gh_buf *dest, const unsigned char *str, int len) +{ + int32_t c; + #define bufpush(x) \ - check(to_utf8(x, buf) == 0, "UTF-8 encode error on code point %04x", x) + utf8proc_encode_char(x, dest) -// Returns the case-folded version of the source string, or NULL on error. -extern bstring case_fold(bstring source) -{ - unsigned char * s = source->data; - unsigned int c = 0; - bstring buf = bfromcstr(""); - while ((s = from_utf8(s, &c))) { -#include "case_fold_switch.c" - } - return buf; -error: - return NULL; + while (len > 0) { + ssize_t char_len = utf8proc_iterate(str, len, &c); + + if (char_len < 0) { + bufpush(0xFFFD); + continue; + } + +#include "case_fold_switch.inc" + + str += char_len; + len -= char_len; + } } -- cgit v1.2.3 From 582674e662d1f8757350c51486a5e0a837195e15 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 2 Sep 2014 13:18:04 +0200 Subject: ffffix --- Makefile | 11 ++- src/blocks.c | 58 +++++++---- src/buffer.c | 69 +++++-------- src/buffer.h | 19 ++-- src/html.c | 276 ---------------------------------------------------- src/inlines.c | 4 +- src/main.c | 142 ++++++++++++--------------- src/print.c | 307 ++++++++++++++++++++++++++++++---------------------------- src/stmd.h | 13 +-- src/utf8.c | 6 +- src/utf8.h | 6 -- 11 files changed, 304 insertions(+), 607 deletions(-) delete mode 100644 src/html.c delete mode 100644 src/utf8.h (limited to 'src') diff --git a/Makefile b/Makefile index cb5938d..d14a928 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ DATADIR=data PROG=./stmd .PHONY: all oldtests test spec benchjs testjs -all: $(SRCDIR)/case_fold_switch.c $(PROG) +all: $(SRCDIR)/case_fold_switch.inc $(PROG) README.html: README.md template.html pandoc --template template.html -S -s -t html5 -o $@ $< @@ -41,13 +41,16 @@ testjs: spec.txt benchjs: node js/bench.js ${BENCHINP} -$(PROG): $(SRCDIR)/main.c $(SRCDIR)/inlines.o $(SRCDIR)/buffer.o $(SRCDIR)/blocks.o $(SRCDIR)/scanners.c $(SRCDIR)/print.o $(SRCDIR)/html.o $(SRCDIR)/utf8.o +HTML_OBJ=$(SRCDIR)/html/html.o $(SRCDIR)/html/houdini_href_e.o $(SRCDIR)/html/houdini_html_e.o +STMD_OBJ=$(SRCDIR)/inlines.o $(SRCDIR)/buffer.o $(SRCDIR)/blocks.o $(SRCDIR)/scanners.c $(SRCDIR)/print.o $(SRCDIR)/utf8.o + +$(PROG): $(SRCDIR)/main.c $(HTML_OBJ) $(STMD_OBJ) $(CC) $(LDFLAGS) -o $@ $^ $(SRCDIR)/scanners.c: $(SRCDIR)/scanners.re re2c --case-insensitive -bis $< > $@ || (rm $@ && false) -$(SRCDIR)/case_fold_switch.inc $(DATADIR)/CaseFolding-3.2.0.txt +$(SRCDIR)/case_fold_switch.inc: $(DATADIR)/CaseFolding-3.2.0.txt perl mkcasefold.pl < $< > $@ .PHONY: leakcheck clean fuzztest dingus upload @@ -72,7 +75,7 @@ update-site: spec.html narrative.html (cd _site ; git pull ; git commit -a -m "Updated site for latest spec, narrative, js" ; git push; cd ..) clean: - -rm -f test $(SRCDIR)/*.o $(SRCDIR)/scanners.c + -rm -f test $(SRCDIR)/*.o $(SRCDIR)/scanners.c $(SRCDIR)/html/*.o -rm -rf *.dSYM -rm -f README.html -rm -f spec.md fuzz.txt spec.html diff --git a/src/blocks.c b/src/blocks.c index eabac03..71dc830 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -3,11 +3,12 @@ #include #include #include -#include "bstrlib.h" + #include "stmd.h" -#include "uthash.h" -#include "debug.h" #include "scanners.h" +#include "uthash.h" + +static void finalize(block* b, int line_number); static block* make_block(int tag, int start_line, int start_column) { @@ -140,7 +141,7 @@ static int break_out_of_lists(block ** bptr, int line_number) } -extern void finalize(block* b, int line_number) +static void finalize(block* b, int line_number) { int firstlinelen; int pos; @@ -364,7 +365,7 @@ static int lists_match(struct ListData list_data, list_data.bullet_char == item_data.bullet_char); } -static void expand_tabs(gh_buf *ob, const char *line, size_t size) +static void expand_tabs(gh_buf *ob, const unsigned char *line, size_t size) { size_t i = 0, tab = 0; @@ -389,13 +390,43 @@ static void expand_tabs(gh_buf *ob, const char *line, size_t size) } } -extern block *stmd_parse_document(const char *buffer, size_t len) +static block *finalize_parsing(block *document, int linenum) { - gh_buf line = GH_BUF_INIT; + while (document != document->top) { + finalize(document, linenum); + document = document->parent; + } + + finalize(document, linenum); + process_inlines(document, document->attributes.refmap); + + return document; +} +extern block *stmd_parse_file(FILE *f) +{ + gh_buf line = GH_BUF_INIT; + unsigned char buffer[4096]; + int linenum = 1; block *document = make_document(); + + while (fgets((char *)buffer, sizeof(buffer), f)) { + expand_tabs(&line, buffer, strlen(buffer)); + incorporate_line(&line, linenum, &document); + gh_buf_clear(&line); + linenum++; + } + + gh_buf_free(&line); + return finalize_document(document, linenum); +} + +extern block *stmd_parse_document(const unsigned char *buffer, size_t len) +{ + gh_buf line = GH_BUF_INIT; int linenum = 1; - const char *end = buffer + len; + const unsigned char *end = buffer + len; + block *document = make_document(); while (buffer < end) { const char *eol = memchr(buffer, '\n', end - buffer); @@ -414,16 +445,7 @@ extern block *stmd_parse_document(const char *buffer, size_t len) } gh_buf_free(&line); - - while (document != document->top) { - finalize(document, linenum); - document = document->parent; - } - - finalize(document, linenum); - process_inlines(document, document->attributes.refmap); - - return document; + return finalize_document(document, linenum); } // Process one line at a time, modifying a block. diff --git a/src/buffer.c b/src/buffer.c index b81e7fa..17dc864 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -31,10 +31,10 @@ void gh_buf_init(gh_buf *buf, int initial_size) int gh_buf_try_grow(gh_buf *buf, int target_size, bool mark_oom) { - char *new_ptr; - size_t new_size; + unsigned char *new_ptr; + int new_size; - if (buf->ptr == gh_buf__oom || buf->asize < 0) + if (buf->ptr == gh_buf__oom) return -1; if (target_size <= buf->asize) @@ -79,7 +79,7 @@ void gh_buf_free(gh_buf *buf) { if (!buf) return; - if (buf->asize > 0 && buf->ptr != gh_buf__initbuf && buf->ptr != gh_buf__oom) + if (buf->ptr != gh_buf__initbuf && buf->ptr != gh_buf__oom) free(buf->ptr); gh_buf_init(buf, 0); @@ -91,14 +91,9 @@ void gh_buf_clear(gh_buf *buf) if (buf->asize > 0) buf->ptr[0] = '\0'; - - if (buf->asize < 0) { - buf->ptr = gh_buf__initbuf; - buf->asize = 0; - } } -int gh_buf_set(gh_buf *buf, const char *data, int len) +int gh_buf_set(gh_buf *buf, const unsigned char *data, int len) { if (len == 0 || data == NULL) { gh_buf_clear(buf); @@ -115,10 +110,12 @@ int gh_buf_set(gh_buf *buf, const char *data, int len) int gh_buf_sets(gh_buf *buf, const char *string) { - return gh_buf_set(buf, string, string ? strlen(string) : 0); + return gh_buf_set(buf, + (const unsigned char *)string, + string ? strlen(string) : 0); } -int gh_buf_putc(gh_buf *buf, char c) +int gh_buf_putc(gh_buf *buf, int c) { ENSURE_SIZE(buf, buf->size + 2); buf->ptr[buf->size++] = c; @@ -126,7 +123,7 @@ int gh_buf_putc(gh_buf *buf, char c) return 0; } -int gh_buf_put(gh_buf *buf, const char *data, int len) +int gh_buf_put(gh_buf *buf, const unsigned char *data, int len) { ENSURE_SIZE(buf, buf->size + len + 1); memmove(buf->ptr + buf->size, data, len); @@ -137,8 +134,7 @@ int gh_buf_put(gh_buf *buf, const char *data, int len) int gh_buf_puts(gh_buf *buf, const char *string) { - assert(string); - return gh_buf_put(buf, string, strlen(string)); + return gh_buf_put(buf, (const unsigned char *)string, strlen(string)); } int gh_buf_vprintf(gh_buf *buf, const char *format, va_list ap) @@ -153,7 +149,7 @@ int gh_buf_vprintf(gh_buf *buf, const char *format, va_list ap) va_copy(args, ap); len = vsnprintf( - buf->ptr + buf->size, + (char *)buf->ptr + buf->size, buf->asize - buf->size, format, args ); @@ -187,9 +183,9 @@ int gh_buf_printf(gh_buf *buf, const char *format, ...) return r; } -void gh_buf_copy_cstr(char *data, size_t datasize, const gh_buf *buf) +void gh_buf_copy_cstr(char *data, int datasize, const gh_buf *buf) { - size_t copylen; + int copylen; assert(data && datasize && buf); @@ -212,9 +208,9 @@ void gh_buf_swap(gh_buf *buf_a, gh_buf *buf_b) *buf_b = t; } -char *gh_buf_detach(gh_buf *buf) +unsigned char *gh_buf_detach(gh_buf *buf) { - char *data = buf->ptr; + unsigned char *data = buf->ptr; if (buf->asize == 0 || buf->ptr == gh_buf__oom) return NULL; @@ -224,13 +220,13 @@ char *gh_buf_detach(gh_buf *buf) return data; } -void gh_buf_attach(gh_buf *buf, char *ptr, int asize) +void gh_buf_attach(gh_buf *buf, unsigned char *ptr, int asize) { gh_buf_free(buf); if (ptr) { buf->ptr = ptr; - buf->size = strlen(ptr); + buf->size = strlen((char *)ptr); if (asize) buf->asize = (asize < buf->size) ? buf->size + 1 : asize; else /* pass 0 to fall back on strlen + 1 */ @@ -249,11 +245,11 @@ int gh_buf_cmp(const gh_buf *a, const gh_buf *b) int gh_buf_strchr(const gh_buf *buf, int c, int pos) { - const char *p = memchr(buf->ptr + pos, c, buf->size - pos); - if (!p) - return -1; + const char *p = memchr(buf->ptr + pos, c, buf->size - pos); + if (!p) + return -1; - return (int)(p - p->ptr); + return (int)(p - buf->ptr); } int gh_buf_strrchr(const gh_buf *buf, int c, int pos) @@ -270,36 +266,21 @@ int gh_buf_strrchr(const gh_buf *buf, int c, int pos) void gh_buf_truncate(gh_buf *buf, size_t len) { - assert(buf->asize >= 0); - if (len < buf->size) { buf->size = len; buf->ptr[buf->size] = '\0'; } } -void gh_buf_ltruncate(gh_buf *buf, size_t len) -{ - assert(buf->asize >= 0); - - if (len && len < buf->size) { - memmove(buf->ptr, buf->ptr + len, buf->size - len); - buf->size -= len; - buf->ptr[buf->size] = '\0'; - } -} - void gh_buf_trim(gh_buf *buf) { - size_t i = 0; - - assert(buf->asize >= 0); - - /* ltrim */ + /* TODO: leading whitespace? */ + /* while (i < buf->size && isspace(buf->ptr[i])) i++; gh_buf_truncate(buf, i); + */ /* rtrim */ while (buf->size > 0) { diff --git a/src/buffer.h b/src/buffer.h index 2581ee3..422ef02 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -24,13 +24,6 @@ extern unsigned char gh_buf__oom[]; */ extern void gh_buf_init(gh_buf *buf, int initial_size); -static inline void gh_buf_static(gh_buf *buf, unsigned char *source) -{ - buf->ptr = source; - buf->size = strlen(source); - buf->asize = -1; -} - /** * Attempt to grow the buffer to hold at least `target_size` bytes. * @@ -81,13 +74,13 @@ static inline size_t gh_buf_len(const gh_buf *buf) extern int gh_buf_cmp(const gh_buf *a, const gh_buf *b); -extern void gh_buf_attach(gh_buf *buf, char *ptr, int asize); -extern char *gh_buf_detach(gh_buf *buf); +extern void gh_buf_attach(gh_buf *buf, unsigned char *ptr, int asize); +extern unsigned char *gh_buf_detach(gh_buf *buf); extern void gh_buf_copy_cstr(char *data, int datasize, const gh_buf *buf); static inline const char *gh_buf_cstr(const gh_buf *buf) { - return buf->ptr; + return (char *)buf->ptr; } #define gh_buf_at(buf, n) ((buf)->ptr[n]) @@ -100,10 +93,10 @@ static inline const char *gh_buf_cstr(const gh_buf *buf) * return code of these functions and call them in a series then just call * gh_buf_oom at the end. */ -extern int gh_buf_set(gh_buf *buf, const char *data, int len); +extern int gh_buf_set(gh_buf *buf, const unsigned char *data, int len); extern int gh_buf_sets(gh_buf *buf, const char *string); -extern int gh_buf_putc(gh_buf *buf, char c); -extern int gh_buf_put(gh_buf *buf, const char *data, int len); +extern int gh_buf_putc(gh_buf *buf, int c); +extern int gh_buf_put(gh_buf *buf, const unsigned char *data, int len); extern int gh_buf_puts(gh_buf *buf, const char *string); extern int gh_buf_printf(gh_buf *buf, const char *format, ...) __attribute__((format (printf, 2, 3))); diff --git a/src/html.c b/src/html.c deleted file mode 100644 index aeec5f1..0000000 --- a/src/html.c +++ /dev/null @@ -1,276 +0,0 @@ -#include -#include -#include -#include "bstrlib.h" -#include "stmd.h" -#include "debug.h" -#include "scanners.h" - -// Functions to convert block and inline lists to HTML strings. - -// Escape special characters in HTML. More efficient than -// three calls to bfindreplace. If preserve_entities is set, -// existing entities are left alone. -static bstring escape_html(bstring inp, bool preserve_entities) -{ - int pos = 0; - int match; - char c; - bstring escapable = blk2bstr("&<>\"", 4); - bstring ent; - bstring s = bstrcpy(inp); - while ((pos = binchr(s, pos, escapable)) != BSTR_ERR) { - c = bchar(s,pos); - switch (c) { - case '<': - bdelete(s, pos, 1); - ent = blk2bstr("<", 4); - binsert(s, pos, ent, ' '); - bdestroy(ent); - pos += 4; - break; - case '>': - bdelete(s, pos, 1); - ent = blk2bstr(">", 4); - binsert(s, pos, ent, ' '); - bdestroy(ent); - pos += 4; - break; - case '&': - if (preserve_entities && (match = scan_entity(s, pos))) { - pos += match; - } else { - bdelete(s, pos, 1); - ent = blk2bstr("&", 5); - binsert(s, pos, ent, ' '); - bdestroy(ent); - pos += 5; - } - break; - case '"': - bdelete(s, pos, 1); - ent = blk2bstr(""", 6); - binsert(s, pos, ent, ' '); - bdestroy(ent); - pos += 6; - break; - default: - bdelete(s, pos, 1); - log_err("unexpected character %02x", c); - } - } - bdestroy(escapable); - return s; -} - -static inline void cr(bstring buffer) -{ - int c = bchar(buffer, blength(buffer) - 1); - if (c != '\n' && c) { - bconchar(buffer, '\n'); - } -} - -// Convert a block list to HTML. Returns 0 on success, and sets result. -extern int blocks_to_html(block* b, bstring* result, bool tight) -{ - bstring contents = NULL; - bstring escaped, escaped2; - struct bstrList * info_words; - struct ListData * data; - bstring mbstart; - bstring html = blk2bstr("", 0); - - while(b != NULL) { - switch(b->tag) { - case document: - check(blocks_to_html(b->children, &contents, false) == 0, - "error converting blocks to html"); - bformata(html, "%s", contents->data); - bdestroy(contents); - break; - case paragraph: - check(inlines_to_html(b->inline_content, &contents) == 0, - "error converting inlines to html"); - if (tight) { - bformata(html, "%s", contents->data); - } else { - cr(html); - bformata(html, "

%s

", contents->data); - cr(html); - } - bdestroy(contents); - break; - case block_quote: - check(blocks_to_html(b->children, &contents, false) == 0, - "error converting blocks to html"); - cr(html); - bformata(html, "
\n%s
", contents->data); - cr(html); - bdestroy(contents); - break; - case list_item: - check(blocks_to_html(b->children, &contents, tight) == 0, - "error converting blocks to html"); - brtrimws(contents); - cr(html); - bformata(html, "
  • %s
  • ", contents->data); - cr(html); - bdestroy(contents); - break; - case list: - // make sure a list starts at the beginning of the line: - cr(html); - data = &(b->attributes.list_data); - check(blocks_to_html(b->children, &contents, data->tight) == 0, - "error converting blocks to html"); - mbstart = bformat(" start=\"%d\"", data->start); - bformata(html, "<%s%s>\n%s", - data->list_type == bullet ? "ul" : "ol", - data->start == 1 ? "" : (char*) mbstart->data, - contents->data, - data->list_type == bullet ? "ul" : "ol"); - cr(html); - bdestroy(contents); - bdestroy(mbstart); - break; - case atx_header: - case setext_header: - check(inlines_to_html(b->inline_content, &contents) == 0, - "error converting inlines to html"); - cr(html); - bformata(html, "%s", - b->attributes.header_level, - contents->data, - b->attributes.header_level); - cr(html); - bdestroy(contents); - break; - case indented_code: - escaped = escape_html(b->string_content, false); - cr(html); - bformata(html, "
    %s
    ", escaped->data); - cr(html); - bdestroy(escaped); - break; - case fenced_code: - escaped = escape_html(b->string_content, false); - cr(html); - bformata(html, "
    attributes.fenced_code_data.info) > 0) {
    -        escaped2 = escape_html(b->attributes.fenced_code_data.info, true);
    -        info_words = bsplit(escaped2, ' ');
    -        bformata(html, " class=\"language-%s\"", info_words->entry[0]->data);
    -        bdestroy(escaped2);
    -        bstrListDestroy(info_words);
    -      }
    -      bformata(html, ">%s
    ", escaped->data); - cr(html); - bdestroy(escaped); - break; - case html_block: - bformata(html, "%s", b->string_content->data); - break; - case hrule: - bformata(html, "
    "); - cr(html); - break; - case reference_def: - break; - default: - log_warn("block type %d not implemented\n", b->tag); - break; - } - b = b->next; - } - *result = html; - return 0; - error: - return -1; -} - -// Convert an inline list to HTML. Returns 0 on success, and sets result. -extern int inlines_to_html(inl* ils, bstring* result) -{ - bstring contents = NULL; - bstring html = blk2bstr("", 0); - bstring mbtitle, escaped, escaped2; - - while(ils != NULL) { - switch(ils->tag) { - case str: - escaped = escape_html(ils->content.literal, false); - bformata(html, "%s", escaped->data); - bdestroy(escaped); - break; - case linebreak: - bformata(html, "
    \n"); - break; - case softbreak: - bformata(html, "\n"); - break; - case code: - escaped = escape_html(ils->content.literal, false); - bformata(html, "%s", escaped->data); - bdestroy(escaped); - break; - case raw_html: - case entity: - bformata(html, "%s", ils->content.literal->data); - break; - case link: - check(inlines_to_html(ils->content.inlines, &contents) == 0, - "error converting inlines to html"); - if (blength(ils->content.linkable.title) > 0) { - escaped = escape_html(ils->content.linkable.title, true); - mbtitle = bformat(" title=\"%s\"", escaped->data); - bdestroy(escaped); - } else { - mbtitle = blk2bstr("",0); - } - escaped = escape_html(ils->content.linkable.url, true); - bformata(html, "%s", - escaped->data, - mbtitle->data, - contents->data); - bdestroy(escaped); - bdestroy(mbtitle); - bdestroy(contents); - break; - case image: - check(inlines_to_html(ils->content.inlines, &contents) == 0, - "error converting inlines to html"); - escaped = escape_html(ils->content.linkable.url, true); - escaped2 = escape_html(contents, false); - bdestroy(contents); - bformata(html, "\"%s\"",data, escaped2->data); - bdestroy(escaped); - bdestroy(escaped2); - if (blength(ils->content.linkable.title) > 0) { - escaped = escape_html(ils->content.linkable.title, true); - bformata(html, " title=\"%s\"", escaped->data); - bdestroy(escaped); - } - bformata(html, " />"); - break; - case strong: - check(inlines_to_html(ils->content.inlines, &contents) == 0, - "error converting inlines to html"); - bformata(html, "%s", contents->data); - bdestroy(contents); - break; - case emph: - check(inlines_to_html(ils->content.inlines, &contents) == 0, - "error converting inlines to html"); - bformata(html, "%s", contents->data); - bdestroy(contents); - break; - } - ils = ils->next; - } - *result = html; - return 0; - error: - return -1; -} diff --git a/src/inlines.c b/src/inlines.c index 4ff45ad..82c7219 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -6,9 +6,7 @@ #include "stmd.h" #include "uthash.h" -#include "debug.h" #include "scanners.h" -#include "utf8.h" typedef struct Subject { const gh_buf *buffer; @@ -119,7 +117,7 @@ inline static inl* make_linkable(int t, inl* label, chunk url, chunk title) e->tag = t; e->content.linkable.label = label; e->content.linkable.url = chunk_to_cstr(&url); - e->content.linkable.title = chunk_to_cstr(&title); + e->content.linkable.title = url.len ? chunk_to_cstr(&title) : NULL; e->next = NULL; return e; } diff --git a/src/main.c b/src/main.c index 9e0a3c8..e1abedc 100644 --- a/src/main.c +++ b/src/main.c @@ -1,99 +1,77 @@ #include #include -#include "bstrlib.h" +#include #include "stmd.h" #include "debug.h" void print_usage() { - printf("Usage: stmd [FILE*]\n"); - printf("Options: --help, -h Print usage information\n"); - printf(" --ast Print AST instead of HTML\n"); - printf(" --version Print version\n"); + printf("Usage: stmd [FILE*]\n"); + printf("Options: --help, -h Print usage information\n"); + printf(" --ast Print AST instead of HTML\n"); + printf(" --version Print version\n"); } -int main(int argc, char *argv[]) { - int i; - bool ast = false; - int g = 0; - int numfps = 0; - int files[argc]; +static void print_document(block *document, bool ast) +{ + gh_buf html = GH_BUF_INIT; + + if (ast) { + print_blocks(document, 0); + } else { + blocks_to_html(&html, document, false); + printf("%s", html.ptr); + gh_buf_free(&html); + } +} - for (i=1; i < argc; i++) { - if (strcmp(argv[i], "--version") == 0) { - printf("stmd %s", VERSION); - printf(" - CommonMark converter (c) 2014 John MacFarlane\n"); - exit(0); - } else if ((strcmp(argv[i], "--help") == 0) || - (strcmp(argv[i], "-h") == 0)) { - print_usage(); - exit(0); - } else if (strcmp(argv[i], "--ast") == 0) { - ast = true; - } else if (*argv[i] == '-') { - print_usage(); - exit(1); - } else { // treat as file argument - files[g] = i; - g++; - } - } +int main(int argc, char *argv[]) +{ + int i, numfps = 0; + bool ast = false; + int files[argc]; + block *document = NULL; - numfps = g; - bstring s = NULL; - bstring html; - g = 0; - block * cur = make_document(); - int linenum = 1; - extern int errno; - FILE * fp = NULL; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "--version") == 0) { + printf("stmd %s", VERSION); + printf(" - CommonMark converter (c) 2014 John MacFarlane\n"); + exit(0); + } else if ((strcmp(argv[i], "--help") == 0) || + (strcmp(argv[i], "-h") == 0)) { + print_usage(); + exit(0); + } else if (strcmp(argv[i], "--ast") == 0) { + ast = true; + } else if (*argv[i] == '-') { + print_usage(); + exit(1); + } else { // treat as file argument + files[numfps++] = i; + } + } - if (numfps == 0) { - // read from stdin - while ((s = bgets((bNgetc) fgetc, stdin, '\n'))) { - check(incorporate_line(s, linenum, &cur) == 0, - "error incorporating line %d", linenum); - bdestroy(s); - linenum++; - } - } else { - // iterate over input file pointers - for (g=0; g < numfps; g++) { + if (numfps == 0) { + document = stmd_parse_file(stdin); + print_document(document, ast); + free_blocks(document); + } else { + for (i = 0; i < numfps; i++) { + FILE *fp = fopen(argv[files[i]], "r"); - fp = fopen(argv[files[g]], "r"); - if (fp == NULL) { - fprintf(stderr, "Error opening file %s: %s\n", - argv[files[g]], strerror(errno)); - exit(1); - } + if (fp == NULL) { + fprintf(stderr, "Error opening file %s: %s\n", + argv[files[i]], strerror(errno)); + exit(1); + } - while ((s = bgets((bNgetc) fgetc, fp, '\n'))) { - check(incorporate_line(s, linenum, &cur) == 0, - "error incorporating line %d", linenum); - bdestroy(s); - linenum++; - } - fclose(fp); - } - } + document = stmd_parse_file(fp); + print_document(document, ast); + free_blocks(document); + fclose(fp); + } + } - while (cur != cur->top) { - finalize(cur, linenum); - cur = cur->parent; - } - check(cur == cur->top, "problems finalizing open containers"); - finalize(cur, linenum); - process_inlines(cur, cur->attributes.refmap); - if (ast) { - print_blocks(cur, 0); - } else { - check(blocks_to_html(cur, &html, false) == 0, "could not format as HTML"); - // printf("%s", html->data); - bdestroy(html); - } - free_blocks(cur); - return 0; -error: - return -1; + return 0; } diff --git a/src/print.c b/src/print.c index a924870..3ebde16 100644 --- a/src/print.c +++ b/src/print.c @@ -1,168 +1,175 @@ #include #include -#include "bstrlib.h" +#include #include "stmd.h" #include "debug.h" -static bstring format_str(bstring s) +static void print_str(const unsigned char *s, int len) { - int pos = 0; - int len = blength(s); - bstring result = bfromcstr(""); - char c; - bformata(result, "\""); - while (pos < len) { - c = bchar(s, pos); - switch (c) { - case '\n': - bformata(result, "\\n"); - break; - case '"': - bformata(result, "\\\""); - break; - case '\\': - bformata(result, "\\\\"); - break; - default: - bformata(result, "%c", c); - } - pos++; - } - bformata(result, "\""); - return result; + int i; + + if (len < 0) + len = strlen(s); + + putchar('"'); + for (i = 0; i < len; ++i) { + unsigned char c = s[i]; + + switch (c) { + case '\n': + printf("\\n"); + break; + case '"': + printf("\\\""); + break; + case '\\': + printf("\\\\"); + break; + default: + putchar((int)c); + } + } + putchar('"'); } // Functions to pretty-print inline and block lists, for debugging. // Prettyprint an inline list, for debugging. extern void print_blocks(block* b, int indent) { - struct ListData * data; - while(b != NULL) { - // printf("%3d %3d %3d| ", b->start_line, b->start_column, b->end_line); - for (int i=0; i < indent; i++) { - putchar(' '); - } - switch(b->tag) { - case document: - printf("document\n"); - print_blocks(b->children, indent + 2); - break; - case block_quote: - printf("block_quote\n"); - print_blocks(b->children, indent + 2); - break; - case list_item: - data = &(b->attributes.list_data); - printf("list_item\n"); - print_blocks(b->children, indent + 2); - break; - case list: - data = &(b->attributes.list_data); - if (data->list_type == ordered) { - printf("list (type=ordered tight=%s start=%d delim=%s)\n", - (data->tight ? "true" : "false"), - data->start, - (data->delimiter == parens ? "parens" : "period")); - } else { - printf("list (type=bullet tight=%s bullet_char=%c)\n", - (data->tight ? "true" : "false"), - data->bullet_char); - } - print_blocks(b->children, indent + 2); - break; - case atx_header: - printf("atx_header (level=%d)\n", b->attributes.header_level); - print_inlines(b->inline_content, indent + 2); - break; - case setext_header: - printf("setext_header (level=%d)\n", b->attributes.header_level); - print_inlines(b->inline_content, indent + 2); - break; - case paragraph: - printf("paragraph\n"); - print_inlines(b->inline_content, indent + 2); - break; - case hrule: - printf("hrule\n"); - break; - case indented_code: - printf("indented_code %s\n", format_str(b->string_content)->data); - break; - case fenced_code: - printf("fenced_code length=%d info=%s %s\n", - b->attributes.fenced_code_data.fence_length, - format_str(b->attributes.fenced_code_data.info)->data, - format_str(b->string_content)->data); - break; - case html_block: - printf("html_block %s\n", format_str(b->string_content)->data); - break; - case reference_def: - printf("reference_def\n"); - break; - default: - log_warn("block type %d not implemented\n", b->tag); - break; - } - b = b->next; - } + struct ListData *data; + + while(b != NULL) { + // printf("%3d %3d %3d| ", b->start_line, b->start_column, b->end_line); + for (int i=0; i < indent; i++) { + putchar(' '); + } + + switch(b->tag) { + case document: + printf("document\n"); + print_blocks(b->children, indent + 2); + break; + case block_quote: + printf("block_quote\n"); + print_blocks(b->children, indent + 2); + break; + case list_item: + data = &(b->attributes.list_data); + printf("list_item\n"); + print_blocks(b->children, indent + 2); + break; + case list: + data = &(b->attributes.list_data); + if (data->list_type == ordered) { + printf("list (type=ordered tight=%s start=%d delim=%s)\n", + (data->tight ? "true" : "false"), + data->start, + (data->delimiter == parens ? "parens" : "period")); + } else { + printf("list (type=bullet tight=%s bullet_char=%c)\n", + (data->tight ? "true" : "false"), + data->bullet_char); + } + print_blocks(b->children, indent + 2); + break; + case atx_header: + printf("atx_header (level=%d)\n", b->attributes.header_level); + print_inlines(b->inline_content, indent + 2); + break; + case setext_header: + printf("setext_header (level=%d)\n", b->attributes.header_level); + print_inlines(b->inline_content, indent + 2); + break; + case paragraph: + printf("paragraph\n"); + print_inlines(b->inline_content, indent + 2); + break; + case hrule: + printf("hrule\n"); + break; + case indented_code: + printf("indented_code "); + print_str(b->string_content.ptr, -1); + putchar('\n'); + break; + case fenced_code: + printf("fenced_code length=%d info=", + b->attributes.fenced_code_data.fence_length); + print_str(b->attributes.fenced_code_data.info.ptr, -1); + putchar(' '); + print_str(b->string_content.ptr, -1); + putchar('\n'); + break; + case html_block: + printf("html_block "); + print_str(b->string_content.ptr, -1); + putchar('\n'); + break; + case reference_def: + printf("reference_def\n"); + break; + default: + printf("# NOT IMPLEMENTED (%d)\n", b->tag); + break; + } + b = b->next; + } } // Prettyprint an inline list, for debugging. extern void print_inlines(inl* ils, int indent) { - while(ils != NULL) { - /* - // we add 11 extra spaces for the line/column info - for (int i=0; i < 11; i++) { - putchar(' '); - } - putchar('|'); - putchar(' '); - */ - for (int i=0; i < indent; i++) { - putchar(' '); - } - switch(ils->tag) { - case str: - printf("str %s\n", format_str(ils->content.literal)->data); - break; - case linebreak: - printf("linebreak\n"); - break; - case softbreak: - printf("softbreak\n"); - break; - case code: - printf("code %s\n", format_str(ils->content.literal)->data); - break; - case raw_html: - printf("html %s\n", format_str(ils->content.literal)->data); - break; - case entity: - printf("entity %s\n", format_str(ils->content.literal)->data); - break; - case link: - printf("link url=%s title=%s\n", - format_str(ils->content.linkable.url)->data, - format_str(ils->content.linkable.title)->data); - print_inlines(ils->content.linkable.label, indent + 2); - break; - case image: - printf("image url=%s title=%s\n", - format_str(ils->content.linkable.url)->data, - format_str(ils->content.linkable.title)->data); - print_inlines(ils->content.linkable.label, indent + 2); - break; - case strong: - printf("strong\n"); - print_inlines(ils->content.linkable.label, indent + 2); - break; - case emph: - printf("emph\n"); - print_inlines(ils->content.linkable.label, indent + 2); - break; - } - ils = ils->next; - } + while(ils != NULL) { + for (int i=0; i < indent; i++) { + putchar(' '); + } + switch(ils->tag) { + case str: + printf("str "); + print_str(ils->content.literal.data, ils->content.literal.len); + putchar('\n'); + break; + case linebreak: + printf("linebreak\n"); + break; + case softbreak: + printf("softbreak\n"); + break; + case code: + printf("code "); + print_str(ils->content.literal.data, ils->content.literal.len); + putchar('\n'); + break; + case raw_html: + printf("html "); + print_str(ils->content.literal.data, ils->content.literal.len); + putchar('\n'); + break; + case entity: + printf("entity "); + print_str(ils->content.literal.data, ils->content.literal.len); + putchar('\n'); + break; + case link: + case image: + printf("%s url=", ils->tag == link ? "link" : "image"); + print_str(ils->content.linkable.url, -1); + if (ils->content.linkable.title) { + printf(" title="); + print_str(ils->content.linkable.title, -1); + } + putchar('\n'); + print_inlines(ils->content.linkable.label, indent + 2); + break; + case strong: + printf("strong\n"); + print_inlines(ils->content.linkable.label, indent + 2); + break; + case emph: + printf("emph\n"); + print_inlines(ils->content.linkable.label, indent + 2); + break; + } + ils = ils->next; + } } diff --git a/src/stmd.h b/src/stmd.h index eb1b989..dc24235 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -105,19 +105,14 @@ extern block* add_child(block* parent, int block_type, int start_line, int start_column); void free_blocks(block* e); -block *stmd_parse_document(const char *buffer, size_t len); - -// FOR NOW: -void process_inlines(block* cur, reference** refmap); -void incorporate_line(gh_buf *ln, int line_number, block** curptr); -void finalize(block* b, int line_number); +extern block *stmd_parse_document(const unsigned char *buffer, size_t len); +extern block *stmd_parse_file(FILE *f); void print_inlines(inl* ils, int indent); void print_blocks(block* blk, int indent); -/* TODO */ -// int blocks_to_html(block* b, bstring* result, bool tight); -// int inlines_to_html(inl* b, bstring* result); +void blocks_to_html(gh_buf *html, block *b, bool tight); +void inlines_to_html(gh_buf *html, inl *b); void utf8proc_case_fold(gh_buf *dest, const unsigned char *str, int len); diff --git a/src/utf8.c b/src/utf8.c index 1a5df9e..e3f8dd3 100644 --- a/src/utf8.c +++ b/src/utf8.c @@ -1,6 +1,8 @@ #include -#include "bstrlib.h" -#include "debug.h" +#include +#include + +#include "stmd.h" static const int8_t utf8proc_utf8class[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, diff --git a/src/utf8.h b/src/utf8.h deleted file mode 100644 index fe59a90..0000000 --- a/src/utf8.h +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include "bstrlib.h" - -extern unsigned char * from_utf8(unsigned char * s, unsigned int *n); -extern int to_utf8(unsigned int c, bstring dest); -extern bstring case_fold(bstring source); -- cgit v1.2.3 From 24248c0f1a6de6f229890c5c03aeff8738214fee Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 2 Sep 2014 13:30:13 +0200 Subject: Rename inlines --- src/inlines.c | 50 +++++++++++++++++++++++++------------------------- src/print.c | 22 +++++++++++----------- src/stmd.h | 4 ++-- 3 files changed, 38 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/inlines.c b/src/inlines.c index 82c7219..b9ece0e 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -151,15 +151,15 @@ inline static inl* make_simple(int t) } // Macros for creating various kinds of inlines. -#define make_str(s) make_literal(str, s) -#define make_code(s) make_literal(code, s) -#define make_raw_html(s) make_literal(raw_html, s) -#define make_entity(s) make_literal(entity, s) -#define make_linebreak() make_simple(linebreak) -#define make_softbreak() make_simple(softbreak) -#define make_link(label, url, title) make_linkable(link, label, url, title) -#define make_emph(contents) make_inlines(emph, contents) -#define make_strong(contents) make_inlines(strong, contents) +#define make_str(s) make_literal(INL_STRING, s) +#define make_code(s) make_literal(INL_CODE, s) +#define make_raw_html(s) make_literal(INL_RAW_HTML, s) +#define make_entity(s) make_literal(INL_ENTITY, s) +#define make_linebreak() make_simple(INL_LINEBREAK) +#define make_softbreak() make_simple(INL_SOFTBREAK) +#define make_link(label, url, title) make_linkable(INL_LINK, label, url, title) +#define make_emph(contents) make_inlines(INL_EMPH, contents) +#define make_strong(contents) make_inlines(INL_STRONG, contents) // Free an inline list. extern void free_inlines(inl* e) @@ -167,23 +167,23 @@ extern void free_inlines(inl* e) inl * next; while (e != NULL) { switch (e->tag){ - case str: - case raw_html: - case code: - case entity: + case INL_STRING: + case INL_RAW_HTML: + case INL_CODE: + case INL_ENTITY: chunk_free(&e->content.literal); break; - case linebreak: - case softbreak: + case INL_LINEBREAK: + case INL_SOFTBREAK: break; - case link: - case image: + case INL_LINK: + case INL_IMAGE: free(e->content.linkable.url); free(e->content.linkable.title); free_inlines(e->content.linkable.label); break; - case emph: - case strong: + case INL_EMPH: + case INL_STRONG: free_inlines(e->content.inlines); break; default: @@ -454,7 +454,7 @@ static inl* handle_strong_emph(subject* subj, char c) numdelims = scan_delims(subj, c, &can_open, &can_close); if (numdelims >= 1 && can_close) { subj->pos += 1; - first_head->tag = emph; + first_head->tag = INL_EMPH; chunk_free(&first_head->content.literal); first_head->content.inlines = first_head->next; first_head->next = NULL; @@ -471,7 +471,7 @@ static inl* handle_strong_emph(subject* subj, char c) numdelims = scan_delims(subj, c, &can_open, &can_close); if (numdelims >= 2 && can_close) { subj->pos += 2; - first_head->tag = strong; + first_head->tag = INL_STRONG; chunk_free(&first_head->content.literal); first_head->content.inlines = first_head->next; first_head->next = NULL; @@ -502,10 +502,10 @@ static inl* handle_strong_emph(subject* subj, char c) } subj->pos += numdelims; if (first_close) { - first_head->tag = first_close_delims == 1 ? strong : emph; + first_head->tag = first_close_delims == 1 ? INL_STRONG : INL_EMPH; chunk_free(&first_head->content.literal); first_head->content.inlines = - make_inlines(first_close_delims == 1 ? emph : strong, + make_inlines(first_close_delims == 1 ? INL_EMPH : INL_STRONG, first_head->next); il = first_head->next; @@ -989,8 +989,8 @@ static int parse_inline(subject* subj, inl ** last) advance(subj); if (peek_char(subj) == '[') { new = handle_left_bracket(subj); - if (new != NULL && new->tag == link) { - new->tag = image; + if (new != NULL && new->tag == INL_LINK) { + new->tag = INL_IMAGE; } else { new = append_inlines(make_str(chunk_literal("!")), new); } diff --git a/src/print.c b/src/print.c index 3ebde16..0a87925 100644 --- a/src/print.c +++ b/src/print.c @@ -124,35 +124,35 @@ extern void print_inlines(inl* ils, int indent) putchar(' '); } switch(ils->tag) { - case str: + case INL_STRING: printf("str "); print_str(ils->content.literal.data, ils->content.literal.len); putchar('\n'); break; - case linebreak: + case INL_LINEBREAK: printf("linebreak\n"); break; - case softbreak: + case INL_SOFTBREAK: printf("softbreak\n"); break; - case code: + case INL_CODE: printf("code "); print_str(ils->content.literal.data, ils->content.literal.len); putchar('\n'); break; - case raw_html: + case INL_RAW_HTML: printf("html "); print_str(ils->content.literal.data, ils->content.literal.len); putchar('\n'); break; - case entity: + case INL_ENTITY: printf("entity "); print_str(ils->content.literal.data, ils->content.literal.len); putchar('\n'); break; - case link: - case image: - printf("%s url=", ils->tag == link ? "link" : "image"); + case INL_LINK: + case INL_IMAGE: + printf("%s url=", ils->tag == INL_LINK ? "link" : "image"); print_str(ils->content.linkable.url, -1); if (ils->content.linkable.title) { printf(" title="); @@ -161,11 +161,11 @@ extern void print_inlines(inl* ils, int indent) putchar('\n'); print_inlines(ils->content.linkable.label, indent + 2); break; - case strong: + case INL_STRONG: printf("strong\n"); print_inlines(ils->content.linkable.label, indent + 2); break; - case emph: + case INL_EMPH: printf("emph\n"); print_inlines(ils->content.linkable.label, indent + 2); break; diff --git a/src/stmd.h b/src/stmd.h index dc24235..1e490d6 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -12,8 +12,8 @@ typedef struct { } chunk; typedef struct Inline { - enum { str, softbreak, linebreak, code, raw_html, entity, - emph, strong, link, image } tag; + enum { INL_STRING, INL_SOFTBREAK, INL_LINEBREAK, INL_CODE, INL_RAW_HTML, INL_ENTITY, + INL_EMPH, INL_STRONG, INL_LINK, INL_IMAGE } tag; union { chunk literal; struct Inline *inlines; -- cgit v1.2.3 From c28af79329264a7cf331a1b1c414919e4ed9e9f9 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 2 Sep 2014 13:37:34 +0200 Subject: It buiiiilds --- src/blocks.c | 11 ++- src/buffer.c | 6 +- src/html/houdini.h | 44 ++++++++++ src/html/houdini_href_e.c | 115 +++++++++++++++++++++++++ src/html/houdini_html_e.c | 89 +++++++++++++++++++ src/html/html.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++ src/stmd.h | 1 + src/utf8.c | 7 +- 8 files changed, 473 insertions(+), 12 deletions(-) create mode 100644 src/html/houdini.h create mode 100644 src/html/houdini_href_e.c create mode 100644 src/html/houdini_html_e.c create mode 100644 src/html/html.c (limited to 'src') diff --git a/src/blocks.c b/src/blocks.c index 71dc830..42f20db 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -8,6 +8,7 @@ #include "scanners.h" #include "uthash.h" +static void incorporate_line(gh_buf *ln, int line_number, block** curptr); static void finalize(block* b, int line_number); static block* make_block(int tag, int start_line, int start_column) @@ -390,7 +391,7 @@ static void expand_tabs(gh_buf *ob, const unsigned char *line, size_t size) } } -static block *finalize_parsing(block *document, int linenum) +static block *finalize_document(block *document, int linenum) { while (document != document->top) { finalize(document, linenum); @@ -411,7 +412,7 @@ extern block *stmd_parse_file(FILE *f) block *document = make_document(); while (fgets((char *)buffer, sizeof(buffer), f)) { - expand_tabs(&line, buffer, strlen(buffer)); + expand_tabs(&line, buffer, strlen((char *)buffer)); incorporate_line(&line, linenum, &document); gh_buf_clear(&line); linenum++; @@ -429,7 +430,7 @@ extern block *stmd_parse_document(const unsigned char *buffer, size_t len) block *document = make_document(); while (buffer < end) { - const char *eol = memchr(buffer, '\n', end - buffer); + const unsigned char *eol = memchr(buffer, '\n', end - buffer); if (!eol) { expand_tabs(&line, buffer, end - buffer); @@ -449,9 +450,7 @@ extern block *stmd_parse_document(const unsigned char *buffer, size_t len) } // Process one line at a time, modifying a block. -// Returns 0 if successful. curptr is changed to point to -// the currently open block. -extern void incorporate_line(gh_buf *ln, int line_number, block** curptr) +static void incorporate_line(gh_buf *ln, int line_number, block** curptr) { block* last_matched_container; int offset = 0; diff --git a/src/buffer.c b/src/buffer.c index 17dc864..cfc6a7e 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -245,11 +245,11 @@ int gh_buf_cmp(const gh_buf *a, const gh_buf *b) int gh_buf_strchr(const gh_buf *buf, int c, int pos) { - const char *p = memchr(buf->ptr + pos, c, buf->size - pos); + const unsigned char *p = memchr(buf->ptr + pos, c, buf->size - pos); if (!p) return -1; - return (int)(p - buf->ptr); + return (int)(p - (const unsigned char *)buf->ptr); } int gh_buf_strrchr(const gh_buf *buf, int c, int pos) @@ -264,7 +264,7 @@ int gh_buf_strrchr(const gh_buf *buf, int c, int pos) return -1; } -void gh_buf_truncate(gh_buf *buf, size_t len) +void gh_buf_truncate(gh_buf *buf, int len) { if (len < buf->size) { buf->size = len; diff --git a/src/html/houdini.h b/src/html/houdini.h new file mode 100644 index 0000000..31fe917 --- /dev/null +++ b/src/html/houdini.h @@ -0,0 +1,44 @@ +#ifndef __HOUDINI_H__ +#define __HOUDINI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "buffer.h" + +#define likely(x) __builtin_expect((x),1) +#define unlikely(x) __builtin_expect((x),0) + +#ifdef HOUDINI_USE_LOCALE +# define _isxdigit(c) isxdigit(c) +# define _isdigit(c) isdigit(c) +#else +/* + * Helper _isdigit methods -- do not trust the current locale + * */ +# define _isxdigit(c) (strchr("0123456789ABCDEFabcdef", (c)) != NULL) +# define _isdigit(c) ((c) >= '0' && (c) <= '9') +#endif + +#define HOUDINI_ESCAPED_SIZE(x) (((x) * 12) / 10) +#define HOUDINI_UNESCAPED_SIZE(x) (x) + +extern int houdini_escape_html(gh_buf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_html0(gh_buf *ob, const uint8_t *src, size_t size, int secure); +extern int houdini_unescape_html(gh_buf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_xml(gh_buf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_uri(gh_buf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_url(gh_buf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_href(gh_buf *ob, const uint8_t *src, size_t size); +extern int houdini_unescape_uri(gh_buf *ob, const uint8_t *src, size_t size); +extern int houdini_unescape_url(gh_buf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_js(gh_buf *ob, const uint8_t *src, size_t size); +extern int houdini_unescape_js(gh_buf *ob, const uint8_t *src, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/html/houdini_href_e.c b/src/html/houdini_href_e.c new file mode 100644 index 0000000..59fe850 --- /dev/null +++ b/src/html/houdini_href_e.c @@ -0,0 +1,115 @@ +#include +#include +#include + +#include "html/houdini.h" + +/* + * The following characters will not be escaped: + * + * -_.+!*'(),%#@?=;:/,+&$ alphanum + * + * Note that this character set is the addition of: + * + * - The characters which are safe to be in an URL + * - The characters which are *not* safe to be in + * an URL because they are RESERVED characters. + * + * We asume (lazily) that any RESERVED char that + * appears inside an URL is actually meant to + * have its native function (i.e. as an URL + * component/separator) and hence needs no escaping. + * + * There are two exceptions: the chacters & (amp) + * and ' (single quote) do not appear in the table. + * They are meant to appear in the URL as components, + * yet they require special HTML-entity escaping + * to generate valid HTML markup. + * + * All other characters will be escaped to %XX. + * + */ +static const char HREF_SAFE[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 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, 1, + 0, 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, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +int +houdini_escape_href(gh_buf *ob, const uint8_t *src, size_t size) +{ + static const uint8_t hex_chars[] = "0123456789ABCDEF"; + size_t i = 0, org; + uint8_t hex_str[3]; + + hex_str[0] = '%'; + + while (i < size) { + org = i; + while (i < size && HREF_SAFE[src[i]] != 0) + i++; + + if (likely(i > org)) { + if (unlikely(org == 0)) { + if (i >= size) + return 0; + + gh_buf_grow(ob, HOUDINI_ESCAPED_SIZE(size)); + } + + gh_buf_put(ob, src + org, i - org); + } + + /* escaping */ + if (i >= size) + break; + + switch (src[i]) { + /* amp appears all the time in URLs, but needs + * HTML-entity escaping to be inside an href */ + case '&': + gh_buf_puts(ob, "&"); + break; + + /* the single quote is a valid URL character + * according to the standard; it needs HTML + * entity escaping too */ + case '\'': + gh_buf_puts(ob, "'"); + break; + + /* the space can be escaped to %20 or a plus + * sign. we're going with the generic escape + * for now. the plus thing is more commonly seen + * when building GET strings */ +#if 0 + case ' ': + gh_buf_putc(ob, '+'); + break; +#endif + + /* every other character goes with a %XX escaping */ + default: + hex_str[1] = hex_chars[(src[i] >> 4) & 0xF]; + hex_str[2] = hex_chars[src[i] & 0xF]; + gh_buf_put(ob, hex_str, 3); + } + + i++; + } + + return 1; +} diff --git a/src/html/houdini_html_e.c b/src/html/houdini_html_e.c new file mode 100644 index 0000000..316c5ce --- /dev/null +++ b/src/html/houdini_html_e.c @@ -0,0 +1,89 @@ +#include +#include +#include + +#include "html/houdini.h" + +/** + * According to the OWASP rules: + * + * & --> & + * < --> < + * > --> > + * " --> " + * ' --> ' ' is not recommended + * / --> / forward slash is included as it helps end an HTML entity + * + */ +static const char HTML_ESCAPE_TABLE[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const char *HTML_ESCAPES[] = { + "", + """, + "&", + "'", + "/", + "<", + ">" +}; + +int +houdini_escape_html0(gh_buf *ob, const uint8_t *src, size_t size, int secure) +{ + size_t i = 0, org, esc = 0; + + while (i < size) { + org = i; + while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0) + i++; + + if (i > org) { + if (unlikely(org == 0)) { + if (i >= size) + return 0; + + gh_buf_grow(ob, HOUDINI_ESCAPED_SIZE(size)); + } + + gh_buf_put(ob, src + org, i - org); + } + + /* escaping */ + if (unlikely(i >= size)) + break; + + /* The forward slash is only escaped in secure mode */ + if (src[i] == '/' && !secure) { + gh_buf_putc(ob, '/'); + } else { + gh_buf_puts(ob, HTML_ESCAPES[esc]); + } + + i++; + } + + return 1; +} + +int +houdini_escape_html(gh_buf *ob, const uint8_t *src, size_t size) +{ + return houdini_escape_html0(ob, src, size, 1); +} diff --git a/src/html/html.c b/src/html/html.c new file mode 100644 index 0000000..2f160ca --- /dev/null +++ b/src/html/html.c @@ -0,0 +1,212 @@ +#include +#include +#include +#include +#include + +#include "stmd.h" +#include "debug.h" +#include "scanners.h" +#include "html/houdini.h" + +// Functions to convert block and inline lists to HTML strings. + +static void escape_html(gh_buf *dest, const unsigned char *source, int length) +{ + if (length < 0) + length = strlen((char *)source); + + houdini_escape_html0(dest, source, (size_t)length, 0); +} + +static void escape_href(gh_buf *dest, const unsigned char *source, int length) +{ + if (length < 0) + length = strlen((char *)source); + + houdini_escape_href(dest, source, (size_t)length); +} + +static inline void cr(gh_buf *html) +{ + if (html->size && html->ptr[html->size - 1] != '\n') + gh_buf_putc(html, '\n'); +} + +// Convert a block list to HTML. Returns 0 on success, and sets result. +void blocks_to_html(gh_buf *html, block *b, bool tight) +{ + struct ListData *data; + + while(b != NULL) { + switch(b->tag) { + case document: + blocks_to_html(html, b->children, false); + break; + + case paragraph: + if (tight) { + inlines_to_html(html, b->inline_content); + } else { + cr(html); + gh_buf_puts(html, "

    "); + inlines_to_html(html, b->inline_content); + gh_buf_puts(html, "

    "); + cr(html); + } + break; + + case block_quote: + cr(html); + gh_buf_puts(html, "
    "); + blocks_to_html(html, b->children, false); + gh_buf_puts(html, "
    "); + cr(html); + break; + + case list_item: + cr(html); + gh_buf_puts(html, "
  • "); + blocks_to_html(html, b->children, tight); + gh_buf_trim(html); + gh_buf_puts(html, "
  • "); + cr(html); + break; + + case list: + // make sure a list starts at the beginning of the line: + cr(html); + data = &(b->attributes.list_data); + + if (data->start > 1) { + gh_buf_printf(html, "<%s start=\"%d\">\n", + data->list_type == bullet ? "ul" : "ol", + data->start); + } else { + gh_buf_puts(html, data->list_type == bullet ? "
      \n" : "
        \n"); + } + + blocks_to_html(html, b->children, data->tight); + gh_buf_puts(html, data->list_type == bullet ? "
    " : ""); + cr(html); + break; + + case atx_header: + case setext_header: + cr(html); + gh_buf_printf(html, "", b->attributes.header_level); + inlines_to_html(html, b->inline_content); + gh_buf_printf(html, "", b->attributes.header_level); + cr(html); + break; + + case indented_code: + case fenced_code: + /* TODO: fenced code lang attributes */ + cr(html); + gh_buf_puts(html, "
    ");
    +				escape_html(html, b->string_content.ptr, b->string_content.size);
    +				gh_buf_puts(html, "
    "); + cr(html); + break; + + case html_block: + gh_buf_put(html, b->string_content.ptr, b->string_content.size); + break; + + case hrule: + gh_buf_puts(html, "
    "); + cr(html); + break; + + case reference_def: + break; + + default: + assert(false); + } + + b = b->next; + } +} + +// Convert an inline list to HTML. Returns 0 on success, and sets result. +void inlines_to_html(gh_buf *html, inl* ils) +{ + gh_buf scrap = GH_BUF_INIT; + + while(ils != NULL) { + switch(ils->tag) { + case INL_STRING: + escape_html(html, ils->content.literal.data, ils->content.literal.len); + break; + + case INL_LINEBREAK: + gh_buf_puts(html, "
    \n"); + break; + + case INL_SOFTBREAK: + gh_buf_putc(html, '\n'); + break; + + case INL_CODE: + gh_buf_puts(html, ""); + escape_html(html, ils->content.literal.data, ils->content.literal.len); + gh_buf_puts(html, ""); + break; + + case INL_RAW_HTML: + case INL_ENTITY: + gh_buf_put(html, + ils->content.literal.data, + ils->content.literal.len); + break; + + case INL_LINK: + gh_buf_puts(html, "content.linkable.url, -1); + + if (ils->content.linkable.title) { + gh_buf_puts(html, "\" title=\""); + escape_html(html, ils->content.linkable.title, -1); + } + + gh_buf_puts(html, "\">"); + inlines_to_html(html, ils->content.inlines); + gh_buf_puts(html, ""); + break; + + case INL_IMAGE: + gh_buf_puts(html, "content.linkable.url, -1); + + inlines_to_html(&scrap, ils->content.inlines); + if (scrap.size) { + gh_buf_puts(html, "\" alt=\""); + escape_html(html, scrap.ptr, scrap.size); + } + gh_buf_clear(&scrap); + + if (ils->content.linkable.title) { + gh_buf_puts(html, "\" title=\""); + escape_html(html, ils->content.linkable.title, -1); + } + + gh_buf_puts(html, "\"/>"); + break; + + case INL_STRONG: + gh_buf_puts(html, ""); + inlines_to_html(html, ils->content.inlines); + gh_buf_puts(html, ""); + break; + + case INL_EMPH: + gh_buf_puts(html, ""); + inlines_to_html(html, ils->content.inlines); + gh_buf_puts(html, ""); + break; + } + ils = ils->next; + } +} diff --git a/src/stmd.h b/src/stmd.h index 1e490d6..3e284bd 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -1,4 +1,5 @@ #include +#include #include "buffer.h" #include "uthash.h" diff --git a/src/utf8.c b/src/utf8.c index e3f8dd3..32c78a4 100644 --- a/src/utf8.c +++ b/src/utf8.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "stmd.h" @@ -83,9 +84,9 @@ ssize_t utf8proc_iterate(const uint8_t *str, ssize_t str_len, int32_t *dst) return length; } -void utf8_encode_char(int32_t uc, gh_buf *buf) +void utf8proc_encode_char(int32_t uc, gh_buf *buf) { - char dst[4]; + unsigned char dst[4]; int len = 0; if (uc < 0x00) { @@ -99,7 +100,7 @@ void utf8_encode_char(int32_t uc, gh_buf *buf) len = 2; } else if (uc == 0xFFFF) { dst[0] = 0xFF; - return 1; + len = 1; } else if (uc == 0xFFFE) { dst[0] = 0xFE; len = 1; -- cgit v1.2.3 From 7e12fdba0c9a444a3cfc29c520e2f2caa57a8232 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 2 Sep 2014 14:15:24 +0200 Subject: NO SEGFAULTS KTHX --- src/inlines.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/inlines.c b/src/inlines.c index b9ece0e..7b48ad9 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -84,7 +84,7 @@ extern reference* lookup_reference(reference** refmap, chunk *label) if (refmap != NULL) { HASH_FIND_STR(*refmap, (char*)norm, ref); } - free(label); + free(norm); return ref; } @@ -262,7 +262,7 @@ inline static unsigned char *chunk_to_cstr(chunk *c) inline static chunk chunk_literal(const char *data) { - chunk c = {data, strlen(data), 0}; + chunk c = {data, data ? strlen(data) : 0, 0}; return c; } @@ -937,6 +937,7 @@ static int find_special_char(subject *subj) while (n < size) { if (strchr("\n\\`&_*[]buffer, n))) return n; + n++; } return -1; @@ -974,7 +975,9 @@ static int parse_inline(subject* subj, inl ** last) case '_': if (subj->pos > 0 && (isalnum(gh_buf_at(subj->buffer, subj->pos - 1)) || gh_buf_at(subj->buffer, subj->pos - 1) == '_')) { - goto text_literal; + new = make_str(chunk_literal("_")); + advance(subj); + break; } new = handle_strong_emph(subj, '_'); -- cgit v1.2.3 From a7314deae649646f1f7ce5ede972641b5b62538c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 3 Sep 2014 03:40:23 +0200 Subject: 338/103 --- Makefile | 4 +- src/blocks.c | 173 +++++++++++++++++----------------- src/buffer.c | 26 ++++- src/buffer.h | 2 +- src/html/houdini_href_e.c | 10 +- src/html/houdini_html_e.c | 10 +- src/html/html.c | 4 +- src/inlines.c | 235 ++++++++++++++++++---------------------------- src/print.c | 2 +- src/scanners.h | 28 +++--- src/scanners.re | 85 +++++++---------- src/stmd.h | 16 ++-- 12 files changed, 261 insertions(+), 334 deletions(-) (limited to 'src') diff --git a/Makefile b/Makefile index d14a928..89ec68c 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -CFLAGS=-ggdb3 -O0 -Wall -Wextra -std=c99 -Isrc $(OPTFLAGS) -LDFLAGS=-ggdb3 -O0 -Wall -Werror +CFLAGS=-ggdb3 -O0 -Wall -Wextra -Wno-unused-variable -std=c99 -Isrc $(OPTFLAGS) +LDFLAGS=-ggdb3 -O0 -Wall -Wno-unused-variable # -Werror SRCDIR=src DATADIR=data diff --git a/src/blocks.c b/src/blocks.c index 42f20db..94ff986 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -8,6 +8,8 @@ #include "scanners.h" #include "uthash.h" +#define peek_at(i, n) (i)->data[n] + static void incorporate_line(gh_buf *ln, int line_number, block** curptr); static void finalize(block* b, int line_number); @@ -27,7 +29,6 @@ static block* make_block(int tag, int start_line, int start_column) e->top = NULL; e->attributes.refmap = NULL; gh_buf_init(&e->string_content, 32); - e->string_pos = 0; e->inline_content = NULL; e->next = NULL; e->prev = NULL; @@ -80,10 +81,10 @@ static inline bool accepts_lines(int block_type) block_type == fenced_code); } -static void add_line(block* block, gh_buf *ln, int offset) +static void add_line(block* block, chunk *ch, int offset) { assert(block->open); - gh_buf_put(&block->string_content, ln->ptr + offset, ln->size - offset); + gh_buf_put(&block->string_content, ch->data + offset, ch->len - offset); } static void remove_trailing_blank_lines(gh_buf *ln) @@ -104,7 +105,7 @@ static void remove_trailing_blank_lines(gh_buf *ln) i = gh_buf_strchr(ln, '\n', i); if (i >= 0) - gh_buf_truncate(ln, i + 1); + gh_buf_truncate(ln, i); } // Check to see if a block ends with a blank line, descending @@ -162,12 +163,12 @@ static void finalize(block* b, int line_number) switch (b->tag) { case paragraph: pos = 0; - while (gh_buf_at(&b->string_content, b->string_pos) == '[' && - (pos = parse_reference(&b->string_content, b->string_pos, - b->top->attributes.refmap))) { - b->string_pos = pos; + while (gh_buf_at(&b->string_content, 0) == '[' && + (pos = parse_reference(&b->string_content, b->top->attributes.refmap))) { + + gh_buf_drop(&b->string_content, pos); } - if (is_blank(&b->string_content, b->string_pos)) { + if (is_blank(&b->string_content, 0)) { b->tag = reference_def; } break; @@ -179,14 +180,16 @@ static void finalize(block* b, int line_number) case fenced_code: // first line of contents becomes info - firstlinelen = gh_buf_strchr(&b->string_content, '\n', b->string_pos); + firstlinelen = gh_buf_strchr(&b->string_content, '\n', 0); + + gh_buf_init(&b->attributes.fenced_code_data.info, 0); gh_buf_set( &b->attributes.fenced_code_data.info, - b->string_content.ptr + b->string_pos, + b->string_content.ptr, firstlinelen ); - b->string_pos = firstlinelen + 1; + gh_buf_drop(&b->string_content, firstlinelen + 1); gh_buf_trim(&b->attributes.fenced_code_data.info); unescape_buffer(&b->attributes.fenced_code_data.info); @@ -281,7 +284,7 @@ void process_inlines(block* cur, reference** refmap) case paragraph: case atx_header: case setext_header: - cur->inline_content = parse_inlines(&cur->string_content, cur->string_pos, refmap); + cur->inline_content = parse_inlines(&cur->string_content, refmap); // MEM // gh_buf_free(&cur->string_content); break; @@ -300,19 +303,18 @@ void process_inlines(block* cur, reference** refmap) // Attempts to parse a list item marker (bullet or enumerated). // On success, returns length of the marker, and populates // data with the details. On failure, returns 0. -static int parse_list_marker(gh_buf *ln, int pos, - struct ListData ** dataptr) +static int parse_list_marker(chunk *input, int pos, struct ListData ** dataptr) { - char c; + unsigned char c; int startpos; struct ListData * data; startpos = pos; - c = gh_buf_at(ln, pos); + c = peek_at(input, pos); - if ((c == '*' || c == '-' || c == '+') && !scan_hrule(ln, pos)) { + if ((c == '*' || c == '-' || c == '+') && !scan_hrule(input, pos)) { pos++; - if (!isspace(gh_buf_at(ln, pos))) { + if (!isspace(peek_at(input, pos))) { return 0; } data = malloc(sizeof(struct ListData)); @@ -327,14 +329,14 @@ static int parse_list_marker(gh_buf *ln, int pos, int start = 0; do { - start = (10 * start) + (gh_buf_at(ln, pos) - '0'); + start = (10 * start) + (peek_at(input, pos) - '0'); pos++; - } while (isdigit(gh_buf_at(ln, pos))); + } while (isdigit(peek_at(input, pos))); - c = gh_buf_at(ln, pos); + c = peek_at(input, pos); if (c == '.' || c == ')') { pos++; - if (!isspace(gh_buf_at(ln, pos))) { + if (!isspace(peek_at(input, pos))) { return 0; } data = malloc(sizeof(struct ListData)); @@ -449,8 +451,26 @@ extern block *stmd_parse_document(const unsigned char *buffer, size_t len) return finalize_document(document, linenum); } +static void chop_trailing_hashtags(chunk *ch) +{ + int n; + + chunk_rtrim(ch); + n = ch->len - 1; + + // if string ends in #s, remove these: + while (n >= 0 && peek_at(ch, n) == '#') + n--; + + // the last # was escaped, so we include it. + if (n >= 0 && peek_at(ch, n) == '\\') + n++; + + ch->len = n + 1; +} + // Process one line at a time, modifying a block. -static void incorporate_line(gh_buf *ln, int line_number, block** curptr) +static void incorporate_line(gh_buf *line, int line_number, block** curptr) { block* last_matched_container; int offset = 0; @@ -464,6 +484,10 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr) bool blank = false; int first_nonspace; int indent; + chunk input; + + input.data = line->ptr; + input.len = line->size; // container starts at the document root. container = cur->top; @@ -475,21 +499,19 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr) container = container->last_child; first_nonspace = offset; - while (gh_buf_at(ln, first_nonspace) == ' ') { + while (peek_at(&input, first_nonspace) == ' ') { first_nonspace++; } indent = first_nonspace - offset; - blank = gh_buf_at(ln, first_nonspace) == '\n'; + blank = peek_at(&input, first_nonspace) == '\n'; if (container->tag == block_quote) { - - matched = indent <= 3 && gh_buf_at(ln, first_nonspace) == '>'; + matched = indent <= 3 && peek_at(&input, first_nonspace) == '>'; if (matched) { offset = first_nonspace + 1; - if (gh_buf_at(ln, offset) == ' ') { + if (peek_at(&input, offset) == ' ') offset++; - } } else { all_matched = false; } @@ -526,7 +548,7 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr) // skip optional spaces of fence offset i = container->attributes.fenced_code_data.fence_offset; - while (i > 0 && gh_buf_at(ln, offset) == ' ') { + while (i > 0 && peek_at(&input, offset) == ' ') { offset++; i--; } @@ -564,15 +586,13 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr) container->tag != html_block) { first_nonspace = offset; - while (gh_buf_at(ln, first_nonspace) == ' ') { + while (peek_at(&input, first_nonspace) == ' ') first_nonspace++; - } indent = first_nonspace - offset; - blank = gh_buf_at(ln, first_nonspace) == '\n'; + blank = peek_at(&input, first_nonspace) == '\n'; if (indent >= CODE_INDENT) { - if (cur->tag != paragraph && !blank) { offset += CODE_INDENT; container = add_child(container, indented_code, line_number, offset + 1); @@ -580,76 +600,70 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr) break; } - } else if (gh_buf_at(ln, first_nonspace) == '>') { + } else if (peek_at(&input, first_nonspace) == '>') { offset = first_nonspace + 1; // optional following character - if (gh_buf_at(ln, offset) == ' ') { + if (peek_at(&input, offset) == ' ') offset++; - } container = add_child(container, block_quote, line_number, offset + 1); - } else if ((matched = scan_atx_header_start(ln, first_nonspace))) { + } else if ((matched = scan_atx_header_start(&input, first_nonspace))) { offset = first_nonspace + matched; container = add_child(container, atx_header, line_number, offset + 1); - int hashpos = gh_buf_strchr(ln, '#', first_nonspace); - assert(hashpos >= 0); - + int hashpos = chunk_strchr(&input, '#', first_nonspace); int level = 0; - while (gh_buf_at(ln, hashpos) == '#') { + + while (peek_at(&input, hashpos) == '#') { level++; hashpos++; } container->attributes.header_level = level; - } else if ((matched = scan_open_code_fence(ln, first_nonspace))) { + } else if ((matched = scan_open_code_fence(&input, first_nonspace))) { - container = add_child(container, fenced_code, line_number, - first_nonspace + 1); - container->attributes.fenced_code_data.fence_char = gh_buf_at(ln, - first_nonspace); + container = add_child(container, fenced_code, line_number, first_nonspace + 1); + container->attributes.fenced_code_data.fence_char = peek_at(&input, first_nonspace); container->attributes.fenced_code_data.fence_length = matched; - container->attributes.fenced_code_data.fence_offset = - first_nonspace - offset; + container->attributes.fenced_code_data.fence_offset = first_nonspace - offset; offset = first_nonspace + matched; - } else if ((matched = scan_html_block_tag(ln, first_nonspace))) { + } else if ((matched = scan_html_block_tag(&input, first_nonspace))) { - container = add_child(container, html_block, line_number, - first_nonspace + 1); + container = add_child(container, html_block, line_number, first_nonspace + 1); // note, we don't adjust offset because the tag is part of the text } else if (container->tag == paragraph && - (lev = scan_setext_header_line(ln, first_nonspace)) && + (lev = scan_setext_header_line(&input, first_nonspace)) && // check that there is only one line in the paragraph: gh_buf_strrchr(&container->string_content, '\n', gh_buf_len(&container->string_content) - 2) < 0) { container->tag = setext_header; container->attributes.header_level = lev; - offset = gh_buf_len(ln) - 1; + offset = input.len - 1; } else if (!(container->tag == paragraph && !all_matched) && - (matched = scan_hrule(ln, first_nonspace))) { + (matched = scan_hrule(&input, first_nonspace))) { // it's only now that we know the line is not part of a setext header: container = add_child(container, hrule, line_number, first_nonspace + 1); finalize(container, line_number); container = container->parent; - offset = gh_buf_len(ln) - 1; + offset = input.len - 1; - } else if ((matched = parse_list_marker(ln, first_nonspace, &data))) { + } else if ((matched = parse_list_marker(&input, first_nonspace, &data))) { // compute padding: offset = first_nonspace + matched; i = 0; - while (i <= 5 && gh_buf_at(ln, offset + i) == ' ') { + while (i <= 5 && peek_at(&input, offset + i) == ' ') { i++; } // i = number of spaces after marker, up to 5 - if (i >= 5 || i < 1 || gh_buf_at(ln, offset) == '\n') { + if (i >= 5 || i < 1 || peek_at(&input, offset) == '\n') { data->padding = matched + 1; if (i > 0) { offset += 1; @@ -674,6 +688,7 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr) // add the list item container = add_child(container, list_item, line_number, first_nonspace + 1); + /* TODO: static */ container->attributes.list_data = *data; free(data); @@ -691,12 +706,11 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr) // appropriate container. first_nonspace = offset; - while (gh_buf_at(ln, first_nonspace) == ' ') { + while (peek_at(&input, first_nonspace) == ' ') first_nonspace++; - } indent = first_nonspace - offset; - blank = gh_buf_at(ln, first_nonspace) == '\n'; + blank = peek_at(&input, first_nonspace) == '\n'; // block quote lines are never blank as they start with > // and we don't count blanks in fenced code for purposes of tight/loose @@ -721,13 +735,12 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr) cur->tag == paragraph && gh_buf_len(&cur->string_content) > 0) { - add_line(cur, ln, offset); + add_line(cur, &input, offset); } else { // not a lazy continuation // finalize any blocks that were not matched and set cur to container: while (cur != last_matched_container) { - finalize(cur, line_number); cur = cur->parent; assert(cur != NULL); @@ -735,58 +748,46 @@ static void incorporate_line(gh_buf *ln, int line_number, block** curptr) if (container->tag == indented_code) { - add_line(container, ln, offset); + add_line(container, &input, offset); } else if (container->tag == fenced_code) { matched = (indent <= 3 - && gh_buf_at(ln, first_nonspace) == container->attributes.fenced_code_data.fence_char) - && scan_close_code_fence(ln, first_nonspace, + && peek_at(&input, first_nonspace) == container->attributes.fenced_code_data.fence_char) + && scan_close_code_fence(&input, first_nonspace, container->attributes.fenced_code_data.fence_length); if (matched) { // if closing fence, don't add line to container; instead, close it: finalize(container, line_number); container = container->parent; // back up to parent } else { - add_line(container, ln, offset); + add_line(container, &input, offset); } } else if (container->tag == html_block) { - add_line(container, ln, offset); + add_line(container, &input, offset); } else if (blank) { // ??? do nothing } else if (container->tag == atx_header) { - // chop off trailing ###s...use a scanner? - gh_buf_trim(ln); - int p = gh_buf_len(ln) - 1; - - // if string ends in #s, remove these: - while (gh_buf_at(ln, p) == '#') { - p--; - } - if (gh_buf_at(ln, p) == '\\') { - // the last # was escaped, so we include it. - p++; - } - gh_buf_truncate(ln, p + 1); - add_line(container, ln, first_nonspace); + chop_trailing_hashtags(&input); + add_line(container, &input, first_nonspace); finalize(container, line_number); container = container->parent; } else if (accepts_lines(container->tag)) { - add_line(container, ln, first_nonspace); + add_line(container, &input, first_nonspace); } else if (container->tag != hrule && container->tag != setext_header) { // create paragraph container for line container = add_child(container, paragraph, line_number, first_nonspace + 1); - add_line(container, ln, first_nonspace); + add_line(container, &input, first_nonspace); } else { assert(false); diff --git a/src/buffer.c b/src/buffer.c index cfc6a7e..dc4a405 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -95,7 +95,7 @@ void gh_buf_clear(gh_buf *buf) int gh_buf_set(gh_buf *buf, const unsigned char *data, int len) { - if (len == 0 || data == NULL) { + if (len <= 0 || data == NULL) { gh_buf_clear(buf); } else { if (data != buf->ptr) { @@ -125,6 +125,9 @@ int gh_buf_putc(gh_buf *buf, int c) int gh_buf_put(gh_buf *buf, const unsigned char *data, int len) { + if (len <= 0) + return 0; + ENSURE_SIZE(buf, buf->size + len + 1); memmove(buf->ptr + buf->size, data, len); buf->size += len; @@ -272,15 +275,28 @@ void gh_buf_truncate(gh_buf *buf, int len) } } +void gh_buf_drop(gh_buf *buf, int n) +{ + if (n > 0) { + buf->size = buf->size - n; + if (buf->size) + memmove(buf->ptr, buf->ptr + n, buf->size); + + buf->ptr[buf->size] = '\0'; + } +} + void gh_buf_trim(gh_buf *buf) { - /* TODO: leading whitespace? */ - /* + int i = 0; + + if (!buf->size) + return; + while (i < buf->size && isspace(buf->ptr[i])) i++; - gh_buf_truncate(buf, i); - */ + gh_buf_drop(buf, i); /* rtrim */ while (buf->size > 0) { diff --git a/src/buffer.h b/src/buffer.h index 422ef02..0d5143e 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -105,8 +105,8 @@ extern void gh_buf_clear(gh_buf *buf); int gh_buf_strchr(const gh_buf *buf, int c, int pos); int gh_buf_strrchr(const gh_buf *buf, int c, int pos); +void gh_buf_drop(gh_buf *buf, int n); void gh_buf_truncate(gh_buf *buf, int len); -void gh_buf_ltruncate(gh_buf *buf, int len); void gh_buf_trim(gh_buf *buf); #endif diff --git a/src/html/houdini_href_e.c b/src/html/houdini_href_e.c index 59fe850..b2a7d79 100644 --- a/src/html/houdini_href_e.c +++ b/src/html/houdini_href_e.c @@ -62,16 +62,8 @@ houdini_escape_href(gh_buf *ob, const uint8_t *src, size_t size) while (i < size && HREF_SAFE[src[i]] != 0) i++; - if (likely(i > org)) { - if (unlikely(org == 0)) { - if (i >= size) - return 0; - - gh_buf_grow(ob, HOUDINI_ESCAPED_SIZE(size)); - } - + if (likely(i > org)) gh_buf_put(ob, src + org, i - org); - } /* escaping */ if (i >= size) diff --git a/src/html/houdini_html_e.c b/src/html/houdini_html_e.c index 316c5ce..5cdd3dd 100644 --- a/src/html/houdini_html_e.c +++ b/src/html/houdini_html_e.c @@ -54,16 +54,8 @@ houdini_escape_html0(gh_buf *ob, const uint8_t *src, size_t size, int secure) while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0) i++; - if (i > org) { - if (unlikely(org == 0)) { - if (i >= size) - return 0; - - gh_buf_grow(ob, HOUDINI_ESCAPED_SIZE(size)); - } - + if (i > org) gh_buf_put(ob, src + org, i - org); - } /* escaping */ if (unlikely(i >= size)) diff --git a/src/html/html.c b/src/html/html.c index 2f160ca..27ffe58 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -68,7 +68,7 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) cr(html); gh_buf_puts(html, "
  • "); blocks_to_html(html, b->children, tight); - gh_buf_trim(html); + gh_buf_trim(html); /* TODO: rtrim */ gh_buf_puts(html, "
  • "); cr(html); break; @@ -106,7 +106,7 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) cr(html); gh_buf_puts(html, "
    ");
     				escape_html(html, b->string_content.ptr, b->string_content.size);
    -				gh_buf_puts(html, "
    "); + gh_buf_puts(html, ""); cr(html); break; diff --git a/src/inlines.c b/src/inlines.c index 7b48ad9..ef27a24 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -9,10 +9,10 @@ #include "scanners.h" typedef struct Subject { - const gh_buf *buffer; - int pos; - reference** reference_map; - int label_nestlevel; + chunk input; + int pos; + int label_nestlevel; + reference** reference_map; } subject; reference* lookup_reference(reference** refmap, chunk *label); @@ -27,12 +27,16 @@ inline static void chunk_trim(chunk *c); inline static chunk chunk_literal(const char *data); inline static chunk chunk_buf_detach(gh_buf *buf); -inline static chunk chunk_buf(const gh_buf *buf, int pos, int len); +inline static chunk chunk_dup(const chunk *ch, int pos, int len); static inl *parse_chunk_inlines(chunk *chunk, reference** refmap); static inl *parse_inlines_while(subject* subj, int (*f)(subject*)); static int parse_inline(subject* subj, inl ** last); +static void subject_from_chunk(subject *e, chunk *chunk, reference** refmap); +static void subject_from_buf(subject *e, gh_buf *buffer, reference** refmap); +static int subject_find_special_char(subject *subj); + extern void free_reference(reference *ref) { free(ref->label); free(ref->url); @@ -101,10 +105,12 @@ extern reference* make_reference(chunk *label, chunk *url, chunk *title) extern void add_reference(reference** refmap, reference* ref) { reference * t = NULL; - HASH_FIND(hh, *refmap, (char*)ref->label, (unsigned)strlen(ref->label), t); + const char *label = (const char *)ref->label; + + HASH_FIND(hh, *refmap, label, strlen(label), t); if (t == NULL) { - HASH_ADD_KEYPTR(hh, *refmap, (char*)ref->label, (unsigned)strlen(ref->label), ref); + HASH_ADD_KEYPTR(hh, *refmap, label, strlen(label), ref); } else { free_reference(ref); // we free this now since it won't be in the refmap } @@ -210,87 +216,49 @@ inline static inl* append_inlines(inl* a, inl* b) return a; } -// Make a 'subject' from an input string. -static void init_subject(subject *e, gh_buf *buffer, int input_pos, reference** refmap) +static void subject_from_buf(subject *e, gh_buf *buffer, reference** refmap) { - e->buffer = buffer; - e->pos = input_pos; + e->input.data = buffer->ptr; + e->input.len = buffer->size; + e->input.alloc = 0; + e->pos = 0; e->label_nestlevel = 0; e->reference_map = refmap; -} - -inline static int isbacktick(int c) -{ - return (c == '`'); -} - -inline static void chunk_free(chunk *c) -{ - if (c->alloc) - free((char *)c->data); - - c->data = NULL; - c->alloc = 0; - c->len = 0; -} - -inline static void chunk_trim(chunk *c) -{ - while (c->len && isspace(c->data[0])) { - c->data++; - c->len--; - } - - while (c->len > 0) { - if (!isspace(c->data[c->len - 1])) - break; - c->len--; - } + chunk_rtrim(&e->input); } -inline static unsigned char *chunk_to_cstr(chunk *c) +static void subject_from_chunk(subject *e, chunk *chunk, reference** refmap) { - unsigned char *str; - - str = malloc(c->len + 1); - memcpy(str, c->data, c->len); - str[c->len] = 0; + e->input.data = chunk->data; + e->input.len = chunk->len; + e->input.alloc = 0; + e->pos = 0; + e->label_nestlevel = 0; + e->reference_map = refmap; - return str; + chunk_rtrim(&e->input); } -inline static chunk chunk_literal(const char *data) +inline static int isbacktick(int c) { - chunk c = {data, data ? strlen(data) : 0, 0}; - return c; + return (c == '`'); } -inline static chunk chunk_buf(const gh_buf *buf, int pos, int len) +static inline unsigned char peek_char(subject *subj) { - chunk c = {buf->ptr + pos, len, 0}; - return c; + return (subj->pos < subj->input.len) ? subj->input.data[subj->pos] : 0; } -inline static chunk chunk_buf_detach(gh_buf *buf) +static inline unsigned char peek_at(subject *subj, int pos) { - chunk c; - - c.len = buf->size; - c.data = gh_buf_detach(buf); - c.alloc = 1; - - return c; + return subj->input.data[pos]; } -// Return the next character in the subject, without advancing. -// Return 0 if at the end of the subject. -#define peek_char(subj) gh_buf_at((subj)->buffer, (subj)->pos) - // Return true if there are more characters in the subject. inline static int is_eof(subject* subj) { - return (subj->pos >= gh_buf_len(subj->buffer)); + return (subj->pos >= subj->input.len); } // Advance the subject. Doesn't check for eof. @@ -308,7 +276,7 @@ inline static chunk take_while(subject* subj, int (*f)(int)) len++; } - return chunk_buf(subj->buffer, startpos, len); + return chunk_dup(&subj->input, startpos, len); } // Try to process a backtick code span that began with a @@ -388,7 +356,7 @@ static inl* handle_backticks(subject *subj) } else { gh_buf buf = GH_BUF_INIT; - gh_buf_set(&buf, subj->buffer->ptr + startpos, endpos - startpos - openticks.len); + gh_buf_set(&buf, subj->input.data + startpos, endpos - startpos - openticks.len); gh_buf_trim(&buf); normalize_whitespace(&buf); @@ -404,7 +372,7 @@ static int scan_delims(subject* subj, char c, bool * can_open, bool * can_close) char char_before, char_after; int startpos = subj->pos; - char_before = subj->pos == 0 ? '\n' : gh_buf_at(subj->buffer, subj->pos - 1); + char_before = subj->pos == 0 ? '\n' : peek_at(subj, subj->pos - 1); while (peek_char(subj) == c) { numdelims++; advance(subj); @@ -439,7 +407,7 @@ static inl* handle_strong_emph(subject* subj, char c) numdelims = scan_delims(subj, c, &can_open, &can_close); subj->pos += numdelims; - new = make_str(chunk_buf(subj->buffer, subj->pos - numdelims, numdelims)); + new = make_str(chunk_dup(&subj->input, subj->pos - numdelims, numdelims)); *last = new; first_head = new; result = new; @@ -488,7 +456,7 @@ static inl* handle_strong_emph(subject* subj, char c) numdelims = scan_delims(subj, c, &can_open, &can_close); if (can_close && numdelims >= 1 && numdelims <= 3 && numdelims != first_close_delims) { - new = make_str(chunk_buf(subj->buffer, subj->pos, numdelims)); + new = make_str(chunk_dup(&subj->input, subj->pos, numdelims)); append_inlines(*last, new); *last = new; if (first_close_delims == 1 && numdelims > 2) { @@ -554,7 +522,7 @@ static inl* handle_backslash(subject *subj) unsigned char nextchar = peek_char(subj); if (ispunct(nextchar)) { // only ascii symbols and newline can be escaped advance(subj); - return make_str(chunk_buf(subj->buffer, subj->pos - 1, 1)); + return make_str(chunk_dup(&subj->input, subj->pos - 1, 1)); } else if (nextchar == '\n') { advance(subj); return make_linebreak(); @@ -569,9 +537,9 @@ static inl* handle_entity(subject* subj) { int match; inl *result; - match = scan_entity(subj->buffer, subj->pos); + match = scan_entity(&subj->input, subj->pos); if (match) { - result = make_entity(chunk_buf(subj->buffer, subj->pos, match)); + result = make_entity(chunk_dup(&subj->input, subj->pos, match)); subj->pos += match; } else { advance(subj); @@ -584,15 +552,13 @@ static inl* handle_entity(subject* subj) // Returns an inline sequence consisting of str and entity elements. static inl *make_str_with_entities(chunk *content) { - inl * result = NULL; - inl * new; + inl *result = NULL; + inl *new; int searchpos; char c; subject subj; - gh_buf content_buf = GH_BUF_INIT; - gh_buf_set(&content_buf, content->data, content->len); - init_subject(&subj, &content_buf, 0, NULL); + subject_from_chunk(&subj, content, NULL); while ((c = peek_char(&subj))) { switch (c) { @@ -600,18 +566,13 @@ static inl *make_str_with_entities(chunk *content) new = handle_entity(&subj); break; default: - searchpos = gh_buf_strchr(subj.buffer, '&', subj.pos); - if (searchpos < 0) { - searchpos = gh_buf_len(subj.buffer); - } - - new = make_str(chunk_buf(subj.buffer, subj.pos, searchpos - subj.pos)); + searchpos = chunk_strchr(&subj.input, '&', subj.pos); + new = make_str(chunk_dup(&subj.input, subj.pos, searchpos - subj.pos)); subj.pos = searchpos; } result = append_inlines(result, new); } - gh_buf_free(&content_buf); return result; } @@ -678,9 +639,9 @@ static inl* handle_pointy_brace(subject* subj) advance(subj); // advance past first < // first try to match a URL autolink - matchlen = scan_autolink_uri(subj->buffer, subj->pos); + matchlen = scan_autolink_uri(&subj->input, subj->pos); if (matchlen > 0) { - contents = chunk_buf(subj->buffer, subj->pos, matchlen - 1); + contents = chunk_dup(&subj->input, subj->pos, matchlen - 1); subj->pos += matchlen; return make_link( @@ -691,11 +652,11 @@ static inl* handle_pointy_brace(subject* subj) } // next try to match an email autolink - matchlen = scan_autolink_email(subj->buffer, subj->pos); + matchlen = scan_autolink_email(&subj->input, subj->pos); if (matchlen > 0) { gh_buf mail_url = GH_BUF_INIT; - contents = chunk_buf(subj->buffer, subj->pos, matchlen - 1); + contents = chunk_dup(&subj->input, subj->pos, matchlen - 1); subj->pos += matchlen; gh_buf_puts(&mail_url, "mailto:"); @@ -709,9 +670,9 @@ static inl* handle_pointy_brace(subject* subj) } // finally, try to match an html tag - matchlen = scan_html_tag(subj->buffer, subj->pos); + matchlen = scan_html_tag(&subj->input, subj->pos); if (matchlen > 0) { - contents = chunk_buf(subj->buffer, subj->pos - 1, matchlen + 1); + contents = chunk_dup(&subj->input, subj->pos - 1, matchlen + 1); subj->pos += matchlen; return make_raw_html(contents); } @@ -776,12 +737,7 @@ static int link_label(subject* subj, chunk *raw_label) } } if (c == ']') { - *raw_label = chunk_buf( - subj->buffer, - startpos + 1, - subj->pos - (startpos + 1) - ); - + *raw_label = chunk_dup(&subj->input, startpos + 1, subj->pos - (startpos + 1)); subj->label_nestlevel = 0; advance(subj); // advance past ] return 1; @@ -813,25 +769,25 @@ static inl* handle_left_bracket(subject* subj) if (found_label) { if (peek_char(subj) == '(' && - ((sps = scan_spacechars(subj->buffer, subj->pos + 1)) > -1) && - ((n = scan_link_url(subj->buffer, subj->pos + 1 + sps)) > -1)) { + ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) && + ((n = scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) { // try to parse an explicit link: starturl = subj->pos + 1 + sps; // after ( endurl = starturl + n; - starttitle = endurl + scan_spacechars(subj->buffer, endurl); + starttitle = endurl + scan_spacechars(&subj->input, endurl); // ensure there are spaces btw url and title endtitle = (starttitle == endurl) ? starttitle : - starttitle + scan_link_title(subj->buffer, starttitle); + starttitle + scan_link_title(&subj->input, starttitle); - endall = endtitle + scan_spacechars(subj->buffer, endtitle); + endall = endtitle + scan_spacechars(&subj->input, endtitle); - if (gh_buf_at(subj->buffer, endall) == ')') { + if (peek_at(subj, endall) == ')') { subj->pos = endall + 1; - url = chunk_buf(subj->buffer, starturl, endurl - starturl); - title = chunk_buf(subj->buffer, starttitle, endtitle - starttitle); + url = chunk_dup(&subj->input, starturl, endurl - starturl); + title = chunk_dup(&subj->input, starttitle, endtitle - starttitle); lab = parse_chunk_inlines(&rawlabel, NULL); return make_link(lab, url, title); @@ -850,7 +806,7 @@ static inl* handle_left_bracket(subject* subj) // Check for reference link. // First, see if there's another label: - subj->pos = subj->pos + scan_spacechars(subj->buffer, endlabel); + subj->pos = subj->pos + scan_spacechars(&subj->input, endlabel); reflabel = rawlabel; // if followed by a nonempty link label, we change reflabel to it: @@ -892,8 +848,8 @@ static inl* handle_newline(subject *subj) advance(subj); } if (nlpos > 1 && - gh_buf_at(subj->buffer, nlpos - 1) == ' ' && - gh_buf_at(subj->buffer, nlpos - 2) == ' ') { + peek_at(subj, nlpos - 1) == ' ' && + peek_at(subj, nlpos - 2) == ' ') { return make_linebreak(); } else { return make_softbreak(); @@ -917,30 +873,22 @@ extern inl* parse_inlines_while(subject* subj, int (*f)(subject*)) inl *parse_chunk_inlines(chunk *chunk, reference** refmap) { - inl *result; subject subj; - gh_buf full_chunk = GH_BUF_INIT; - - gh_buf_set(&full_chunk, chunk->data, chunk->len); - init_subject(&subj, &full_chunk, 0, refmap); - result = parse_inlines_while(&subj, not_eof); - - gh_buf_free(&full_chunk); - return result; + subject_from_chunk(&subj, chunk, refmap); + return parse_inlines_while(&subj, not_eof); } -static int find_special_char(subject *subj) +static int subject_find_special_char(subject *subj) { int n = subj->pos + 1; - int size = (int)gh_buf_len(subj->buffer); - while (n < size) { - if (strchr("\n\\`&_*[]buffer, n))) + while (n < subj->input.len) { + if (strchr("\n\\`&_*[]input.data[n])) return n; n++; } - return -1; + return subj->input.len; } // Parse an inline, advancing subject, and add it to last element. @@ -973,11 +921,13 @@ static int parse_inline(subject* subj, inl ** last) new = handle_pointy_brace(subj); break; case '_': - if (subj->pos > 0 && (isalnum(gh_buf_at(subj->buffer, subj->pos - 1)) || - gh_buf_at(subj->buffer, subj->pos - 1) == '_')) { - new = make_str(chunk_literal("_")); - advance(subj); - break; + if (subj->pos > 0) { + unsigned char prev = peek_at(subj, subj->pos - 1); + if (isalnum(prev) || prev == '_') { + new = make_str(chunk_literal("_")); + advance(subj); + break; + } } new = handle_strong_emph(subj, '_'); @@ -1002,18 +952,13 @@ static int parse_inline(subject* subj, inl ** last) } break; default: - text_literal: - endpos = find_special_char(subj); - if (endpos < 0) { - endpos = gh_buf_len(subj->buffer); - } - - contents = chunk_buf(subj->buffer, subj->pos, endpos - subj->pos); + endpos = subject_find_special_char(subj); + contents = chunk_dup(&subj->input, subj->pos, endpos - subj->pos); subj->pos = endpos; // if we're at a newline, strip trailing spaces. if (peek_char(subj) == '\n') { - chunk_trim(&contents); + chunk_rtrim(&contents); } new = make_str(contents); @@ -1026,10 +971,10 @@ static int parse_inline(subject* subj, inl ** last) return 1; } -extern inl* parse_inlines(gh_buf *input, int input_pos, reference** refmap) +extern inl* parse_inlines(gh_buf *input, reference** refmap) { subject subj; - init_subject(&subj, input, input_pos, refmap); + subject_from_buf(&subj, input, refmap); return parse_inlines_while(&subj, not_eof); } @@ -1048,7 +993,7 @@ void spnl(subject* subj) // Modify refmap if a reference is encountered. // Return 0 if no reference found, otherwise position of subject // after reference is parsed. -extern int parse_reference(gh_buf *input, int input_pos, reference** refmap) +extern int parse_reference(gh_buf *input, reference** refmap) { subject subj; @@ -1058,9 +1003,9 @@ extern int parse_reference(gh_buf *input, int input_pos, reference** refmap) int matchlen = 0; int beforetitle; - reference * new = NULL; + reference *new = NULL; - init_subject(&subj, input, input_pos, NULL); + subject_from_buf(&subj, input, NULL); // parse label: if (!link_label(&subj, &lab)) @@ -1075,9 +1020,9 @@ extern int parse_reference(gh_buf *input, int input_pos, reference** refmap) // parse link url: spnl(&subj); - matchlen = scan_link_url(subj.buffer, subj.pos); + matchlen = scan_link_url(&subj.input, subj.pos); if (matchlen) { - url = chunk_buf(subj.buffer, subj.pos, matchlen); + url = chunk_dup(&subj.input, subj.pos, matchlen); subj.pos += matchlen; } else { return 0; @@ -1086,9 +1031,9 @@ extern int parse_reference(gh_buf *input, int input_pos, reference** refmap) // parse optional link_title beforetitle = subj.pos; spnl(&subj); - matchlen = scan_link_title(subj.buffer, subj.pos); + matchlen = scan_link_title(&subj.input, subj.pos); if (matchlen) { - title = chunk_buf(subj.buffer, subj.pos, matchlen); + title = chunk_dup(&subj.input, subj.pos, matchlen); subj.pos += matchlen; } else { subj.pos = beforetitle; diff --git a/src/print.c b/src/print.c index 0a87925..c262995 100644 --- a/src/print.c +++ b/src/print.c @@ -9,7 +9,7 @@ static void print_str(const unsigned char *s, int len) int i; if (len < 0) - len = strlen(s); + len = strlen((char *)s); putchar('"'); for (i = 0; i < len; ++i) { diff --git a/src/scanners.h b/src/scanners.h index b6e586b..f96c42d 100644 --- a/src/scanners.h +++ b/src/scanners.h @@ -1,15 +1,15 @@ -#include "buffer.h" +#include "stmd.h" -int scan_autolink_uri(const gh_buf *s, int pos); -int scan_autolink_email(const gh_buf *s, int pos); -int scan_html_tag(const gh_buf *s, int pos); -int scan_html_block_tag(const gh_buf *s, int pos); -int scan_link_url(const gh_buf *s, int pos); -int scan_link_title(const gh_buf *s, int pos); -int scan_spacechars(const gh_buf *s, int pos); -int scan_atx_header_start(const gh_buf *s, int pos); -int scan_setext_header_line(const gh_buf *s, int pos); -int scan_hrule(const gh_buf *s, int pos); -int scan_open_code_fence(const gh_buf *s, int pos); -int scan_close_code_fence(const gh_buf *s, int pos, int len); -int scan_entity(const gh_buf *s, int pos); +int scan_autolink_uri(chunk *c, int offset); +int scan_autolink_email(chunk *c, int offset); +int scan_html_tag(chunk *c, int offset); +int scan_html_block_tag(chunk *c, int offset); +int scan_link_url(chunk *c, int offset); +int scan_link_title(chunk *c, int offset); +int scan_spacechars(chunk *c, int offset); +int scan_atx_header_start(chunk *c, int offset); +int scan_setext_header_line(chunk *c, int offset); +int scan_hrule(chunk *c, int offset); +int scan_open_code_fence(chunk *c, int offset); +int scan_close_code_fence(chunk *c, int offset, int len); +int scan_entity(chunk *c, int offset); diff --git a/src/scanners.re b/src/scanners.re index 7323ef9..5ac7c15 100644 --- a/src/scanners.re +++ b/src/scanners.re @@ -1,8 +1,15 @@ -#include "buffer.h" +#include "scanners.h" + +#define SCAN_DATA \ + const unsigned char *marker = NULL; \ + const unsigned char *p = c->data + offset; \ + const unsigned char *start = p; \ + const unsigned char *end = c->data + c->len /*!re2c re2c:define:YYCTYPE = "unsigned char"; re2c:define:YYCURSOR = p; + re2c:define:YYLIMIT = end; re2c:define:YYMARKER = marker; re2c:define:YYCTXMARKER = marker; re2c:yyfill:enable = 0; @@ -55,11 +62,9 @@ */ // Try to match URI autolink after first <, returning number of chars matched. -extern int scan_autolink_uri(const gh_buf *s, int pos) +extern int scan_autolink_uri(chunk *c, int offset) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c scheme [:]([^\x00-\x20<>\\]|escaped_char)*[>] { return (p - start); } .? { return 0; } @@ -67,11 +72,9 @@ extern int scan_autolink_uri(const gh_buf *s, int pos) } // Try to match email autolink after first <, returning num of chars matched. -extern int scan_autolink_email(const gh_buf *s, int pos) +extern int scan_autolink_email(chunk *c, int offset) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c [a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+ [@] @@ -83,11 +86,9 @@ extern int scan_autolink_email(const gh_buf *s, int pos) } // Try to match an HTML tag after first <, returning num of chars matched. -extern int scan_html_tag(const gh_buf *s, int pos) +extern int scan_html_tag(chunk *c, int offset) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c htmltag { return (p - start); } .? { return 0; } @@ -96,11 +97,9 @@ extern int scan_html_tag(const gh_buf *s, int pos) // Try to match an HTML block tag including first <, // returning num of chars matched. -extern int scan_html_block_tag(const gh_buf *s, int pos) +extern int scan_html_block_tag(chunk *c, int offset) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c [<] [/] blocktagname (spacechar | [>]) { return (p - start); } [<] blocktagname (spacechar | [/>]) { return (p - start); } @@ -113,11 +112,9 @@ extern int scan_html_block_tag(const gh_buf *s, int pos) // This may optionally be contained in <..>; otherwise // whitespace and unbalanced right parentheses aren't allowed. // Newlines aren't ever allowed. -extern int scan_link_url(const gh_buf *s, int pos) +extern int scan_link_url(chunk *c, int offset) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c [ \n]* [<] ([^<>\n\\\x00] | escaped_char | [\\])* [>] { return (p - start); } [ \n]* (reg_char+ | escaped_char | in_parens_nosp)* { return (p - start); } @@ -128,11 +125,9 @@ extern int scan_link_url(const gh_buf *s, int pos) // Try to match a link title (in single quotes, in double quotes, or // in parentheses), returning number of chars matched. Allow one // level of internal nesting (quotes within quotes). -extern int scan_link_title(const gh_buf *s, int pos) +extern int scan_link_title(chunk *c, int offset) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c ["] (escaped_char|[^"\x00])* ["] { return (p - start); } ['] (escaped_char|[^'\x00])* ['] { return (p - start); } @@ -142,10 +137,9 @@ extern int scan_link_title(const gh_buf *s, int pos) } // Match space characters, including newlines. -extern int scan_spacechars(const gh_buf *s, int pos) +extern int scan_spacechars(chunk *c, int offset) { - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c [ \t\n]* { return (p - start); } . { return 0; } @@ -153,11 +147,9 @@ extern int scan_spacechars(const gh_buf *s, int pos) } // Match ATX header start. -extern int scan_atx_header_start(const gh_buf *s, int pos) +extern int scan_atx_header_start(chunk *c, int offset) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c [#]{1,6} ([ ]+|[\n]) { return (p - start); } .? { return 0; } @@ -166,10 +158,9 @@ extern int scan_atx_header_start(const gh_buf *s, int pos) // Match sexext header line. Return 1 for level-1 header, // 2 for level-2, 0 for no match. -extern int scan_setext_header_line(const gh_buf *s, int pos) +extern int scan_setext_header_line(chunk *c, int offset) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); + SCAN_DATA; /*!re2c [=]+ [ ]* [\n] { return 1; } [-]+ [ ]* [\n] { return 2; } @@ -180,11 +171,9 @@ extern int scan_setext_header_line(const gh_buf *s, int pos) // Scan a horizontal rule line: "...three or more hyphens, asterisks, // or underscores on a line by themselves. If you wish, you may use // spaces between the hyphens or asterisks." -extern int scan_hrule(const gh_buf *s, int pos) +extern int scan_hrule(chunk *c, int offset) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c ([*][ ]*){3,} [ \t]* [\n] { return (p - start); } ([_][ ]*){3,} [ \t]* [\n] { return (p - start); } @@ -194,11 +183,9 @@ extern int scan_hrule(const gh_buf *s, int pos) } // Scan an opening code fence. -extern int scan_open_code_fence(const gh_buf *s, int pos) +extern int scan_open_code_fence(chunk *c, int offset) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c [`]{3,} / [^`\n\x00]*[\n] { return (p - start); } [~]{3,} / [^~\n\x00]*[\n] { return (p - start); } @@ -207,11 +194,9 @@ extern int scan_open_code_fence(const gh_buf *s, int pos) } // Scan a closing code fence with length at least len. -extern int scan_close_code_fence(const gh_buf *s, int pos, int len) +extern int scan_close_code_fence(chunk *c, int offset, int len) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c ([`]{3,} | [~]{3,}) / spacechar* [\n] { if (p - start > len) { @@ -225,11 +210,9 @@ extern int scan_close_code_fence(const gh_buf *s, int pos, int len) // Scans an entity. // Returns number of chars matched. -extern int scan_entity(const gh_buf *s, int pos) +extern int scan_entity(chunk *c, int offset) { - unsigned char * marker = NULL; - unsigned char * p = &(s->ptr[pos]); - unsigned char * start = p; + SCAN_DATA; /*!re2c [&] ([#] ([Xx][A-Fa-f0-9]{1,8}|[0-9]{1,8}) |[A-Za-z][A-Za-z0-9]{1,31} ) [;] { return (p - start); } diff --git a/src/stmd.h b/src/stmd.h index 3e284bd..4a3c399 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -1,17 +1,15 @@ +#ifndef _STDMD_H_ +#define _STDMD_H_ + #include #include #include "buffer.h" +#include "chunk.h" #include "uthash.h" #define VERSION "0.1" #define CODE_INDENT 4 -typedef struct { - const unsigned char *data; - int len; - int alloc; -} chunk; - typedef struct Inline { enum { INL_STRING, INL_SOFTBREAK, INL_LINEBREAK, INL_CODE, INL_RAW_HTML, INL_ENTITY, INL_EMPH, INL_STRONG, INL_LINK, INL_IMAGE } tag; @@ -79,7 +77,6 @@ typedef struct Block { struct Block* parent; struct Block* top; gh_buf string_content; - int string_pos; inl* inline_content; union { struct ListData list_data; @@ -91,10 +88,10 @@ typedef struct Block { struct Block * prev; } block; -inl* parse_inlines(gh_buf *input, int input_pos, reference** refmap); +inl* parse_inlines(gh_buf *input, reference** refmap); void free_inlines(inl* e); -int parse_reference(gh_buf *input, int input_pos, reference** refmap); +int parse_reference(gh_buf *input, reference** refmap); void free_reference(reference *ref); void free_reference_map(reference **refmap); @@ -117,3 +114,4 @@ void inlines_to_html(gh_buf *html, inl *b); void utf8proc_case_fold(gh_buf *dest, const unsigned char *str, int len); +#endif -- cgit v1.2.3 From 460d46c62b0675f2fab6f103bb9f0d185a73eebb Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 3 Sep 2014 03:40:53 +0200 Subject: Add chunk.h --- src/chunk.h | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/chunk.h (limited to 'src') diff --git a/src/chunk.h b/src/chunk.h new file mode 100644 index 0000000..f3841ed --- /dev/null +++ b/src/chunk.h @@ -0,0 +1,92 @@ +#ifndef _CHUNK_H_ +#define _CHUNK_H_ + +#include +#include +#include +#include +#include "buffer.h" + +typedef struct { + const unsigned char *data; + int len; + int alloc; +} chunk; + +static inline void chunk_free(chunk *c) +{ + if (c->alloc) + free((char *)c->data); + + c->data = NULL; + c->alloc = 0; + c->len = 0; +} + +static inline void chunk_ltrim(chunk *c) +{ + assert(!c->alloc); + + while (c->len && isspace(c->data[0])) { + c->data++; + c->len--; + } +} + +static inline void chunk_rtrim(chunk *c) +{ + while (c->len > 0) { + if (!isspace(c->data[c->len - 1])) + break; + + c->len--; + } +} + +static inline void chunk_trim(chunk *c) +{ + chunk_ltrim(c); + chunk_rtrim(c); +} + +static inline int chunk_strchr(chunk *ch, int c, int offset) +{ + const unsigned char *p = memchr(ch->data + offset, c, ch->len - offset); + return p ? (int)(p - ch->data) : ch->len; +} + +static inline unsigned char *chunk_to_cstr(chunk *c) +{ + unsigned char *str; + + str = malloc(c->len + 1); + memcpy(str, c->data, c->len); + str[c->len] = 0; + + return str; +} + +static inline chunk chunk_literal(const char *data) +{ + chunk c = {(const unsigned char *)data, data ? strlen(data) : 0, 0}; + return c; +} + +static inline chunk chunk_dup(const chunk *ch, int pos, int len) +{ + chunk c = {ch->data + pos, len, 0}; + return c; +} + +static inline chunk chunk_buf_detach(gh_buf *buf) +{ + chunk c; + + c.len = buf->size; + c.data = gh_buf_detach(buf); + c.alloc = 1; + + return c; +} + +#endif -- cgit v1.2.3 From bb6d7c4a394e61574f5f32db60da5c5f5a5e5002 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 3 Sep 2014 03:54:11 +0200 Subject: 342/99 --- src/html/html.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/html/html.c b/src/html/html.c index 27ffe58..3bd5df0 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -102,9 +102,26 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) case indented_code: case fenced_code: - /* TODO: fenced code lang attributes */ cr(html); - gh_buf_puts(html, "
    ");
    +
    +				gh_buf_puts(html, "tag == fenced_code) {
    +					gh_buf *info = &b->attributes.fenced_code_data.info;
    +
    +					if (gh_buf_len(info) > 0) {
    +						int first_tag = gh_buf_strchr(info, ' ', 0);
    +						if (first_tag < 0)
    +							first_tag = gh_buf_len(info);
    +
    +
    +						gh_buf_puts(html, " class=\"");
    +						escape_html(html, info->ptr, first_tag);
    +						gh_buf_putc(html, '"');
    +					}
    +				}
    +
    +				gh_buf_puts(html, ">");
     				escape_html(html, b->string_content.ptr, b->string_content.size);
     				gh_buf_puts(html, "
    "); cr(html); -- cgit v1.2.3 From f5168c63ad305b3e331eb7d31efaf46b0541bba4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 06:41:18 +0200 Subject: 368/73 --- src/blocks.c | 1 + src/inlines.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/blocks.c b/src/blocks.c index 94ff986..bd25d6c 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -57,6 +57,7 @@ bool is_blank(gh_buf *s, int offset) return true; case ' ': offset++; + break; default: return false; } diff --git a/src/inlines.c b/src/inlines.c index ef27a24..ced4673 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -123,7 +123,7 @@ inline static inl* make_linkable(int t, inl* label, chunk url, chunk title) e->tag = t; e->content.linkable.label = label; e->content.linkable.url = chunk_to_cstr(&url); - e->content.linkable.title = url.len ? chunk_to_cstr(&title) : NULL; + e->content.linkable.title = title.len ? chunk_to_cstr(&title) : NULL; e->next = NULL; return e; } -- cgit v1.2.3 From 28be4a59c940bd55ed4fef668091d52638925c3c Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 15:55:27 +0200 Subject: 379/62 --- src/blocks.c | 12 ++++++++---- src/html/html.c | 1 - src/scanners.h | 53 ++++++++++++++++++++++++++++++++++++++++------------- src/scanners.re | 38 +++++++++++++++----------------------- 4 files changed, 63 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/blocks.c b/src/blocks.c index bd25d6c..cf0e9e4 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -752,11 +752,15 @@ static void incorporate_line(gh_buf *line, int line_number, block** curptr) add_line(container, &input, offset); } else if (container->tag == fenced_code) { + matched = 0; + + if (indent <= 3 && + peek_at(&input, first_nonspace) == container->attributes.fenced_code_data.fence_char) { + int fence_len = scan_close_code_fence(&input, first_nonspace); + if (fence_len > container->attributes.fenced_code_data.fence_length) + matched = 1; + } - matched = (indent <= 3 - && peek_at(&input, first_nonspace) == container->attributes.fenced_code_data.fence_char) - && scan_close_code_fence(&input, first_nonspace, - container->attributes.fenced_code_data.fence_length); if (matched) { // if closing fence, don't add line to container; instead, close it: finalize(container, line_number); diff --git a/src/html/html.c b/src/html/html.c index 3bd5df0..2a65a63 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -6,7 +6,6 @@ #include "stmd.h" #include "debug.h" -#include "scanners.h" #include "html/houdini.h" // Functions to convert block and inline lists to HTML strings. diff --git a/src/scanners.h b/src/scanners.h index f96c42d..785d424 100644 --- a/src/scanners.h +++ b/src/scanners.h @@ -1,15 +1,42 @@ #include "stmd.h" -int scan_autolink_uri(chunk *c, int offset); -int scan_autolink_email(chunk *c, int offset); -int scan_html_tag(chunk *c, int offset); -int scan_html_block_tag(chunk *c, int offset); -int scan_link_url(chunk *c, int offset); -int scan_link_title(chunk *c, int offset); -int scan_spacechars(chunk *c, int offset); -int scan_atx_header_start(chunk *c, int offset); -int scan_setext_header_line(chunk *c, int offset); -int scan_hrule(chunk *c, int offset); -int scan_open_code_fence(chunk *c, int offset); -int scan_close_code_fence(chunk *c, int offset, int len); -int scan_entity(chunk *c, int offset); +extern int _scan_autolink_uri(const unsigned char *p); +extern int _scan_autolink_email(const unsigned char *p); +extern int _scan_html_tag(const unsigned char *p); +extern int _scan_html_block_tag(const unsigned char *p); +extern int _scan_link_url(const unsigned char *p); +extern int _scan_link_title(const unsigned char *p); +extern int _scan_spacechars(const unsigned char *p); +extern int _scan_atx_header_start(const unsigned char *p); +extern int _scan_setext_header_line(const unsigned char *p); +extern int _scan_hrule(const unsigned char *p); +extern int _scan_open_code_fence(const unsigned char *p); +extern int _scan_close_code_fence(const unsigned char *p); +extern int _scan_entity(const unsigned char *p); + +static int scan_at(int (*scanner)(const unsigned char *), chunk *c, int offset) +{ + int res; + unsigned char *ptr = (unsigned char *)c->data; + unsigned char lim = ptr[c->len]; + + ptr[c->len] = '\0'; + res = scanner(ptr + offset); + ptr[c->len] = lim; + + return res; +} + +#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_tag(c, n) scan_at(&_scan_html_block_tag, c, n) +#define scan_link_url(c, n) scan_at(&_scan_link_url, 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_header_start(c, n) scan_at(&_scan_atx_header_start, c, n) +#define scan_setext_header_line(c, n) scan_at(&_scan_setext_header_line, c, n) +#define scan_hrule(c, n) scan_at(&_scan_hrule, 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) diff --git a/src/scanners.re b/src/scanners.re index 5ac7c15..71103f6 100644 --- a/src/scanners.re +++ b/src/scanners.re @@ -1,15 +1,12 @@ -#include "scanners.h" +#include #define SCAN_DATA \ const unsigned char *marker = NULL; \ - const unsigned char *p = c->data + offset; \ const unsigned char *start = p; \ - const unsigned char *end = c->data + c->len /*!re2c re2c:define:YYCTYPE = "unsigned char"; re2c:define:YYCURSOR = p; - re2c:define:YYLIMIT = end; re2c:define:YYMARKER = marker; re2c:define:YYCTXMARKER = marker; re2c:yyfill:enable = 0; @@ -62,7 +59,7 @@ */ // Try to match URI autolink after first <, returning number of chars matched. -extern int scan_autolink_uri(chunk *c, int offset) +extern int _scan_autolink_uri(const unsigned char *p) { SCAN_DATA; /*!re2c @@ -72,7 +69,7 @@ extern int scan_autolink_uri(chunk *c, int offset) } // Try to match email autolink after first <, returning num of chars matched. -extern int scan_autolink_email(chunk *c, int offset) +extern int _scan_autolink_email(const unsigned char *p) { SCAN_DATA; /*!re2c @@ -86,7 +83,7 @@ extern int scan_autolink_email(chunk *c, int offset) } // Try to match an HTML tag after first <, returning num of chars matched. -extern int scan_html_tag(chunk *c, int offset) +extern int _scan_html_tag(const unsigned char *p) { SCAN_DATA; /*!re2c @@ -97,7 +94,7 @@ extern int scan_html_tag(chunk *c, int offset) // Try to match an HTML block tag including first <, // returning num of chars matched. -extern int scan_html_block_tag(chunk *c, int offset) +extern int _scan_html_block_tag(const unsigned char *p) { SCAN_DATA; /*!re2c @@ -112,7 +109,7 @@ extern int scan_html_block_tag(chunk *c, int offset) // This may optionally be contained in <..>; otherwise // whitespace and unbalanced right parentheses aren't allowed. // Newlines aren't ever allowed. -extern int scan_link_url(chunk *c, int offset) +extern int _scan_link_url(const unsigned char *p) { SCAN_DATA; /*!re2c @@ -125,7 +122,7 @@ extern int scan_link_url(chunk *c, int offset) // Try to match a link title (in single quotes, in double quotes, or // in parentheses), returning number of chars matched. Allow one // level of internal nesting (quotes within quotes). -extern int scan_link_title(chunk *c, int offset) +extern int _scan_link_title(const unsigned char *p) { SCAN_DATA; /*!re2c @@ -137,7 +134,7 @@ extern int scan_link_title(chunk *c, int offset) } // Match space characters, including newlines. -extern int scan_spacechars(chunk *c, int offset) +extern int _scan_spacechars(const unsigned char *p) { SCAN_DATA; /*!re2c @@ -147,7 +144,7 @@ extern int scan_spacechars(chunk *c, int offset) } // Match ATX header start. -extern int scan_atx_header_start(chunk *c, int offset) +extern int _scan_atx_header_start(const unsigned char *p) { SCAN_DATA; /*!re2c @@ -158,7 +155,7 @@ extern int scan_atx_header_start(chunk *c, int offset) // Match sexext header line. Return 1 for level-1 header, // 2 for level-2, 0 for no match. -extern int scan_setext_header_line(chunk *c, int offset) +extern int _scan_setext_header_line(const unsigned char *p) { SCAN_DATA; /*!re2c @@ -171,7 +168,7 @@ extern int scan_setext_header_line(chunk *c, int offset) // Scan a horizontal rule line: "...three or more hyphens, asterisks, // or underscores on a line by themselves. If you wish, you may use // spaces between the hyphens or asterisks." -extern int scan_hrule(chunk *c, int offset) +extern int _scan_hrule(const unsigned char *p) { SCAN_DATA; /*!re2c @@ -183,7 +180,7 @@ extern int scan_hrule(chunk *c, int offset) } // Scan an opening code fence. -extern int scan_open_code_fence(chunk *c, int offset) +extern int _scan_open_code_fence(const unsigned char *p) { SCAN_DATA; /*!re2c @@ -194,23 +191,18 @@ extern int scan_open_code_fence(chunk *c, int offset) } // Scan a closing code fence with length at least len. -extern int scan_close_code_fence(chunk *c, int offset, int len) +extern int _scan_close_code_fence(const unsigned char *p) { SCAN_DATA; /*!re2c - ([`]{3,} | [~]{3,}) / spacechar* [\n] - { if (p - start > len) { - return (p - start); - } else { - return 0; - } } + ([`]{3,} | [~]{3,}) / spacechar* [\n] { return (p - start); } .? { return 0; } */ } // Scans an entity. // Returns number of chars matched. -extern int scan_entity(chunk *c, int offset) +extern int _scan_entity(const unsigned char *p) { SCAN_DATA; /*!re2c -- cgit v1.2.3 From 45c1d9fadb3e8aab4a01bb27a4e2ece379902d1a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 17:26:11 +0200 Subject: 426/15 --- runtests.pl | 3 ++ spec.txt | 6 ++-- src/html/html.c | 22 +++++------- src/inlines.c | 105 +++++++++++++++++++++++++++++--------------------------- 4 files changed, 69 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/runtests.pl b/runtests.pl index 2e2b795..e53938d 100644 --- a/runtests.pl +++ b/runtests.pl @@ -49,6 +49,7 @@ sub tidy s/ */ /; # collapse space before /> in tag s/ *\/>/\/>/; + s/>\n$/>/; # skip blank line if (/^$/) { next; @@ -89,8 +90,10 @@ sub dotest print $markdown; print "=== expected ===============\n"; print $html; + print "\n"; print "=== got ====================\n"; print $actual; + print "\n"; print color "black"; return 0; } diff --git a/spec.txt b/spec.txt index 82ae0b6..d7e70f5 100644 --- a/spec.txt +++ b/spec.txt @@ -1682,7 +1682,7 @@ them. [Foo bar] . -

    Foo bar

    +

    Foo bar

    . The title may be omitted: @@ -1745,7 +1745,7 @@ case-insensitive (see [matches](#matches)). [αγω] . -

    αγω

    +

    αγω

    . Here is a link reference definition with no corresponding link. @@ -3688,7 +3688,7 @@ raw HTML: . . -

    http://google.com?find=\*

    +

    http://google.com?find=\*

    . . diff --git a/src/html/html.c b/src/html/html.c index 2a65a63..cdccf2a 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -50,17 +50,15 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) cr(html); gh_buf_puts(html, "

    "); inlines_to_html(html, b->inline_content); - gh_buf_puts(html, "

    "); - cr(html); + gh_buf_puts(html, "

    \n"); } break; case block_quote: cr(html); - gh_buf_puts(html, "
    "); + gh_buf_puts(html, "
    \n"); blocks_to_html(html, b->children, false); - gh_buf_puts(html, "
    "); - cr(html); + gh_buf_puts(html, "
    \n"); break; case list_item: @@ -68,8 +66,7 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) gh_buf_puts(html, "
  • "); blocks_to_html(html, b->children, tight); gh_buf_trim(html); /* TODO: rtrim */ - gh_buf_puts(html, "
  • "); - cr(html); + gh_buf_puts(html, "\n"); break; case list: @@ -87,7 +84,7 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) blocks_to_html(html, b->children, data->tight); gh_buf_puts(html, data->list_type == bullet ? "" : ""); - cr(html); + gh_buf_putc(html, '\n'); break; case atx_header: @@ -95,8 +92,7 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) cr(html); gh_buf_printf(html, "", b->attributes.header_level); inlines_to_html(html, b->inline_content); - gh_buf_printf(html, "", b->attributes.header_level); - cr(html); + gh_buf_printf(html, "\n", b->attributes.header_level); break; case indented_code: @@ -122,8 +118,7 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) gh_buf_puts(html, ">"); escape_html(html, b->string_content.ptr, b->string_content.size); - gh_buf_puts(html, ""); - cr(html); + gh_buf_puts(html, "
    \n"); break; case html_block: @@ -131,8 +126,7 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) break; case hrule: - gh_buf_puts(html, "
    "); - cr(html); + gh_buf_puts(html, "
    \n"); break; case reference_def: diff --git a/src/inlines.c b/src/inlines.c index ced4673..a0dcac9 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -1,8 +1,8 @@ #include +#include #include #include #include -#include #include "stmd.h" #include "uthash.h" @@ -18,7 +18,7 @@ typedef struct Subject { reference* lookup_reference(reference** refmap, chunk *label); reference* make_reference(chunk *label, chunk *url, chunk *title); -static unsigned char *clean_url(chunk *url); +static unsigned char *clean_url(chunk *url, int is_email); static unsigned char *clean_title(chunk *title); inline static unsigned char *chunk_to_cstr(chunk *c); @@ -97,7 +97,7 @@ extern reference* make_reference(chunk *label, chunk *url, chunk *title) reference *ref; ref = malloc(sizeof(reference)); ref->label = normalize_reference(label); - ref->url = clean_url(url); + ref->url = clean_url(url, 0); ref->title = clean_title(title); return ref; } @@ -116,14 +116,25 @@ extern void add_reference(reference** refmap, reference* ref) } } +inline static inl* make_link_from_reference(inl* label, reference *ref) +{ + inl* e = (inl*) malloc(sizeof(inl)); + e->tag = INL_LINK; + e->content.linkable.label = label; + e->content.linkable.url = strdup(ref->url); + e->content.linkable.title = ref->title ? strdup(ref->title) : NULL; + e->next = NULL; + return e; +} + // Create an inline with a linkable string value. -inline static inl* make_linkable(int t, inl* label, chunk url, chunk title) +inline static inl* make_link(inl* label, chunk url, chunk title, int is_email) { inl* e = (inl*) malloc(sizeof(inl)); - e->tag = t; + e->tag = INL_LINK; e->content.linkable.label = label; - e->content.linkable.url = chunk_to_cstr(&url); - e->content.linkable.title = title.len ? chunk_to_cstr(&title) : NULL; + e->content.linkable.url = clean_url(&url, is_email); + e->content.linkable.title = clean_title(&title); e->next = NULL; return e; } @@ -163,7 +174,6 @@ inline static inl* make_simple(int t) #define make_entity(s) make_literal(INL_ENTITY, s) #define make_linebreak() make_simple(INL_LINEBREAK) #define make_softbreak() make_simple(INL_SOFTBREAK) -#define make_link(label, url, title) make_linkable(INL_LINK, label, url, title) #define make_emph(contents) make_inlines(INL_EMPH, contents) #define make_strong(contents) make_inlines(INL_STRONG, contents) @@ -309,37 +319,27 @@ static int scan_to_closing_backticks(subject* subj, int openticklength) // space and newline characters into a single space. static void normalize_whitespace(gh_buf *s) { - /* TODO */ -#if 0 bool last_char_was_space = false; - int pos = 0; - char c; - while ((c = gh_buf_at(s, pos))) { - switch (c) { - case ' ': - if (last_char_was_space) { - bdelete(s, pos, 1); - } else { - pos++; - } - last_char_was_space = true; - break; - case '\n': - if (last_char_was_space) { - bdelete(s, pos, 1); - } else { - bdelete(s, pos, 1); - binsertch(s, pos, 1, ' '); - pos++; - } - last_char_was_space = true; + int r, w; + + for (r = 0, w = 0; r < s->size; ++r) { + switch (s->ptr[r]) { + case ' ': + case '\n': + if (last_char_was_space) break; - default: - pos++; - last_char_was_space = false; + + s->ptr[w++] = ' '; + last_char_was_space = true; + break; + + default: + s->ptr[w++] = s->ptr[r]; + last_char_was_space = false; } } -#endif + + gh_buf_truncate(s, w); } // Parse backtick code section or raw backticks, return an inline. @@ -593,16 +593,19 @@ extern void unescape_buffer(gh_buf *buf) // Clean a URL: remove surrounding whitespace and surrounding <>, // and remove \ that escape punctuation. -static unsigned char *clean_url(chunk *url) +static unsigned char *clean_url(chunk *url, int is_email) { gh_buf buf = GH_BUF_INIT; chunk_trim(url); + if (is_email) + gh_buf_puts(&buf, "mailto:"); + if (url->data[0] == '<' && url->data[url->len - 1] == '>') { - gh_buf_set(&buf, url->data + 1, url->len - 2); + gh_buf_put(&buf, url->data + 1, url->len - 2); } else { - gh_buf_set(&buf, url->data, url->len); + gh_buf_put(&buf, url->data, url->len); } unescape_buffer(&buf); @@ -613,8 +616,13 @@ static unsigned char *clean_url(chunk *url) static unsigned char *clean_title(chunk *title) { gh_buf buf = GH_BUF_INIT; - unsigned char first = title->data[0]; - unsigned char last = title->data[title->len - 1]; + unsigned char first, last; + + if (title->len == 0) + return NULL; + + first = title->data[0]; + last = title->data[title->len - 1]; // remove surrounding quotes if any: if ((first == '\'' && last == '\'') || @@ -647,25 +655,22 @@ static inl* handle_pointy_brace(subject* subj) return make_link( make_str_with_entities(&contents), contents, - chunk_literal("") + chunk_literal(""), + 0 ); } // next try to match an email autolink matchlen = scan_autolink_email(&subj->input, subj->pos); if (matchlen > 0) { - gh_buf mail_url = GH_BUF_INIT; - contents = chunk_dup(&subj->input, subj->pos, matchlen - 1); subj->pos += matchlen; - gh_buf_puts(&mail_url, "mailto:"); - gh_buf_put(&mail_url, contents.data, contents.len); - return make_link( make_str_with_entities(&contents), - chunk_buf_detach(&mail_url), - chunk_literal("") + contents, + chunk_literal(""), + 1 ); } @@ -790,7 +795,7 @@ static inl* handle_left_bracket(subject* subj) title = chunk_dup(&subj->input, starttitle, endtitle - starttitle); lab = parse_chunk_inlines(&rawlabel, NULL); - return make_link(lab, url, title); + return make_link(lab, url, title, 0); } else { // if we get here, we matched a label but didn't get further: subj->pos = endlabel; @@ -821,7 +826,7 @@ static inl* handle_left_bracket(subject* subj) ref = lookup_reference(subj->reference_map, &reflabel); if (ref != NULL) { // found lab = parse_chunk_inlines(&rawlabel, NULL); - result = make_link(lab, chunk_literal(ref->url), chunk_literal(ref->title)); + result = make_link_from_reference(lab, ref); } else { subj->pos = endlabel; lab = parse_chunk_inlines(&rawlabel, subj->reference_map); -- cgit v1.2.3 From 9830d3a05a374a0d05676301bd4065917b59ad53 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 17:42:12 +0200 Subject: 430/11 --- src/html/houdini_html_e.c | 4 ++-- src/html/html.c | 5 ++--- src/inlines.c | 14 +++----------- 3 files changed, 7 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/html/houdini_html_e.c b/src/html/houdini_html_e.c index 5cdd3dd..95b6c41 100644 --- a/src/html/houdini_html_e.c +++ b/src/html/houdini_html_e.c @@ -62,8 +62,8 @@ houdini_escape_html0(gh_buf *ob, const uint8_t *src, size_t size, int secure) break; /* The forward slash is only escaped in secure mode */ - if (src[i] == '/' && !secure) { - gh_buf_putc(ob, '/'); + if ((src[i] == '/' || src[i] == '\'') && !secure) { + gh_buf_putc(ob, src[i]); } else { gh_buf_puts(ob, HTML_ESCAPES[esc]); } diff --git a/src/html/html.c b/src/html/html.c index cdccf2a..913a602 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -191,10 +191,9 @@ void inlines_to_html(gh_buf *html, inl* ils) escape_href(html, ils->content.linkable.url, -1); inlines_to_html(&scrap, ils->content.inlines); - if (scrap.size) { - gh_buf_puts(html, "\" alt=\""); + gh_buf_puts(html, "\" alt=\""); + if (scrap.size) escape_html(html, scrap.ptr, scrap.size); - } gh_buf_clear(&scrap); if (ils->content.linkable.title) { diff --git a/src/inlines.c b/src/inlines.c index a0dcac9..599be84 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -21,7 +21,6 @@ reference* make_reference(chunk *label, chunk *url, chunk *title); static unsigned char *clean_url(chunk *url, int is_email); static unsigned char *clean_title(chunk *title); -inline static unsigned char *chunk_to_cstr(chunk *c); inline static void chunk_free(chunk *c); inline static void chunk_trim(chunk *c); @@ -37,6 +36,8 @@ static void subject_from_chunk(subject *e, chunk *chunk, reference** refmap); static void subject_from_buf(subject *e, gh_buf *buffer, reference** refmap); static int subject_find_special_char(subject *subj); +static void normalize_whitespace(gh_buf *s); + extern void free_reference(reference *ref) { free(ref->label); free(ref->url); @@ -62,19 +63,10 @@ extern void free_reference_map(reference **refmap) { static unsigned char *normalize_reference(chunk *ref) { gh_buf normalized = GH_BUF_INIT; - int r, w; utf8proc_case_fold(&normalized, ref->data, ref->len); gh_buf_trim(&normalized); - - for (r = 0, w = 0; r < normalized.size; ++r) { - if (r && gh_buf_at(&normalized, r - 1) == ' ') { - while (gh_buf_at(&normalized, r) == ' ') - r++; - } - - normalized.ptr[w++] = normalized.ptr[r]; - } + normalize_whitespace(&normalized); return gh_buf_detach(&normalized); } -- cgit v1.2.3 From d8f44f1e4f0bd944ab43e6434a1579d670ed66cf Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 17:49:13 +0200 Subject: 433/8 --- spec.txt | 2 +- src/html/html.c | 6 ++++-- src/inlines.c | 3 +++ src/print.c | 5 ++++- 4 files changed, 12 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/spec.txt b/spec.txt index d7e70f5..cfda2a3 100644 --- a/spec.txt +++ b/spec.txt @@ -3946,7 +3946,7 @@ But this is a link: . ` . -

    http://foo.bar.`baz`

    +

    http://foo.bar.`baz`

    . And this is an HTML tag: diff --git a/src/html/html.c b/src/html/html.c index 913a602..41b8fda 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -174,7 +174,8 @@ void inlines_to_html(gh_buf *html, inl* ils) case INL_LINK: gh_buf_puts(html, "content.linkable.url, -1); + if (ils->content.linkable.url) + escape_href(html, ils->content.linkable.url, -1); if (ils->content.linkable.title) { gh_buf_puts(html, "\" title=\""); @@ -188,7 +189,8 @@ void inlines_to_html(gh_buf *html, inl* ils) case INL_IMAGE: gh_buf_puts(html, "content.linkable.url, -1); + if (ils->content.linkable.url) + escape_href(html, ils->content.linkable.url, -1); inlines_to_html(&scrap, ils->content.inlines); gh_buf_puts(html, "\" alt=\""); diff --git a/src/inlines.c b/src/inlines.c index 599be84..8e2e683 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -591,6 +591,9 @@ static unsigned char *clean_url(chunk *url, int is_email) chunk_trim(url); + if (url->len == 0) + return NULL; + if (is_email) gh_buf_puts(&buf, "mailto:"); diff --git a/src/print.c b/src/print.c index c262995..832ad4f 100644 --- a/src/print.c +++ b/src/print.c @@ -153,7 +153,10 @@ extern void print_inlines(inl* ils, int indent) case INL_LINK: case INL_IMAGE: printf("%s url=", ils->tag == INL_LINK ? "link" : "image"); - print_str(ils->content.linkable.url, -1); + + if (ils->content.linkable.url) + print_str(ils->content.linkable.url, -1); + if (ils->content.linkable.title) { printf(" title="); print_str(ils->content.linkable.title, -1); -- cgit v1.2.3 From 543c2c94d71adee42c7bd2f8027d75c87ed8120d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 18:38:14 +0200 Subject: Rename to strbuf --- src/blocks.c | 64 +++++++++++++++---------------- src/buffer.c | 86 ++++++++++++++++++++--------------------- src/buffer.h | 80 +++++++++++++++++++------------------- src/chunk.h | 4 +- src/html/houdini.h | 22 +++++------ src/html/houdini_href_e.c | 12 +++--- src/html/houdini_html_e.c | 10 ++--- src/html/html.c | 98 +++++++++++++++++++++++------------------------ src/inlines.c | 50 ++++++++++++------------ src/main.c | 4 +- src/stmd.h | 16 ++++---- src/utf8.c | 6 +-- 12 files changed, 226 insertions(+), 226 deletions(-) (limited to 'src') diff --git a/src/blocks.c b/src/blocks.c index cf0e9e4..9faccd9 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -10,7 +10,7 @@ #define peek_at(i, n) (i)->data[n] -static void incorporate_line(gh_buf *ln, int line_number, block** curptr); +static void incorporate_line(strbuf *ln, int line_number, block** curptr); static void finalize(block* b, int line_number); static block* make_block(int tag, int start_line, int start_column) @@ -28,7 +28,7 @@ static block* make_block(int tag, int start_line, int start_column) e->parent = NULL; e->top = NULL; e->attributes.refmap = NULL; - gh_buf_init(&e->string_content, 32); + strbuf_init(&e->string_content, 32); e->inline_content = NULL; e->next = NULL; e->prev = NULL; @@ -49,7 +49,7 @@ extern block* make_document() } // Returns true if line has only space characters, else false. -bool is_blank(gh_buf *s, int offset) +bool is_blank(strbuf *s, int offset) { while (offset < s->size) { switch (s->ptr[offset]) { @@ -85,10 +85,10 @@ static inline bool accepts_lines(int block_type) static void add_line(block* block, chunk *ch, int offset) { assert(block->open); - gh_buf_put(&block->string_content, ch->data + offset, ch->len - offset); + strbuf_put(&block->string_content, ch->data + offset, ch->len - offset); } -static void remove_trailing_blank_lines(gh_buf *ln) +static void remove_trailing_blank_lines(strbuf *ln) { int i; @@ -100,13 +100,13 @@ static void remove_trailing_blank_lines(gh_buf *ln) } if (i < 0) { - gh_buf_clear(ln); + strbuf_clear(ln); return; } - i = gh_buf_strchr(ln, '\n', i); + i = strbuf_strchr(ln, '\n', i); if (i >= 0) - gh_buf_truncate(ln, i); + strbuf_truncate(ln, i); } // Check to see if a block ends with a blank line, descending @@ -164,10 +164,10 @@ static void finalize(block* b, int line_number) switch (b->tag) { case paragraph: pos = 0; - while (gh_buf_at(&b->string_content, 0) == '[' && + while (strbuf_at(&b->string_content, 0) == '[' && (pos = parse_reference(&b->string_content, b->top->attributes.refmap))) { - gh_buf_drop(&b->string_content, pos); + strbuf_drop(&b->string_content, pos); } if (is_blank(&b->string_content, 0)) { b->tag = reference_def; @@ -176,23 +176,23 @@ static void finalize(block* b, int line_number) case indented_code: remove_trailing_blank_lines(&b->string_content); - gh_buf_putc(&b->string_content, '\n'); + strbuf_putc(&b->string_content, '\n'); break; case fenced_code: // first line of contents becomes info - firstlinelen = gh_buf_strchr(&b->string_content, '\n', 0); + firstlinelen = strbuf_strchr(&b->string_content, '\n', 0); - gh_buf_init(&b->attributes.fenced_code_data.info, 0); - gh_buf_set( + strbuf_init(&b->attributes.fenced_code_data.info, 0); + strbuf_set( &b->attributes.fenced_code_data.info, b->string_content.ptr, firstlinelen ); - gh_buf_drop(&b->string_content, firstlinelen + 1); + strbuf_drop(&b->string_content, firstlinelen + 1); - gh_buf_trim(&b->attributes.fenced_code_data.info); + strbuf_trim(&b->attributes.fenced_code_data.info); unescape_buffer(&b->attributes.fenced_code_data.info); break; @@ -265,9 +265,9 @@ extern void free_blocks(block* e) while (e != NULL) { next = e->next; free_inlines(e->inline_content); - gh_buf_free(&e->string_content); + strbuf_free(&e->string_content); if (e->tag == fenced_code) { - gh_buf_free(&e->attributes.fenced_code_data.info); + strbuf_free(&e->attributes.fenced_code_data.info); } else if (e->tag == document) { free_reference_map(e->attributes.refmap); } @@ -287,7 +287,7 @@ void process_inlines(block* cur, reference** refmap) case setext_header: cur->inline_content = parse_inlines(&cur->string_content, refmap); // MEM - // gh_buf_free(&cur->string_content); + // strbuf_free(&cur->string_content); break; default: @@ -369,7 +369,7 @@ static int lists_match(struct ListData list_data, list_data.bullet_char == item_data.bullet_char); } -static void expand_tabs(gh_buf *ob, const unsigned char *line, size_t size) +static void expand_tabs(strbuf *ob, const unsigned char *line, size_t size) { size_t i = 0, tab = 0; @@ -381,13 +381,13 @@ static void expand_tabs(gh_buf *ob, const unsigned char *line, size_t size) } if (i > org) - gh_buf_put(ob, line + org, i - org); + strbuf_put(ob, line + org, i - org); if (i >= size) break; do { - gh_buf_putc(ob, ' '); tab++; + strbuf_putc(ob, ' '); tab++; } while (tab % 4); i++; @@ -409,7 +409,7 @@ static block *finalize_document(block *document, int linenum) extern block *stmd_parse_file(FILE *f) { - gh_buf line = GH_BUF_INIT; + strbuf line = GH_BUF_INIT; unsigned char buffer[4096]; int linenum = 1; block *document = make_document(); @@ -417,17 +417,17 @@ extern block *stmd_parse_file(FILE *f) while (fgets((char *)buffer, sizeof(buffer), f)) { expand_tabs(&line, buffer, strlen((char *)buffer)); incorporate_line(&line, linenum, &document); - gh_buf_clear(&line); + strbuf_clear(&line); linenum++; } - gh_buf_free(&line); + strbuf_free(&line); return finalize_document(document, linenum); } extern block *stmd_parse_document(const unsigned char *buffer, size_t len) { - gh_buf line = GH_BUF_INIT; + strbuf line = GH_BUF_INIT; int linenum = 1; const unsigned char *end = buffer + len; block *document = make_document(); @@ -444,11 +444,11 @@ extern block *stmd_parse_document(const unsigned char *buffer, size_t len) } incorporate_line(&line, linenum, &document); - gh_buf_clear(&line); + strbuf_clear(&line); linenum++; } - gh_buf_free(&line); + strbuf_free(&line); return finalize_document(document, linenum); } @@ -471,7 +471,7 @@ static void chop_trailing_hashtags(chunk *ch) } // Process one line at a time, modifying a block. -static void incorporate_line(gh_buf *line, int line_number, block** curptr) +static void incorporate_line(strbuf *line, int line_number, block** curptr) { block* last_matched_container; int offset = 0; @@ -639,8 +639,8 @@ static void incorporate_line(gh_buf *line, int line_number, block** curptr) } else if (container->tag == paragraph && (lev = scan_setext_header_line(&input, first_nonspace)) && // check that there is only one line in the paragraph: - gh_buf_strrchr(&container->string_content, '\n', - gh_buf_len(&container->string_content) - 2) < 0) { + strbuf_strrchr(&container->string_content, '\n', + strbuf_len(&container->string_content) - 2) < 0) { container->tag = setext_header; container->attributes.header_level = lev; @@ -734,7 +734,7 @@ static void incorporate_line(gh_buf *line, int line_number, block** curptr) container == last_matched_container && !blank && cur->tag == paragraph && - gh_buf_len(&cur->string_content) > 0) { + strbuf_len(&cur->string_content) > 0) { add_line(cur, &input, offset); diff --git a/src/buffer.c b/src/buffer.c index dc4a405..90c2186 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -9,32 +9,32 @@ #include "buffer.h" -/* Used as default value for gh_buf->ptr so that people can always - * assume ptr is non-NULL and zero terminated even for new gh_bufs. +/* Used as default value for strbuf->ptr so that people can always + * assume ptr is non-NULL and zero terminated even for new strbufs. */ -unsigned char gh_buf__initbuf[1]; -unsigned char gh_buf__oom[1]; +unsigned char strbuf__initbuf[1]; +unsigned char strbuf__oom[1]; #define ENSURE_SIZE(b, d) \ - if ((d) > buf->asize && gh_buf_grow(b, (d)) < 0)\ + if ((d) > buf->asize && strbuf_grow(b, (d)) < 0)\ return -1; -void gh_buf_init(gh_buf *buf, int initial_size) +void strbuf_init(strbuf *buf, int initial_size) { buf->asize = 0; buf->size = 0; - buf->ptr = gh_buf__initbuf; + buf->ptr = strbuf__initbuf; if (initial_size) - gh_buf_grow(buf, initial_size); + strbuf_grow(buf, initial_size); } -int gh_buf_try_grow(gh_buf *buf, int target_size, bool mark_oom) +int strbuf_try_grow(strbuf *buf, int target_size, bool mark_oom) { unsigned char *new_ptr; int new_size; - if (buf->ptr == gh_buf__oom) + if (buf->ptr == strbuf__oom) return -1; if (target_size <= buf->asize) @@ -60,7 +60,7 @@ int gh_buf_try_grow(gh_buf *buf, int target_size, bool mark_oom) if (!new_ptr) { if (mark_oom) - buf->ptr = gh_buf__oom; + buf->ptr = strbuf__oom; return -1; } @@ -75,17 +75,17 @@ int gh_buf_try_grow(gh_buf *buf, int target_size, bool mark_oom) return 0; } -void gh_buf_free(gh_buf *buf) +void strbuf_free(strbuf *buf) { if (!buf) return; - if (buf->ptr != gh_buf__initbuf && buf->ptr != gh_buf__oom) + if (buf->ptr != strbuf__initbuf && buf->ptr != strbuf__oom) free(buf->ptr); - gh_buf_init(buf, 0); + strbuf_init(buf, 0); } -void gh_buf_clear(gh_buf *buf) +void strbuf_clear(strbuf *buf) { buf->size = 0; @@ -93,10 +93,10 @@ void gh_buf_clear(gh_buf *buf) buf->ptr[0] = '\0'; } -int gh_buf_set(gh_buf *buf, const unsigned char *data, int len) +int strbuf_set(strbuf *buf, const unsigned char *data, int len) { if (len <= 0 || data == NULL) { - gh_buf_clear(buf); + strbuf_clear(buf); } else { if (data != buf->ptr) { ENSURE_SIZE(buf, len + 1); @@ -108,14 +108,14 @@ int gh_buf_set(gh_buf *buf, const unsigned char *data, int len) return 0; } -int gh_buf_sets(gh_buf *buf, const char *string) +int strbuf_sets(strbuf *buf, const char *string) { - return gh_buf_set(buf, + return strbuf_set(buf, (const unsigned char *)string, string ? strlen(string) : 0); } -int gh_buf_putc(gh_buf *buf, int c) +int strbuf_putc(strbuf *buf, int c) { ENSURE_SIZE(buf, buf->size + 2); buf->ptr[buf->size++] = c; @@ -123,7 +123,7 @@ int gh_buf_putc(gh_buf *buf, int c) return 0; } -int gh_buf_put(gh_buf *buf, const unsigned char *data, int len) +int strbuf_put(strbuf *buf, const unsigned char *data, int len) { if (len <= 0) return 0; @@ -135,12 +135,12 @@ int gh_buf_put(gh_buf *buf, const unsigned char *data, int len) return 0; } -int gh_buf_puts(gh_buf *buf, const char *string) +int strbuf_puts(strbuf *buf, const char *string) { - return gh_buf_put(buf, (const unsigned char *)string, strlen(string)); + return strbuf_put(buf, (const unsigned char *)string, strlen(string)); } -int gh_buf_vprintf(gh_buf *buf, const char *format, va_list ap) +int strbuf_vprintf(strbuf *buf, const char *format, va_list ap) { const int expected_size = buf->size + (strlen(format) * 2); int len; @@ -159,7 +159,7 @@ int gh_buf_vprintf(gh_buf *buf, const char *format, va_list ap) if (len < 0) { free(buf->ptr); - buf->ptr = gh_buf__oom; + buf->ptr = strbuf__oom; return -1; } @@ -174,19 +174,19 @@ int gh_buf_vprintf(gh_buf *buf, const char *format, va_list ap) return 0; } -int gh_buf_printf(gh_buf *buf, const char *format, ...) +int strbuf_printf(strbuf *buf, const char *format, ...) { int r; va_list ap; va_start(ap, format); - r = gh_buf_vprintf(buf, format, ap); + r = strbuf_vprintf(buf, format, ap); va_end(ap); return r; } -void gh_buf_copy_cstr(char *data, int datasize, const gh_buf *buf) +void strbuf_copy_cstr(char *data, int datasize, const strbuf *buf) { int copylen; @@ -204,28 +204,28 @@ void gh_buf_copy_cstr(char *data, int datasize, const gh_buf *buf) data[copylen] = '\0'; } -void gh_buf_swap(gh_buf *buf_a, gh_buf *buf_b) +void strbuf_swap(strbuf *buf_a, strbuf *buf_b) { - gh_buf t = *buf_a; + strbuf t = *buf_a; *buf_a = *buf_b; *buf_b = t; } -unsigned char *gh_buf_detach(gh_buf *buf) +unsigned char *strbuf_detach(strbuf *buf) { unsigned char *data = buf->ptr; - if (buf->asize == 0 || buf->ptr == gh_buf__oom) + if (buf->asize == 0 || buf->ptr == strbuf__oom) return NULL; - gh_buf_init(buf, 0); + strbuf_init(buf, 0); return data; } -void gh_buf_attach(gh_buf *buf, unsigned char *ptr, int asize) +void strbuf_attach(strbuf *buf, unsigned char *ptr, int asize) { - gh_buf_free(buf); + strbuf_free(buf); if (ptr) { buf->ptr = ptr; @@ -235,18 +235,18 @@ void gh_buf_attach(gh_buf *buf, unsigned char *ptr, int asize) else /* pass 0 to fall back on strlen + 1 */ buf->asize = buf->size + 1; } else { - gh_buf_grow(buf, asize); + strbuf_grow(buf, asize); } } -int gh_buf_cmp(const gh_buf *a, const gh_buf *b) +int strbuf_cmp(const strbuf *a, const strbuf *b) { int result = memcmp(a->ptr, b->ptr, MIN(a->size, b->size)); return (result != 0) ? result : (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0; } -int gh_buf_strchr(const gh_buf *buf, int c, int pos) +int strbuf_strchr(const strbuf *buf, int c, int pos) { const unsigned char *p = memchr(buf->ptr + pos, c, buf->size - pos); if (!p) @@ -255,7 +255,7 @@ int gh_buf_strchr(const gh_buf *buf, int c, int pos) return (int)(p - (const unsigned char *)buf->ptr); } -int gh_buf_strrchr(const gh_buf *buf, int c, int pos) +int strbuf_strrchr(const strbuf *buf, int c, int pos) { int i; @@ -267,7 +267,7 @@ int gh_buf_strrchr(const gh_buf *buf, int c, int pos) return -1; } -void gh_buf_truncate(gh_buf *buf, int len) +void strbuf_truncate(strbuf *buf, int len) { if (len < buf->size) { buf->size = len; @@ -275,7 +275,7 @@ void gh_buf_truncate(gh_buf *buf, int len) } } -void gh_buf_drop(gh_buf *buf, int n) +void strbuf_drop(strbuf *buf, int n) { if (n > 0) { buf->size = buf->size - n; @@ -286,7 +286,7 @@ void gh_buf_drop(gh_buf *buf, int n) } } -void gh_buf_trim(gh_buf *buf) +void strbuf_trim(strbuf *buf) { int i = 0; @@ -296,7 +296,7 @@ void gh_buf_trim(gh_buf *buf) while (i < buf->size && isspace(buf->ptr[i])) i++; - gh_buf_drop(buf, i); + strbuf_drop(buf, i); /* rtrim */ while (buf->size > 0) { diff --git a/src/buffer.h b/src/buffer.h index 0d5143e..6f45cbb 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -9,20 +9,20 @@ typedef struct { unsigned char *ptr; int asize, size; -} gh_buf; +} strbuf; -extern unsigned char gh_buf__initbuf[]; -extern unsigned char gh_buf__oom[]; +extern unsigned char strbuf__initbuf[]; +extern unsigned char strbuf__oom[]; -#define GH_BUF_INIT { gh_buf__initbuf, 0, 0 } +#define GH_BUF_INIT { strbuf__initbuf, 0, 0 } /** - * Initialize a gh_buf structure. + * Initialize a strbuf structure. * * For the cases where GH_BUF_INIT cannot be used to do static * initialization. */ -extern void gh_buf_init(gh_buf *buf, int initial_size); +extern void strbuf_init(strbuf *buf, int initial_size); /** * Attempt to grow the buffer to hold at least `target_size` bytes. @@ -32,7 +32,7 @@ extern void gh_buf_init(gh_buf *buf, int initial_size); * existing buffer content will be preserved, but calling code must handle * that buffer was not expanded. */ -extern int gh_buf_try_grow(gh_buf *buf, int target_size, bool mark_oom); +extern int strbuf_try_grow(strbuf *buf, int target_size, bool mark_oom); /** * Grow the buffer to hold at least `target_size` bytes. @@ -42,71 +42,71 @@ extern int gh_buf_try_grow(gh_buf *buf, int target_size, bool mark_oom); * * @return 0 on success or -1 on failure */ -static inline int gh_buf_grow(gh_buf *buf, int target_size) +static inline int strbuf_grow(strbuf *buf, int target_size) { - return gh_buf_try_grow(buf, target_size, true); + return strbuf_try_grow(buf, target_size, true); } -extern void gh_buf_free(gh_buf *buf); -extern void gh_buf_swap(gh_buf *buf_a, gh_buf *buf_b); +extern void strbuf_free(strbuf *buf); +extern void strbuf_swap(strbuf *buf_a, strbuf *buf_b); /** - * Test if there have been any reallocation failures with this gh_buf. + * Test if there have been any reallocation failures with this strbuf. * - * Any function that writes to a gh_buf can fail due to memory allocation - * issues. If one fails, the gh_buf will be marked with an OOM error and - * further calls to modify the buffer will fail. Check gh_buf_oom() at the + * Any function that writes to a strbuf can fail due to memory allocation + * issues. If one fails, the strbuf will be marked with an OOM error and + * further calls to modify the buffer will fail. Check strbuf_oom() at the * end of your sequence and it will be true if you ran out of memory at any * point with that buffer. * * @return false if no error, true if allocation error */ -static inline bool gh_buf_oom(const gh_buf *buf) +static inline bool strbuf_oom(const strbuf *buf) { - return (buf->ptr == gh_buf__oom); + return (buf->ptr == strbuf__oom); } -static inline size_t gh_buf_len(const gh_buf *buf) +static inline size_t strbuf_len(const strbuf *buf) { return buf->size; } -extern int gh_buf_cmp(const gh_buf *a, const gh_buf *b); +extern int strbuf_cmp(const strbuf *a, const strbuf *b); -extern void gh_buf_attach(gh_buf *buf, unsigned char *ptr, int asize); -extern unsigned char *gh_buf_detach(gh_buf *buf); -extern void gh_buf_copy_cstr(char *data, int datasize, const gh_buf *buf); +extern void strbuf_attach(strbuf *buf, unsigned char *ptr, int asize); +extern unsigned char *strbuf_detach(strbuf *buf); +extern void strbuf_copy_cstr(char *data, int datasize, const strbuf *buf); -static inline const char *gh_buf_cstr(const gh_buf *buf) +static inline const char *strbuf_cstr(const strbuf *buf) { return (char *)buf->ptr; } -#define gh_buf_at(buf, n) ((buf)->ptr[n]) +#define strbuf_at(buf, n) ((buf)->ptr[n]) /* * Functions below that return int value error codes will return 0 on * success or -1 on failure (which generally means an allocation failed). - * Using a gh_buf where the allocation has failed with result in -1 from + * Using a strbuf where the allocation has failed with result in -1 from * all further calls using that buffer. As a result, you can ignore the * return code of these functions and call them in a series then just call - * gh_buf_oom at the end. + * strbuf_oom at the end. */ -extern int gh_buf_set(gh_buf *buf, const unsigned char *data, int len); -extern int gh_buf_sets(gh_buf *buf, const char *string); -extern int gh_buf_putc(gh_buf *buf, int c); -extern int gh_buf_put(gh_buf *buf, const unsigned char *data, int len); -extern int gh_buf_puts(gh_buf *buf, const char *string); -extern int gh_buf_printf(gh_buf *buf, const char *format, ...) +extern int strbuf_set(strbuf *buf, const unsigned char *data, int len); +extern int strbuf_sets(strbuf *buf, const char *string); +extern int strbuf_putc(strbuf *buf, int c); +extern int strbuf_put(strbuf *buf, const unsigned char *data, int len); +extern int strbuf_puts(strbuf *buf, const char *string); +extern int strbuf_printf(strbuf *buf, const char *format, ...) __attribute__((format (printf, 2, 3))); -extern int gh_buf_vprintf(gh_buf *buf, const char *format, va_list ap); -extern void gh_buf_clear(gh_buf *buf); - -int gh_buf_strchr(const gh_buf *buf, int c, int pos); -int gh_buf_strrchr(const gh_buf *buf, int c, int pos); -void gh_buf_drop(gh_buf *buf, int n); -void gh_buf_truncate(gh_buf *buf, int len); -void gh_buf_trim(gh_buf *buf); +extern int strbuf_vprintf(strbuf *buf, const char *format, va_list ap); +extern void strbuf_clear(strbuf *buf); + +int strbuf_strchr(const strbuf *buf, int c, int pos); +int strbuf_strrchr(const strbuf *buf, int c, int pos); +void strbuf_drop(strbuf *buf, int n); +void strbuf_truncate(strbuf *buf, int len); +void strbuf_trim(strbuf *buf); #endif diff --git a/src/chunk.h b/src/chunk.h index f3841ed..f37a2f3 100644 --- a/src/chunk.h +++ b/src/chunk.h @@ -78,12 +78,12 @@ static inline chunk chunk_dup(const chunk *ch, int pos, int len) return c; } -static inline chunk chunk_buf_detach(gh_buf *buf) +static inline chunk chunk_buf_detach(strbuf *buf) { chunk c; c.len = buf->size; - c.data = gh_buf_detach(buf); + c.data = strbuf_detach(buf); c.alloc = 1; return c; diff --git a/src/html/houdini.h b/src/html/houdini.h index 31fe917..1e54d20 100644 --- a/src/html/houdini.h +++ b/src/html/houdini.h @@ -25,17 +25,17 @@ extern "C" { #define HOUDINI_ESCAPED_SIZE(x) (((x) * 12) / 10) #define HOUDINI_UNESCAPED_SIZE(x) (x) -extern int houdini_escape_html(gh_buf *ob, const uint8_t *src, size_t size); -extern int houdini_escape_html0(gh_buf *ob, const uint8_t *src, size_t size, int secure); -extern int houdini_unescape_html(gh_buf *ob, const uint8_t *src, size_t size); -extern int houdini_escape_xml(gh_buf *ob, const uint8_t *src, size_t size); -extern int houdini_escape_uri(gh_buf *ob, const uint8_t *src, size_t size); -extern int houdini_escape_url(gh_buf *ob, const uint8_t *src, size_t size); -extern int houdini_escape_href(gh_buf *ob, const uint8_t *src, size_t size); -extern int houdini_unescape_uri(gh_buf *ob, const uint8_t *src, size_t size); -extern int houdini_unescape_url(gh_buf *ob, const uint8_t *src, size_t size); -extern int houdini_escape_js(gh_buf *ob, const uint8_t *src, size_t size); -extern int houdini_unescape_js(gh_buf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_html(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_html0(strbuf *ob, const uint8_t *src, size_t size, int secure); +extern int houdini_unescape_html(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_xml(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_uri(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_url(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_href(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_unescape_uri(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_unescape_url(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_escape_js(strbuf *ob, const uint8_t *src, size_t size); +extern int houdini_unescape_js(strbuf *ob, const uint8_t *src, size_t size); #ifdef __cplusplus } diff --git a/src/html/houdini_href_e.c b/src/html/houdini_href_e.c index b2a7d79..12456ce 100644 --- a/src/html/houdini_href_e.c +++ b/src/html/houdini_href_e.c @@ -49,7 +49,7 @@ static const char HREF_SAFE[] = { }; int -houdini_escape_href(gh_buf *ob, const uint8_t *src, size_t size) +houdini_escape_href(strbuf *ob, const uint8_t *src, size_t size) { static const uint8_t hex_chars[] = "0123456789ABCDEF"; size_t i = 0, org; @@ -63,7 +63,7 @@ houdini_escape_href(gh_buf *ob, const uint8_t *src, size_t size) i++; if (likely(i > org)) - gh_buf_put(ob, src + org, i - org); + strbuf_put(ob, src + org, i - org); /* escaping */ if (i >= size) @@ -73,14 +73,14 @@ houdini_escape_href(gh_buf *ob, const uint8_t *src, size_t size) /* amp appears all the time in URLs, but needs * HTML-entity escaping to be inside an href */ case '&': - gh_buf_puts(ob, "&"); + strbuf_puts(ob, "&"); break; /* the single quote is a valid URL character * according to the standard; it needs HTML * entity escaping too */ case '\'': - gh_buf_puts(ob, "'"); + strbuf_puts(ob, "'"); break; /* the space can be escaped to %20 or a plus @@ -89,7 +89,7 @@ houdini_escape_href(gh_buf *ob, const uint8_t *src, size_t size) * when building GET strings */ #if 0 case ' ': - gh_buf_putc(ob, '+'); + strbuf_putc(ob, '+'); break; #endif @@ -97,7 +97,7 @@ houdini_escape_href(gh_buf *ob, const uint8_t *src, size_t size) default: hex_str[1] = hex_chars[(src[i] >> 4) & 0xF]; hex_str[2] = hex_chars[src[i] & 0xF]; - gh_buf_put(ob, hex_str, 3); + strbuf_put(ob, hex_str, 3); } i++; diff --git a/src/html/houdini_html_e.c b/src/html/houdini_html_e.c index 95b6c41..f2e86fe 100644 --- a/src/html/houdini_html_e.c +++ b/src/html/houdini_html_e.c @@ -45,7 +45,7 @@ static const char *HTML_ESCAPES[] = { }; int -houdini_escape_html0(gh_buf *ob, const uint8_t *src, size_t size, int secure) +houdini_escape_html0(strbuf *ob, const uint8_t *src, size_t size, int secure) { size_t i = 0, org, esc = 0; @@ -55,7 +55,7 @@ houdini_escape_html0(gh_buf *ob, const uint8_t *src, size_t size, int secure) i++; if (i > org) - gh_buf_put(ob, src + org, i - org); + strbuf_put(ob, src + org, i - org); /* escaping */ if (unlikely(i >= size)) @@ -63,9 +63,9 @@ houdini_escape_html0(gh_buf *ob, const uint8_t *src, size_t size, int secure) /* The forward slash is only escaped in secure mode */ if ((src[i] == '/' || src[i] == '\'') && !secure) { - gh_buf_putc(ob, src[i]); + strbuf_putc(ob, src[i]); } else { - gh_buf_puts(ob, HTML_ESCAPES[esc]); + strbuf_puts(ob, HTML_ESCAPES[esc]); } i++; @@ -75,7 +75,7 @@ houdini_escape_html0(gh_buf *ob, const uint8_t *src, size_t size, int secure) } int -houdini_escape_html(gh_buf *ob, const uint8_t *src, size_t size) +houdini_escape_html(strbuf *ob, const uint8_t *src, size_t size) { return houdini_escape_html0(ob, src, size, 1); } diff --git a/src/html/html.c b/src/html/html.c index 41b8fda..a9356dd 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -10,7 +10,7 @@ // Functions to convert block and inline lists to HTML strings. -static void escape_html(gh_buf *dest, const unsigned char *source, int length) +static void escape_html(strbuf *dest, const unsigned char *source, int length) { if (length < 0) length = strlen((char *)source); @@ -18,7 +18,7 @@ static void escape_html(gh_buf *dest, const unsigned char *source, int length) houdini_escape_html0(dest, source, (size_t)length, 0); } -static void escape_href(gh_buf *dest, const unsigned char *source, int length) +static void escape_href(strbuf *dest, const unsigned char *source, int length) { if (length < 0) length = strlen((char *)source); @@ -26,14 +26,14 @@ static void escape_href(gh_buf *dest, const unsigned char *source, int length) houdini_escape_href(dest, source, (size_t)length); } -static inline void cr(gh_buf *html) +static inline void cr(strbuf *html) { if (html->size && html->ptr[html->size - 1] != '\n') - gh_buf_putc(html, '\n'); + strbuf_putc(html, '\n'); } // Convert a block list to HTML. Returns 0 on success, and sets result. -void blocks_to_html(gh_buf *html, block *b, bool tight) +void blocks_to_html(strbuf *html, block *b, bool tight) { struct ListData *data; @@ -48,25 +48,25 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) inlines_to_html(html, b->inline_content); } else { cr(html); - gh_buf_puts(html, "

    "); + strbuf_puts(html, "

    "); inlines_to_html(html, b->inline_content); - gh_buf_puts(html, "

    \n"); + strbuf_puts(html, "

    \n"); } break; case block_quote: cr(html); - gh_buf_puts(html, "
    \n"); + strbuf_puts(html, "
    \n"); blocks_to_html(html, b->children, false); - gh_buf_puts(html, "
    \n"); + strbuf_puts(html, "
    \n"); break; case list_item: cr(html); - gh_buf_puts(html, "
  • "); + strbuf_puts(html, "
  • "); blocks_to_html(html, b->children, tight); - gh_buf_trim(html); /* TODO: rtrim */ - gh_buf_puts(html, "
  • \n"); + strbuf_trim(html); /* TODO: rtrim */ + strbuf_puts(html, "\n"); break; case list: @@ -75,58 +75,58 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) data = &(b->attributes.list_data); if (data->start > 1) { - gh_buf_printf(html, "<%s start=\"%d\">\n", + strbuf_printf(html, "<%s start=\"%d\">\n", data->list_type == bullet ? "ul" : "ol", data->start); } else { - gh_buf_puts(html, data->list_type == bullet ? "
      \n" : "
        \n"); + strbuf_puts(html, data->list_type == bullet ? "
          \n" : "
            \n"); } blocks_to_html(html, b->children, data->tight); - gh_buf_puts(html, data->list_type == bullet ? "
        " : "
      "); - gh_buf_putc(html, '\n'); + strbuf_puts(html, data->list_type == bullet ? "
    " : ""); + strbuf_putc(html, '\n'); break; case atx_header: case setext_header: cr(html); - gh_buf_printf(html, "", b->attributes.header_level); + strbuf_printf(html, "", b->attributes.header_level); inlines_to_html(html, b->inline_content); - gh_buf_printf(html, "\n", b->attributes.header_level); + strbuf_printf(html, "\n", b->attributes.header_level); break; case indented_code: case fenced_code: cr(html); - gh_buf_puts(html, "tag == fenced_code) { - gh_buf *info = &b->attributes.fenced_code_data.info; + strbuf *info = &b->attributes.fenced_code_data.info; - if (gh_buf_len(info) > 0) { - int first_tag = gh_buf_strchr(info, ' ', 0); + if (strbuf_len(info) > 0) { + int first_tag = strbuf_strchr(info, ' ', 0); if (first_tag < 0) - first_tag = gh_buf_len(info); + first_tag = strbuf_len(info); - gh_buf_puts(html, " class=\""); + strbuf_puts(html, " class=\""); escape_html(html, info->ptr, first_tag); - gh_buf_putc(html, '"'); + strbuf_putc(html, '"'); } } - gh_buf_puts(html, ">"); + strbuf_puts(html, ">"); escape_html(html, b->string_content.ptr, b->string_content.size); - gh_buf_puts(html, "\n"); + strbuf_puts(html, "\n"); break; case html_block: - gh_buf_put(html, b->string_content.ptr, b->string_content.size); + strbuf_put(html, b->string_content.ptr, b->string_content.size); break; case hrule: - gh_buf_puts(html, "
    \n"); + strbuf_puts(html, "
    \n"); break; case reference_def: @@ -141,9 +141,9 @@ void blocks_to_html(gh_buf *html, block *b, bool tight) } // Convert an inline list to HTML. Returns 0 on success, and sets result. -void inlines_to_html(gh_buf *html, inl* ils) +void inlines_to_html(strbuf *html, inl* ils) { - gh_buf scrap = GH_BUF_INIT; + strbuf scrap = GH_BUF_INIT; while(ils != NULL) { switch(ils->tag) { @@ -152,70 +152,70 @@ void inlines_to_html(gh_buf *html, inl* ils) break; case INL_LINEBREAK: - gh_buf_puts(html, "
    \n"); + strbuf_puts(html, "
    \n"); break; case INL_SOFTBREAK: - gh_buf_putc(html, '\n'); + strbuf_putc(html, '\n'); break; case INL_CODE: - gh_buf_puts(html, ""); + strbuf_puts(html, ""); escape_html(html, ils->content.literal.data, ils->content.literal.len); - gh_buf_puts(html, ""); + strbuf_puts(html, ""); break; case INL_RAW_HTML: case INL_ENTITY: - gh_buf_put(html, + strbuf_put(html, ils->content.literal.data, ils->content.literal.len); break; case INL_LINK: - gh_buf_puts(html, "
    content.linkable.url) escape_href(html, ils->content.linkable.url, -1); if (ils->content.linkable.title) { - gh_buf_puts(html, "\" title=\""); + strbuf_puts(html, "\" title=\""); escape_html(html, ils->content.linkable.title, -1); } - gh_buf_puts(html, "\">"); + strbuf_puts(html, "\">"); inlines_to_html(html, ils->content.inlines); - gh_buf_puts(html, ""); + strbuf_puts(html, ""); break; case INL_IMAGE: - gh_buf_puts(html, "content.linkable.url) escape_href(html, ils->content.linkable.url, -1); inlines_to_html(&scrap, ils->content.inlines); - gh_buf_puts(html, "\" alt=\""); + strbuf_puts(html, "\" alt=\""); if (scrap.size) escape_html(html, scrap.ptr, scrap.size); - gh_buf_clear(&scrap); + strbuf_clear(&scrap); if (ils->content.linkable.title) { - gh_buf_puts(html, "\" title=\""); + strbuf_puts(html, "\" title=\""); escape_html(html, ils->content.linkable.title, -1); } - gh_buf_puts(html, "\"/>"); + strbuf_puts(html, "\"/>"); break; case INL_STRONG: - gh_buf_puts(html, ""); + strbuf_puts(html, ""); inlines_to_html(html, ils->content.inlines); - gh_buf_puts(html, ""); + strbuf_puts(html, ""); break; case INL_EMPH: - gh_buf_puts(html, ""); + strbuf_puts(html, ""); inlines_to_html(html, ils->content.inlines); - gh_buf_puts(html, ""); + strbuf_puts(html, ""); break; } ils = ils->next; diff --git a/src/inlines.c b/src/inlines.c index 8e2e683..33973df 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -25,7 +25,7 @@ inline static void chunk_free(chunk *c); inline static void chunk_trim(chunk *c); inline static chunk chunk_literal(const char *data); -inline static chunk chunk_buf_detach(gh_buf *buf); +inline static chunk chunk_buf_detach(strbuf *buf); inline static chunk chunk_dup(const chunk *ch, int pos, int len); static inl *parse_chunk_inlines(chunk *chunk, reference** refmap); @@ -33,10 +33,10 @@ static inl *parse_inlines_while(subject* subj, int (*f)(subject*)); static int parse_inline(subject* subj, inl ** last); static void subject_from_chunk(subject *e, chunk *chunk, reference** refmap); -static void subject_from_buf(subject *e, gh_buf *buffer, reference** refmap); +static void subject_from_buf(subject *e, strbuf *buffer, reference** refmap); static int subject_find_special_char(subject *subj); -static void normalize_whitespace(gh_buf *s); +static void normalize_whitespace(strbuf *s); extern void free_reference(reference *ref) { free(ref->label); @@ -62,13 +62,13 @@ extern void free_reference_map(reference **refmap) { // remove leading/trailing whitespace, case fold static unsigned char *normalize_reference(chunk *ref) { - gh_buf normalized = GH_BUF_INIT; + strbuf normalized = GH_BUF_INIT; utf8proc_case_fold(&normalized, ref->data, ref->len); - gh_buf_trim(&normalized); + strbuf_trim(&normalized); normalize_whitespace(&normalized); - return gh_buf_detach(&normalized); + return strbuf_detach(&normalized); } // Returns reference if refmap contains a reference with matching @@ -218,7 +218,7 @@ inline static inl* append_inlines(inl* a, inl* b) return a; } -static void subject_from_buf(subject *e, gh_buf *buffer, reference** refmap) +static void subject_from_buf(subject *e, strbuf *buffer, reference** refmap) { e->input.data = buffer->ptr; e->input.len = buffer->size; @@ -309,7 +309,7 @@ static int scan_to_closing_backticks(subject* subj, int openticklength) // Destructively modify string, collapsing consecutive // space and newline characters into a single space. -static void normalize_whitespace(gh_buf *s) +static void normalize_whitespace(strbuf *s) { bool last_char_was_space = false; int r, w; @@ -331,7 +331,7 @@ static void normalize_whitespace(gh_buf *s) } } - gh_buf_truncate(s, w); + strbuf_truncate(s, w); } // Parse backtick code section or raw backticks, return an inline. @@ -346,10 +346,10 @@ static inl* handle_backticks(subject *subj) subj->pos = startpos; // rewind return make_str(openticks); } else { - gh_buf buf = GH_BUF_INIT; + strbuf buf = GH_BUF_INIT; - gh_buf_set(&buf, subj->input.data + startpos, endpos - startpos - openticks.len); - gh_buf_trim(&buf); + strbuf_set(&buf, subj->input.data + startpos, endpos - startpos - openticks.len); + strbuf_trim(&buf); normalize_whitespace(&buf); return make_code(chunk_buf_detach(&buf)); @@ -569,7 +569,7 @@ static inl *make_str_with_entities(chunk *content) } // Destructively unescape a string: remove backslashes before punctuation chars. -extern void unescape_buffer(gh_buf *buf) +extern void unescape_buffer(strbuf *buf) { int r, w; @@ -580,14 +580,14 @@ extern void unescape_buffer(gh_buf *buf) buf->ptr[w++] = buf->ptr[r]; } - gh_buf_truncate(buf, w); + strbuf_truncate(buf, w); } // Clean a URL: remove surrounding whitespace and surrounding <>, // and remove \ that escape punctuation. static unsigned char *clean_url(chunk *url, int is_email) { - gh_buf buf = GH_BUF_INIT; + strbuf buf = GH_BUF_INIT; chunk_trim(url); @@ -595,22 +595,22 @@ static unsigned char *clean_url(chunk *url, int is_email) return NULL; if (is_email) - gh_buf_puts(&buf, "mailto:"); + strbuf_puts(&buf, "mailto:"); if (url->data[0] == '<' && url->data[url->len - 1] == '>') { - gh_buf_put(&buf, url->data + 1, url->len - 2); + strbuf_put(&buf, url->data + 1, url->len - 2); } else { - gh_buf_put(&buf, url->data, url->len); + strbuf_put(&buf, url->data, url->len); } unescape_buffer(&buf); - return gh_buf_detach(&buf); + return strbuf_detach(&buf); } // Clean a title: remove surrounding quotes and remove \ that escape punctuation. static unsigned char *clean_title(chunk *title) { - gh_buf buf = GH_BUF_INIT; + strbuf buf = GH_BUF_INIT; unsigned char first, last; if (title->len == 0) @@ -623,13 +623,13 @@ static unsigned char *clean_title(chunk *title) if ((first == '\'' && last == '\'') || (first == '(' && last == ')') || (first == '"' && last == '"')) { - gh_buf_set(&buf, title->data + 1, title->len - 2); + strbuf_set(&buf, title->data + 1, title->len - 2); } else { - gh_buf_set(&buf, title->data, title->len); + strbuf_set(&buf, title->data, title->len); } unescape_buffer(&buf); - return gh_buf_detach(&buf); + return strbuf_detach(&buf); } // Parse an autolink or HTML tag. @@ -971,7 +971,7 @@ static int parse_inline(subject* subj, inl ** last) return 1; } -extern inl* parse_inlines(gh_buf *input, reference** refmap) +extern inl* parse_inlines(strbuf *input, reference** refmap) { subject subj; subject_from_buf(&subj, input, refmap); @@ -993,7 +993,7 @@ void spnl(subject* subj) // Modify refmap if a reference is encountered. // Return 0 if no reference found, otherwise position of subject // after reference is parsed. -extern int parse_reference(gh_buf *input, reference** refmap) +extern int parse_reference(strbuf *input, reference** refmap) { subject subj; diff --git a/src/main.c b/src/main.c index e1abedc..7cf67e2 100644 --- a/src/main.c +++ b/src/main.c @@ -14,14 +14,14 @@ void print_usage() static void print_document(block *document, bool ast) { - gh_buf html = GH_BUF_INIT; + strbuf html = GH_BUF_INIT; if (ast) { print_blocks(document, 0); } else { blocks_to_html(&html, document, false); printf("%s", html.ptr); - gh_buf_free(&html); + strbuf_free(&html); } } diff --git a/src/stmd.h b/src/stmd.h index 4a3c399..2e86f3a 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -50,7 +50,7 @@ struct FencedCodeData { int fence_length; int fence_offset; char fence_char; - gh_buf info; + strbuf info; }; typedef struct Block { @@ -76,7 +76,7 @@ typedef struct Block { struct Block* last_child; struct Block* parent; struct Block* top; - gh_buf string_content; + strbuf string_content; inl* inline_content; union { struct ListData list_data; @@ -88,15 +88,15 @@ typedef struct Block { struct Block * prev; } block; -inl* parse_inlines(gh_buf *input, reference** refmap); +inl* parse_inlines(strbuf *input, reference** refmap); void free_inlines(inl* e); -int parse_reference(gh_buf *input, reference** refmap); +int parse_reference(strbuf *input, reference** refmap); void free_reference(reference *ref); void free_reference_map(reference **refmap); void add_reference(reference** refmap, reference* ref); -void unescape_buffer(gh_buf *buf); +void unescape_buffer(strbuf *buf); extern block* make_document(); extern block* add_child(block* parent, @@ -109,9 +109,9 @@ extern block *stmd_parse_file(FILE *f); void print_inlines(inl* ils, int indent); void print_blocks(block* blk, int indent); -void blocks_to_html(gh_buf *html, block *b, bool tight); -void inlines_to_html(gh_buf *html, inl *b); +void blocks_to_html(strbuf *html, block *b, bool tight); +void inlines_to_html(strbuf *html, inl *b); -void utf8proc_case_fold(gh_buf *dest, const unsigned char *str, int len); +void utf8proc_case_fold(strbuf *dest, const unsigned char *str, int len); #endif diff --git a/src/utf8.c b/src/utf8.c index 32c78a4..cebd872 100644 --- a/src/utf8.c +++ b/src/utf8.c @@ -84,7 +84,7 @@ ssize_t utf8proc_iterate(const uint8_t *str, ssize_t str_len, int32_t *dst) return length; } -void utf8proc_encode_char(int32_t uc, gh_buf *buf) +void utf8proc_encode_char(int32_t uc, strbuf *buf) { unsigned char dst[4]; int len = 0; @@ -119,10 +119,10 @@ void utf8proc_encode_char(int32_t uc, gh_buf *buf) assert(false); } - gh_buf_put(buf, dst, len); + strbuf_put(buf, dst, len); } -void utf8proc_case_fold(gh_buf *dest, const unsigned char *str, int len) +void utf8proc_case_fold(strbuf *dest, const unsigned char *str, int len) { int32_t c; -- cgit v1.2.3 From 647b15968c95ec268d6d728eea73756c7ba648a8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 18:42:49 +0200 Subject: Rename inl --- src/html/html.c | 2 +- src/inlines.c | 88 ++++++++++++++++++++++++++++----------------------------- src/print.c | 2 +- src/stmd.h | 34 ++++++++++++++-------- 4 files changed, 68 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/html/html.c b/src/html/html.c index a9356dd..53521b8 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -141,7 +141,7 @@ void blocks_to_html(strbuf *html, block *b, bool tight) } // Convert an inline list to HTML. Returns 0 on success, and sets result. -void inlines_to_html(strbuf *html, inl* ils) +void inlines_to_html(strbuf *html, struct inl* ils) { strbuf scrap = GH_BUF_INIT; diff --git a/src/inlines.c b/src/inlines.c index 33973df..301125e 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -28,9 +28,9 @@ inline static chunk chunk_literal(const char *data); inline static chunk chunk_buf_detach(strbuf *buf); inline static chunk chunk_dup(const chunk *ch, int pos, int len); -static inl *parse_chunk_inlines(chunk *chunk, reference** refmap); -static inl *parse_inlines_while(subject* subj, int (*f)(subject*)); -static int parse_inline(subject* subj, inl ** last); +static struct inl *parse_chunk_inlines(chunk *chunk, reference** refmap); +static struct inl *parse_inlines_while(subject* subj, int (*f)(subject*)); +static int parse_inline(subject* subj, struct inl ** last); static void subject_from_chunk(subject *e, chunk *chunk, reference** refmap); static void subject_from_buf(subject *e, strbuf *buffer, reference** refmap); @@ -108,9 +108,9 @@ extern void add_reference(reference** refmap, reference* ref) } } -inline static inl* make_link_from_reference(inl* label, reference *ref) +inline static struct inl* make_link_from_reference(struct inl* label, reference *ref) { - inl* e = (inl*) malloc(sizeof(inl)); + struct inl* e = (struct inl*) malloc(sizeof(struct inl)); e->tag = INL_LINK; e->content.linkable.label = label; e->content.linkable.url = strdup(ref->url); @@ -120,9 +120,9 @@ inline static inl* make_link_from_reference(inl* label, reference *ref) } // Create an inline with a linkable string value. -inline static inl* make_link(inl* label, chunk url, chunk title, int is_email) +inline static struct inl* make_link(struct inl* label, chunk url, chunk title, int is_email) { - inl* e = (inl*) malloc(sizeof(inl)); + struct inl* e = (struct inl*) malloc(sizeof(struct inl)); e->tag = INL_LINK; e->content.linkable.label = label; e->content.linkable.url = clean_url(&url, is_email); @@ -131,9 +131,9 @@ inline static inl* make_link(inl* label, chunk url, chunk title, int is_email) return e; } -inline static inl* make_inlines(int t, inl* contents) +inline static struct inl* make_inlines(int t, struct inl* contents) { - inl* e = (inl*) malloc(sizeof(inl)); + struct inl* e = (struct inl*) malloc(sizeof(struct inl)); e->tag = t; e->content.inlines = contents; e->next = NULL; @@ -141,9 +141,9 @@ inline static inl* make_inlines(int t, inl* contents) } // Create an inline with a literal string value. -inline static inl* make_literal(int t, chunk s) +inline static struct inl* make_literal(int t, chunk s) { - inl* e = (inl*) malloc(sizeof(inl)); + struct inl* e = (struct inl*) malloc(sizeof(struct inl)); e->tag = t; e->content.literal = s; e->next = NULL; @@ -151,9 +151,9 @@ inline static inl* make_literal(int t, chunk s) } // Create an inline with no value. -inline static inl* make_simple(int t) +inline static struct inl* make_simple(int t) { - inl* e = (inl*) malloc(sizeof(inl)); + struct inl* e = (struct inl*) malloc(sizeof(struct inl)); e->tag = t; e->next = NULL; return e; @@ -170,9 +170,9 @@ inline static inl* make_simple(int t) #define make_strong(contents) make_inlines(INL_STRONG, contents) // Free an inline list. -extern void free_inlines(inl* e) +extern void free_inlines(struct inl* e) { - inl * next; + struct inl * next; while (e != NULL) { switch (e->tag){ case INL_STRING: @@ -205,12 +205,12 @@ extern void free_inlines(inl* e) // Append inline list b to the end of inline list a. // Return pointer to head of new list. -inline static inl* append_inlines(inl* a, inl* b) +inline static struct inl* append_inlines(struct inl* a, struct inl* b) { if (a == NULL) { // NULL acts like an empty list return b; } - inl* cur = a; + struct inl* cur = a; while (cur->next) { cur = cur->next; } @@ -336,7 +336,7 @@ static void normalize_whitespace(strbuf *s) // Parse backtick code section or raw backticks, return an inline. // Assumes that the subject has a backtick at the current position. -static inl* handle_backticks(subject *subj) +static struct inl* handle_backticks(subject *subj) { chunk openticks = take_while(subj, isbacktick); int startpos = subj->pos; @@ -382,15 +382,15 @@ static int scan_delims(subject* subj, char c, bool * can_open, bool * can_close) // Parse strong/emph or a fallback. // Assumes the subject has '_' or '*' at the current position. -static inl* handle_strong_emph(subject* subj, char c) +static struct inl* handle_strong_emph(subject* subj, char c) { bool can_open, can_close; - inl * result = NULL; - inl ** last = malloc(sizeof(inl *)); - inl * new; - inl * il; - inl * first_head = NULL; - inl * first_close = NULL; + struct inl * result = NULL; + struct inl ** last = malloc(sizeof(struct inl *)); + struct inl * new; + struct inl * il; + struct inl * first_head = NULL; + struct inl * first_close = NULL; int first_close_delims = 0; int numdelims; @@ -508,7 +508,7 @@ done: } // Parse backslash-escape or just a backslash, returning an inline. -static inl* handle_backslash(subject *subj) +static struct inl* handle_backslash(subject *subj) { advance(subj); unsigned char nextchar = peek_char(subj); @@ -525,10 +525,10 @@ static inl* handle_backslash(subject *subj) // Parse an entity or a regular "&" string. // Assumes the subject has an '&' character at the current position. -static inl* handle_entity(subject* subj) +static struct inl* handle_entity(subject* subj) { int match; - inl *result; + struct inl *result; match = scan_entity(&subj->input, subj->pos); if (match) { result = make_entity(chunk_dup(&subj->input, subj->pos, match)); @@ -542,10 +542,10 @@ static inl* handle_entity(subject* subj) // Like make_str, but parses entities. // Returns an inline sequence consisting of str and entity elements. -static inl *make_str_with_entities(chunk *content) +static struct inl *make_str_with_entities(chunk *content) { - inl *result = NULL; - inl *new; + struct inl *result = NULL; + struct inl *new; int searchpos; char c; subject subj; @@ -634,7 +634,7 @@ static unsigned char *clean_title(chunk *title) // Parse an autolink or HTML tag. // Assumes the subject has a '<' character at the current position. -static inl* handle_pointy_brace(subject* subj) +static struct inl* handle_pointy_brace(subject* subj) { int matchlen = 0; chunk contents; @@ -693,7 +693,7 @@ static inl* handle_pointy_brace(subject* subj) static int link_label(subject* subj, chunk *raw_label) { int nestlevel = 0; - inl* tmp = NULL; + struct inl* tmp = NULL; int startpos = subj->pos; if (subj->label_nestlevel) { @@ -751,10 +751,10 @@ static int link_label(subject* subj, chunk *raw_label) } // Parse a link or the link portion of an image, or return a fallback. -static inl* handle_left_bracket(subject* subj) +static struct inl* handle_left_bracket(subject* subj) { - inl *lab = NULL; - inl *result = NULL; + struct inl *lab = NULL; + struct inl *result = NULL; reference *ref; int n; int sps; @@ -838,7 +838,7 @@ static inl* handle_left_bracket(subject* subj) // Parse a hard or soft linebreak, returning an inline. // Assumes the subject has a newline at the current position. -static inl* handle_newline(subject *subj) +static struct inl* handle_newline(subject *subj) { int nlpos = subj->pos; // skip over newline @@ -862,16 +862,16 @@ inline static int not_eof(subject* subj) } // Parse inlines while a predicate is satisfied. Return inlines. -extern inl* parse_inlines_while(subject* subj, int (*f)(subject*)) +extern struct inl* parse_inlines_while(subject* subj, int (*f)(subject*)) { - inl* result = NULL; - inl** last = &result; + struct inl* result = NULL; + struct inl** last = &result; while ((*f)(subj) && parse_inline(subj, last)) { } return result; } -inl *parse_chunk_inlines(chunk *chunk, reference** refmap) +struct inl *parse_chunk_inlines(chunk *chunk, reference** refmap) { subject subj; subject_from_chunk(&subj, chunk, refmap); @@ -894,9 +894,9 @@ static int subject_find_special_char(subject *subj) // Parse an inline, advancing subject, and add it to last element. // Adjust tail to point to new last element of list. // Return 0 if no inline can be parsed, 1 otherwise. -static int parse_inline(subject* subj, inl ** last) +static int parse_inline(subject* subj, struct inl ** last) { - inl* new = NULL; + struct inl* new = NULL; chunk contents; unsigned char c; int endpos; @@ -971,7 +971,7 @@ static int parse_inline(subject* subj, inl ** last) return 1; } -extern inl* parse_inlines(strbuf *input, reference** refmap) +extern struct inl* parse_inlines(strbuf *input, reference** refmap) { subject subj; subject_from_buf(&subj, input, refmap); diff --git a/src/print.c b/src/print.c index 832ad4f..63f63c8 100644 --- a/src/print.c +++ b/src/print.c @@ -117,7 +117,7 @@ extern void print_blocks(block* b, int indent) } // Prettyprint an inline list, for debugging. -extern void print_inlines(inl* ils, int indent) +extern void print_inlines(struct inl* ils, int indent) { while(ils != NULL) { for (int i=0; i < indent; i++) { diff --git a/src/stmd.h b/src/stmd.h index 2e86f3a..9ed33ec 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -10,20 +10,30 @@ #define VERSION "0.1" #define CODE_INDENT 4 -typedef struct Inline { - enum { INL_STRING, INL_SOFTBREAK, INL_LINEBREAK, INL_CODE, INL_RAW_HTML, INL_ENTITY, - INL_EMPH, INL_STRONG, INL_LINK, INL_IMAGE } tag; +struct inl { + enum { + INL_STRING, + INL_SOFTBREAK, + INL_LINEBREAK, + INL_CODE, + INL_RAW_HTML, + INL_ENTITY, + INL_EMPH, + INL_STRONG, + INL_LINK, + INL_IMAGE + } tag; union { chunk literal; - struct Inline *inlines; + struct inl *inlines; struct { - struct Inline *label; + struct inl *label; unsigned char *url; unsigned char *title; } linkable; } content; - struct Inline *next; -} inl; + struct inl *next; +}; typedef struct Reference { unsigned char *label; @@ -77,7 +87,7 @@ typedef struct Block { struct Block* parent; struct Block* top; strbuf string_content; - inl* inline_content; + struct inl* inline_content; union { struct ListData list_data; struct FencedCodeData fenced_code_data; @@ -88,8 +98,8 @@ typedef struct Block { struct Block * prev; } block; -inl* parse_inlines(strbuf *input, reference** refmap); -void free_inlines(inl* e); +struct inl* parse_inlines(strbuf *input, reference** refmap); +void free_inlines(struct inl* e); int parse_reference(strbuf *input, reference** refmap); void free_reference(reference *ref); @@ -106,11 +116,11 @@ void free_blocks(block* e); extern block *stmd_parse_document(const unsigned char *buffer, size_t len); extern block *stmd_parse_file(FILE *f); -void print_inlines(inl* ils, int indent); +void print_inlines(struct inl* ils, int indent); void print_blocks(block* blk, int indent); void blocks_to_html(strbuf *html, block *b, bool tight); -void inlines_to_html(strbuf *html, inl *b); +void inlines_to_html(strbuf *html, struct inl *b); void utf8proc_case_fold(strbuf *dest, const unsigned char *str, int len); -- cgit v1.2.3 From 9e4855365b920c2a80b0f1ab6937280f0b504334 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 18:45:44 +0200 Subject: Rename `inl` --- src/html/html.c | 2 +- src/inlines.c | 88 ++++++++++++++++++++++++++++----------------------------- src/print.c | 2 +- src/stmd.h | 28 ++++++++++-------- 4 files changed, 62 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/html/html.c b/src/html/html.c index 53521b8..a7bb21a 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -141,7 +141,7 @@ void blocks_to_html(strbuf *html, block *b, bool tight) } // Convert an inline list to HTML. Returns 0 on success, and sets result. -void inlines_to_html(strbuf *html, struct inl* ils) +void inlines_to_html(strbuf *html, node_inl* ils) { strbuf scrap = GH_BUF_INIT; diff --git a/src/inlines.c b/src/inlines.c index 301125e..6bb89da 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -28,9 +28,9 @@ inline static chunk chunk_literal(const char *data); inline static chunk chunk_buf_detach(strbuf *buf); inline static chunk chunk_dup(const chunk *ch, int pos, int len); -static struct inl *parse_chunk_inlines(chunk *chunk, reference** refmap); -static struct inl *parse_inlines_while(subject* subj, int (*f)(subject*)); -static int parse_inline(subject* subj, struct inl ** last); +static node_inl *parse_chunk_inlines(chunk *chunk, reference** refmap); +static node_inl *parse_inlines_while(subject* subj, int (*f)(subject*)); +static int parse_inline(subject* subj, node_inl ** last); static void subject_from_chunk(subject *e, chunk *chunk, reference** refmap); static void subject_from_buf(subject *e, strbuf *buffer, reference** refmap); @@ -108,9 +108,9 @@ extern void add_reference(reference** refmap, reference* ref) } } -inline static struct inl* make_link_from_reference(struct inl* label, reference *ref) +inline static node_inl* make_link_from_reference(node_inl* label, reference *ref) { - struct inl* e = (struct inl*) malloc(sizeof(struct inl)); + node_inl* e = (node_inl*) malloc(sizeof(node_inl)); e->tag = INL_LINK; e->content.linkable.label = label; e->content.linkable.url = strdup(ref->url); @@ -120,9 +120,9 @@ inline static struct inl* make_link_from_reference(struct inl* label, reference } // Create an inline with a linkable string value. -inline static struct inl* make_link(struct inl* label, chunk url, chunk title, int is_email) +inline static node_inl* make_link(node_inl* label, chunk url, chunk title, int is_email) { - struct inl* e = (struct inl*) malloc(sizeof(struct inl)); + node_inl* e = (node_inl*) malloc(sizeof(node_inl)); e->tag = INL_LINK; e->content.linkable.label = label; e->content.linkable.url = clean_url(&url, is_email); @@ -131,9 +131,9 @@ inline static struct inl* make_link(struct inl* label, chunk url, chunk title, i return e; } -inline static struct inl* make_inlines(int t, struct inl* contents) +inline static node_inl* make_inlines(int t, node_inl* contents) { - struct inl* e = (struct inl*) malloc(sizeof(struct inl)); + node_inl* e = (node_inl*) malloc(sizeof(node_inl)); e->tag = t; e->content.inlines = contents; e->next = NULL; @@ -141,9 +141,9 @@ inline static struct inl* make_inlines(int t, struct inl* contents) } // Create an inline with a literal string value. -inline static struct inl* make_literal(int t, chunk s) +inline static node_inl* make_literal(int t, chunk s) { - struct inl* e = (struct inl*) malloc(sizeof(struct inl)); + node_inl* e = (node_inl*) malloc(sizeof(node_inl)); e->tag = t; e->content.literal = s; e->next = NULL; @@ -151,9 +151,9 @@ inline static struct inl* make_literal(int t, chunk s) } // Create an inline with no value. -inline static struct inl* make_simple(int t) +inline static node_inl* make_simple(int t) { - struct inl* e = (struct inl*) malloc(sizeof(struct inl)); + node_inl* e = (node_inl*) malloc(sizeof(node_inl)); e->tag = t; e->next = NULL; return e; @@ -170,9 +170,9 @@ inline static struct inl* make_simple(int t) #define make_strong(contents) make_inlines(INL_STRONG, contents) // Free an inline list. -extern void free_inlines(struct inl* e) +extern void free_inlines(node_inl* e) { - struct inl * next; + node_inl * next; while (e != NULL) { switch (e->tag){ case INL_STRING: @@ -205,12 +205,12 @@ extern void free_inlines(struct inl* e) // Append inline list b to the end of inline list a. // Return pointer to head of new list. -inline static struct inl* append_inlines(struct inl* a, struct inl* b) +inline static node_inl* append_inlines(node_inl* a, node_inl* b) { if (a == NULL) { // NULL acts like an empty list return b; } - struct inl* cur = a; + node_inl* cur = a; while (cur->next) { cur = cur->next; } @@ -336,7 +336,7 @@ static void normalize_whitespace(strbuf *s) // Parse backtick code section or raw backticks, return an inline. // Assumes that the subject has a backtick at the current position. -static struct inl* handle_backticks(subject *subj) +static node_inl* handle_backticks(subject *subj) { chunk openticks = take_while(subj, isbacktick); int startpos = subj->pos; @@ -382,15 +382,15 @@ static int scan_delims(subject* subj, char c, bool * can_open, bool * can_close) // Parse strong/emph or a fallback. // Assumes the subject has '_' or '*' at the current position. -static struct inl* handle_strong_emph(subject* subj, char c) +static node_inl* handle_strong_emph(subject* subj, char c) { bool can_open, can_close; - struct inl * result = NULL; - struct inl ** last = malloc(sizeof(struct inl *)); - struct inl * new; - struct inl * il; - struct inl * first_head = NULL; - struct inl * first_close = NULL; + node_inl * result = NULL; + node_inl ** last = malloc(sizeof(node_inl *)); + node_inl * new; + node_inl * il; + node_inl * first_head = NULL; + node_inl * first_close = NULL; int first_close_delims = 0; int numdelims; @@ -508,7 +508,7 @@ done: } // Parse backslash-escape or just a backslash, returning an inline. -static struct inl* handle_backslash(subject *subj) +static node_inl* handle_backslash(subject *subj) { advance(subj); unsigned char nextchar = peek_char(subj); @@ -525,10 +525,10 @@ static struct inl* handle_backslash(subject *subj) // Parse an entity or a regular "&" string. // Assumes the subject has an '&' character at the current position. -static struct inl* handle_entity(subject* subj) +static node_inl* handle_entity(subject* subj) { int match; - struct inl *result; + node_inl *result; match = scan_entity(&subj->input, subj->pos); if (match) { result = make_entity(chunk_dup(&subj->input, subj->pos, match)); @@ -542,10 +542,10 @@ static struct inl* handle_entity(subject* subj) // Like make_str, but parses entities. // Returns an inline sequence consisting of str and entity elements. -static struct inl *make_str_with_entities(chunk *content) +static node_inl *make_str_with_entities(chunk *content) { - struct inl *result = NULL; - struct inl *new; + node_inl *result = NULL; + node_inl *new; int searchpos; char c; subject subj; @@ -634,7 +634,7 @@ static unsigned char *clean_title(chunk *title) // Parse an autolink or HTML tag. // Assumes the subject has a '<' character at the current position. -static struct inl* handle_pointy_brace(subject* subj) +static node_inl* handle_pointy_brace(subject* subj) { int matchlen = 0; chunk contents; @@ -693,7 +693,7 @@ static struct inl* handle_pointy_brace(subject* subj) static int link_label(subject* subj, chunk *raw_label) { int nestlevel = 0; - struct inl* tmp = NULL; + node_inl* tmp = NULL; int startpos = subj->pos; if (subj->label_nestlevel) { @@ -751,10 +751,10 @@ static int link_label(subject* subj, chunk *raw_label) } // Parse a link or the link portion of an image, or return a fallback. -static struct inl* handle_left_bracket(subject* subj) +static node_inl* handle_left_bracket(subject* subj) { - struct inl *lab = NULL; - struct inl *result = NULL; + node_inl *lab = NULL; + node_inl *result = NULL; reference *ref; int n; int sps; @@ -838,7 +838,7 @@ static struct inl* handle_left_bracket(subject* subj) // Parse a hard or soft linebreak, returning an inline. // Assumes the subject has a newline at the current position. -static struct inl* handle_newline(subject *subj) +static node_inl* handle_newline(subject *subj) { int nlpos = subj->pos; // skip over newline @@ -862,16 +862,16 @@ inline static int not_eof(subject* subj) } // Parse inlines while a predicate is satisfied. Return inlines. -extern struct inl* parse_inlines_while(subject* subj, int (*f)(subject*)) +extern node_inl* parse_inlines_while(subject* subj, int (*f)(subject*)) { - struct inl* result = NULL; - struct inl** last = &result; + node_inl* result = NULL; + node_inl** last = &result; while ((*f)(subj) && parse_inline(subj, last)) { } return result; } -struct inl *parse_chunk_inlines(chunk *chunk, reference** refmap) +node_inl *parse_chunk_inlines(chunk *chunk, reference** refmap) { subject subj; subject_from_chunk(&subj, chunk, refmap); @@ -894,9 +894,9 @@ static int subject_find_special_char(subject *subj) // Parse an inline, advancing subject, and add it to last element. // Adjust tail to point to new last element of list. // Return 0 if no inline can be parsed, 1 otherwise. -static int parse_inline(subject* subj, struct inl ** last) +static int parse_inline(subject* subj, node_inl ** last) { - struct inl* new = NULL; + node_inl* new = NULL; chunk contents; unsigned char c; int endpos; @@ -971,7 +971,7 @@ static int parse_inline(subject* subj, struct inl ** last) return 1; } -extern struct inl* parse_inlines(strbuf *input, reference** refmap) +extern node_inl* parse_inlines(strbuf *input, reference** refmap) { subject subj; subject_from_buf(&subj, input, refmap); diff --git a/src/print.c b/src/print.c index 63f63c8..01e9136 100644 --- a/src/print.c +++ b/src/print.c @@ -117,7 +117,7 @@ extern void print_blocks(block* b, int indent) } // Prettyprint an inline list, for debugging. -extern void print_inlines(struct inl* ils, int indent) +extern void print_inlines(node_inl* ils, int indent) { while(ils != NULL) { for (int i=0; i < indent; i++) { diff --git a/src/stmd.h b/src/stmd.h index 9ed33ec..dbc8c8c 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -10,7 +10,7 @@ #define VERSION "0.1" #define CODE_INDENT 4 -struct inl { +struct node_inl { enum { INL_STRING, INL_SOFTBREAK, @@ -25,22 +25,26 @@ struct inl { } tag; union { chunk literal; - struct inl *inlines; + struct node_inl *inlines; struct { - struct inl *label; + struct node_inl *label; unsigned char *url; unsigned char *title; } linkable; } content; - struct inl *next; + struct node_inl *next; }; -typedef struct Reference { +typedef struct node_inl node_inl; + +struct reference { unsigned char *label; unsigned char *url; unsigned char *title; - UT_hash_handle hh; // used by uthash -} reference; + UT_hash_handle hh; // used by uthash +}; + +typedef struct reference reference; // Types for blocks @@ -87,7 +91,7 @@ typedef struct Block { struct Block* parent; struct Block* top; strbuf string_content; - struct inl* inline_content; + node_inl* inline_content; union { struct ListData list_data; struct FencedCodeData fenced_code_data; @@ -98,8 +102,8 @@ typedef struct Block { struct Block * prev; } block; -struct inl* parse_inlines(strbuf *input, reference** refmap); -void free_inlines(struct inl* e); +node_inl* parse_inlines(strbuf *input, reference** refmap); +void free_inlines(node_inl* e); int parse_reference(strbuf *input, reference** refmap); void free_reference(reference *ref); @@ -116,11 +120,11 @@ void free_blocks(block* e); extern block *stmd_parse_document(const unsigned char *buffer, size_t len); extern block *stmd_parse_file(FILE *f); -void print_inlines(struct inl* ils, int indent); +void print_inlines(node_inl* ils, int indent); void print_blocks(block* blk, int indent); void blocks_to_html(strbuf *html, block *b, bool tight); -void inlines_to_html(strbuf *html, struct inl *b); +void inlines_to_html(strbuf *html, node_inl *b); void utf8proc_case_fold(strbuf *dest, const unsigned char *str, int len); -- cgit v1.2.3 From 19ba82d7a30bd999a25fc303a8516056880abc9d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 18:49:33 +0200 Subject: Rename node_block --- src/blocks.c | 100 ++++++++++++++++++++++++++++---------------------------- src/html/html.c | 6 ++-- src/main.c | 4 +-- src/print.c | 4 +-- src/stmd.h | 57 +++++++++++++++++--------------- 5 files changed, 87 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/blocks.c b/src/blocks.c index 9faccd9..d74ceb2 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -10,13 +10,13 @@ #define peek_at(i, n) (i)->data[n] -static void incorporate_line(strbuf *ln, int line_number, block** curptr); -static void finalize(block* b, int line_number); +static void incorporate_line(strbuf *ln, int line_number, node_block** curptr); +static void finalize(node_block* b, int line_number); -static block* make_block(int tag, int start_line, int start_column) +static node_block* make_block(int tag, int start_line, int start_column) { - block* e; - e = (block*) malloc(sizeof(block)); + node_block* e; + e = (node_block*) malloc(sizeof(node_block)); e->tag = tag; e->open = true; e->last_line_blank = false; @@ -35,10 +35,10 @@ static block* make_block(int tag, int start_line, int start_column) return e; } -// Create a root document block. -extern block* make_document() +// Create a root document node_block. +extern node_block* make_document() { - block * e = make_block(document, 1, 1); + node_block * e = make_block(document, 1, 1); reference * map = NULL; reference ** refmap; refmap = (reference**) malloc(sizeof(reference*)); @@ -82,10 +82,10 @@ static inline bool accepts_lines(int block_type) block_type == fenced_code); } -static void add_line(block* block, chunk *ch, int offset) +static void add_line(node_block* node_block, chunk *ch, int offset) { - assert(block->open); - strbuf_put(&block->string_content, ch->data + offset, ch->len - offset); + assert(node_block->open); + strbuf_put(&node_block->string_content, ch->data + offset, ch->len - offset); } static void remove_trailing_blank_lines(strbuf *ln) @@ -109,25 +109,25 @@ static void remove_trailing_blank_lines(strbuf *ln) strbuf_truncate(ln, i); } -// Check to see if a block ends with a blank line, descending +// Check to see if a node_block ends with a blank line, descending // if needed into lists and sublists. -static bool ends_with_blank_line(block* block) +static bool ends_with_blank_line(node_block* node_block) { - if (block->last_line_blank) { + if (node_block->last_line_blank) { return true; } - if ((block->tag == list || block->tag == list_item) && block->last_child) { - return ends_with_blank_line(block->last_child); + if ((node_block->tag == list || node_block->tag == list_item) && node_block->last_child) { + return ends_with_blank_line(node_block->last_child); } else { return false; } } // Break out of all containing lists -static int break_out_of_lists(block ** bptr, int line_number) +static int break_out_of_lists(node_block ** bptr, int line_number) { - block * container = *bptr; - block * b = container->top; + node_block * container = *bptr; + node_block * b = container->top; // find first containing list: while (b && b->tag != list) { b = b->last_child; @@ -144,15 +144,15 @@ static int break_out_of_lists(block ** bptr, int line_number) } -static void finalize(block* b, int line_number) +static void finalize(node_block* b, int line_number) { int firstlinelen; int pos; - block* item; - block* subitem; + node_block* item; + node_block* subitem; if (!b->open) - return; // don't do anything if the block is already closed + return; // don't do anything if the node_block is already closed b->open = false; if (line_number > b->start_line) { @@ -230,20 +230,20 @@ static void finalize(block* b, int line_number) } } -// Add a block as child of another. Return pointer to child. -extern block* add_child(block* parent, +// Add a node_block as child of another. Return pointer to child. +extern node_block* add_child(node_block* parent, int block_type, int start_line, int start_column) { assert(parent); - // if 'parent' isn't the kind of block that can accept this child, - // then back up til we hit a block that can. + // if 'parent' isn't the kind of node_block that can accept this child, + // then back up til we hit a node_block that can. while (!can_contain(parent->tag, block_type)) { finalize(parent, start_line); parent = parent->parent; } - block* child = make_block(block_type, start_line, start_column); + node_block* child = make_block(block_type, start_line, start_column); child->parent = parent; child->top = parent->top; @@ -258,10 +258,10 @@ extern block* add_child(block* parent, return child; } -// Free a block list and any children. -extern void free_blocks(block* e) +// Free a node_block list and any children. +extern void free_blocks(node_block* e) { - block * next; + node_block * next; while (e != NULL) { next = e->next; free_inlines(e->inline_content); @@ -277,9 +277,9 @@ extern void free_blocks(block* e) } } -// Walk through block and all children, recursively, parsing +// Walk through node_block and all children, recursively, parsing // string content into inline content where appropriate. -void process_inlines(block* cur, reference** refmap) +void process_inlines(node_block* cur, reference** refmap) { switch (cur->tag) { case paragraph: @@ -294,7 +294,7 @@ void process_inlines(block* cur, reference** refmap) break; } - block *child = cur->children; + node_block *child = cur->children; while (child != NULL) { process_inlines(child, refmap); child = child->next; @@ -394,7 +394,7 @@ static void expand_tabs(strbuf *ob, const unsigned char *line, size_t size) } } -static block *finalize_document(block *document, int linenum) +static node_block *finalize_document(node_block *document, int linenum) { while (document != document->top) { finalize(document, linenum); @@ -407,12 +407,12 @@ static block *finalize_document(block *document, int linenum) return document; } -extern block *stmd_parse_file(FILE *f) +extern node_block *stmd_parse_file(FILE *f) { strbuf line = GH_BUF_INIT; unsigned char buffer[4096]; int linenum = 1; - block *document = make_document(); + node_block *document = make_document(); while (fgets((char *)buffer, sizeof(buffer), f)) { expand_tabs(&line, buffer, strlen((char *)buffer)); @@ -425,12 +425,12 @@ extern block *stmd_parse_file(FILE *f) return finalize_document(document, linenum); } -extern block *stmd_parse_document(const unsigned char *buffer, size_t len) +extern node_block *stmd_parse_document(const unsigned char *buffer, size_t len) { strbuf line = GH_BUF_INIT; int linenum = 1; const unsigned char *end = buffer + len; - block *document = make_document(); + node_block *document = make_document(); while (buffer < end) { const unsigned char *eol = memchr(buffer, '\n', end - buffer); @@ -470,18 +470,18 @@ static void chop_trailing_hashtags(chunk *ch) ch->len = n + 1; } -// Process one line at a time, modifying a block. -static void incorporate_line(strbuf *line, int line_number, block** curptr) +// Process one line at a time, modifying a node_block. +static void incorporate_line(strbuf *line, int line_number, node_block** curptr) { - block* last_matched_container; + node_block* last_matched_container; int offset = 0; int matched = 0; int lev = 0; int i; struct ListData * data = NULL; bool all_matched = true; - block* container; - block* cur = *curptr; + node_block* container; + node_block* cur = *curptr; bool blank = false; int first_nonspace; int indent; @@ -493,8 +493,8 @@ static void incorporate_line(strbuf *line, int line_number, block** curptr) // container starts at the document root. container = cur->top; - // for each containing block, try to parse the associated line start. - // bail out on failure: container will point to the last matching block. + // for each containing node_block, try to parse the associated line start. + // bail out on failure: container will point to the last matching node_block. while (container->last_child && container->last_child->open) { container = container->last_child; @@ -570,7 +570,7 @@ static void incorporate_line(strbuf *line, int line_number, block** curptr) } if (!all_matched) { - container = container->parent; // back up to last matching block + container = container->parent; // back up to last matching node_block break; } } @@ -582,7 +582,7 @@ static void incorporate_line(strbuf *line, int line_number, block** curptr) break_out_of_lists(&container, line_number); } - // unless last matched container is code block, try new container starts: + // unless last matched container is code node_block, try new container starts: while (container->tag != fenced_code && container->tag != indented_code && container->tag != html_block) { @@ -713,7 +713,7 @@ static void incorporate_line(strbuf *line, int line_number, block** curptr) indent = first_nonspace - offset; blank = peek_at(&input, first_nonspace) == '\n'; - // block quote lines are never blank as they start with > + // node_block quote lines are never blank as they start with > // and we don't count blanks in fenced code for purposes of tight/loose // lists or breaking out of lists. we also don't set last_line_blank // on an empty list item. @@ -724,7 +724,7 @@ static void incorporate_line(strbuf *line, int line_number, block** curptr) container->children == NULL && container->start_line == line_number)); - block *cont = container; + node_block *cont = container; while (cont->parent) { cont->parent->last_line_blank = false; cont = cont->parent; diff --git a/src/html/html.c b/src/html/html.c index a7bb21a..6041fde 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -8,7 +8,7 @@ #include "debug.h" #include "html/houdini.h" -// Functions to convert block and inline lists to HTML strings. +// Functions to convert node_block and inline lists to HTML strings. static void escape_html(strbuf *dest, const unsigned char *source, int length) { @@ -32,8 +32,8 @@ static inline void cr(strbuf *html) strbuf_putc(html, '\n'); } -// Convert a block list to HTML. Returns 0 on success, and sets result. -void blocks_to_html(strbuf *html, block *b, bool tight) +// Convert a node_block list to HTML. Returns 0 on success, and sets result. +void blocks_to_html(strbuf *html, node_block *b, bool tight) { struct ListData *data; diff --git a/src/main.c b/src/main.c index 7cf67e2..90bb16d 100644 --- a/src/main.c +++ b/src/main.c @@ -12,7 +12,7 @@ void print_usage() printf(" --version Print version\n"); } -static void print_document(block *document, bool ast) +static void print_document(node_block *document, bool ast) { strbuf html = GH_BUF_INIT; @@ -30,7 +30,7 @@ int main(int argc, char *argv[]) int i, numfps = 0; bool ast = false; int files[argc]; - block *document = NULL; + node_block *document = NULL; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--version") == 0) { diff --git a/src/print.c b/src/print.c index 01e9136..069d299 100644 --- a/src/print.c +++ b/src/print.c @@ -32,9 +32,9 @@ static void print_str(const unsigned char *s, int len) putchar('"'); } -// Functions to pretty-print inline and block lists, for debugging. +// Functions to pretty-print inline and node_block lists, for debugging. // Prettyprint an inline list, for debugging. -extern void print_blocks(block* b, int indent) +extern void print_blocks(node_block* b, int indent) { struct ListData *data; diff --git a/src/stmd.h b/src/stmd.h index dbc8c8c..957ab03 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -67,29 +67,30 @@ struct FencedCodeData { strbuf info; }; -typedef struct Block { - enum { document, - block_quote, - list, - list_item, - fenced_code, - indented_code, - html_block, - paragraph, - atx_header, - setext_header, - hrule, - reference_def +struct node_block { + enum { + document, + block_quote, + list, + list_item, + fenced_code, + indented_code, + html_block, + paragraph, + atx_header, + setext_header, + hrule, + reference_def } tag; int start_line; int start_column; int end_line; bool open; bool last_line_blank; - struct Block* children; - struct Block* last_child; - struct Block* parent; - struct Block* top; + struct node_block* children; + struct node_block* last_child; + struct node_block* parent; + struct node_block* top; strbuf string_content; node_inl* inline_content; union { @@ -98,9 +99,11 @@ typedef struct Block { int header_level; reference** refmap; } attributes; - struct Block * next; - struct Block * prev; -} block; + struct node_block * next; + struct node_block * prev; +}; + +typedef struct node_block node_block; node_inl* parse_inlines(strbuf *input, reference** refmap); void free_inlines(node_inl* e); @@ -112,18 +115,18 @@ void free_reference_map(reference **refmap); void add_reference(reference** refmap, reference* ref); void unescape_buffer(strbuf *buf); -extern block* make_document(); -extern block* add_child(block* parent, +extern node_block* make_document(); +extern node_block* add_child(node_block* parent, int block_type, int start_line, int start_column); -void free_blocks(block* e); +void free_blocks(node_block* e); -extern block *stmd_parse_document(const unsigned char *buffer, size_t len); -extern block *stmd_parse_file(FILE *f); +extern node_block *stmd_parse_document(const unsigned char *buffer, size_t len); +extern node_block *stmd_parse_file(FILE *f); void print_inlines(node_inl* ils, int indent); -void print_blocks(block* blk, int indent); +void print_blocks(node_block* blk, int indent); -void blocks_to_html(strbuf *html, block *b, bool tight); +void blocks_to_html(strbuf *html, node_block *b, bool tight); void inlines_to_html(strbuf *html, node_inl *b); void utf8proc_case_fold(strbuf *dest, const unsigned char *str, int len); -- cgit v1.2.3 From 806ff17755c90579afc68914b251b80e2f8c4b77 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 18:56:52 +0200 Subject: Rename block literals --- src/blocks.c | 110 ++++++++++++++++++++++++++++---------------------------- src/html/html.c | 26 +++++++------- src/print.c | 24 ++++++------- src/stmd.h | 43 +++++++++++----------- 4 files changed, 100 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/blocks.c b/src/blocks.c index d74ceb2..f671b5e 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -38,7 +38,7 @@ static node_block* make_block(int tag, int start_line, int start_column) // Create a root document node_block. extern node_block* make_document() { - node_block * e = make_block(document, 1, 1); + node_block * e = make_block(BLOCK_DOCUMENT, 1, 1); reference * map = NULL; reference ** refmap; refmap = (reference**) malloc(sizeof(reference*)); @@ -68,18 +68,18 @@ bool is_blank(strbuf *s, int offset) static inline bool can_contain(int parent_type, int child_type) { - return ( parent_type == document || - parent_type == block_quote || - parent_type == list_item || - (parent_type == list && child_type == list_item) ); + return ( parent_type == BLOCK_DOCUMENT || + parent_type == BLOCK_BQUOTE || + parent_type == BLOCK_LIST_ITEM || + (parent_type == BLOCK_LIST && child_type == BLOCK_LIST_ITEM) ); } static inline bool accepts_lines(int block_type) { - return (block_type == paragraph || - block_type == atx_header || - block_type == indented_code || - block_type == fenced_code); + return (block_type == BLOCK_PARAGRAPH || + block_type == BLOCK_ATX_HEADER || + block_type == BLOCK_INDENTED_CODE || + block_type == BLOCK_FENCED_CODE); } static void add_line(node_block* node_block, chunk *ch, int offset) @@ -116,7 +116,7 @@ static bool ends_with_blank_line(node_block* node_block) if (node_block->last_line_blank) { return true; } - if ((node_block->tag == list || node_block->tag == list_item) && node_block->last_child) { + if ((node_block->tag == BLOCK_LIST || node_block->tag == BLOCK_LIST_ITEM) && node_block->last_child) { return ends_with_blank_line(node_block->last_child); } else { return false; @@ -128,8 +128,8 @@ static int break_out_of_lists(node_block ** bptr, int line_number) { node_block * container = *bptr; node_block * b = container->top; - // find first containing list: - while (b && b->tag != list) { + // find first containing BLOCK_LIST: + while (b && b->tag != BLOCK_LIST) { b = b->last_child; } if (b) { @@ -162,7 +162,7 @@ static void finalize(node_block* b, int line_number) } switch (b->tag) { - case paragraph: + case BLOCK_PARAGRAPH: pos = 0; while (strbuf_at(&b->string_content, 0) == '[' && (pos = parse_reference(&b->string_content, b->top->attributes.refmap))) { @@ -170,16 +170,16 @@ static void finalize(node_block* b, int line_number) strbuf_drop(&b->string_content, pos); } if (is_blank(&b->string_content, 0)) { - b->tag = reference_def; + b->tag = BLOCK_REFERENCE_DEF; } break; - case indented_code: + case BLOCK_INDENTED_CODE: remove_trailing_blank_lines(&b->string_content); strbuf_putc(&b->string_content, '\n'); break; - case fenced_code: + case BLOCK_FENCED_CODE: // first line of contents becomes info firstlinelen = strbuf_strchr(&b->string_content, '\n', 0); @@ -196,7 +196,7 @@ static void finalize(node_block* b, int line_number) unescape_buffer(&b->attributes.fenced_code_data.info); break; - case list: // determine tight/loose status + case BLOCK_LIST: // determine tight/loose status b->attributes.list_data.tight = true; // tight by default item = b->children; @@ -266,9 +266,9 @@ extern void free_blocks(node_block* e) next = e->next; free_inlines(e->inline_content); strbuf_free(&e->string_content); - if (e->tag == fenced_code) { + if (e->tag == BLOCK_FENCED_CODE) { strbuf_free(&e->attributes.fenced_code_data.info); - } else if (e->tag == document) { + } else if (e->tag == BLOCK_DOCUMENT) { free_reference_map(e->attributes.refmap); } free_blocks(e->children); @@ -282,9 +282,9 @@ extern void free_blocks(node_block* e) void process_inlines(node_block* cur, reference** refmap) { switch (cur->tag) { - case paragraph: - case atx_header: - case setext_header: + case BLOCK_PARAGRAPH: + case BLOCK_ATX_HEADER: + case BLOCK_SETEXT_HEADER: cur->inline_content = parse_inlines(&cur->string_content, refmap); // MEM // strbuf_free(&cur->string_content); @@ -507,7 +507,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) indent = first_nonspace - offset; blank = peek_at(&input, first_nonspace) == '\n'; - if (container->tag == block_quote) { + if (container->tag == BLOCK_BQUOTE) { matched = indent <= 3 && peek_at(&input, first_nonspace) == '>'; if (matched) { offset = first_nonspace + 1; @@ -517,7 +517,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) all_matched = false; } - } else if (container->tag == list_item) { + } else if (container->tag == BLOCK_LIST_ITEM) { if (indent >= container->attributes.list_data.marker_offset + container->attributes.list_data.padding) { @@ -529,7 +529,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) all_matched = false; } - } else if (container->tag == indented_code) { + } else if (container->tag == BLOCK_INDENTED_CODE) { if (indent >= CODE_INDENT) { offset += CODE_INDENT; @@ -539,13 +539,13 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) all_matched = false; } - } else if (container->tag == atx_header || - container->tag == setext_header) { + } else if (container->tag == BLOCK_ATX_HEADER || + container->tag == BLOCK_SETEXT_HEADER) { // a header can never contain more than one line all_matched = false; - } else if (container->tag == fenced_code) { + } else if (container->tag == BLOCK_FENCED_CODE) { // skip optional spaces of fence offset i = container->attributes.fenced_code_data.fence_offset; @@ -554,13 +554,13 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) i--; } - } else if (container->tag == html_block) { + } else if (container->tag == BLOCK_HTML) { if (blank) { all_matched = false; } - } else if (container->tag == paragraph) { + } else if (container->tag == BLOCK_PARAGRAPH) { if (blank) { container->last_line_blank = true; @@ -583,8 +583,8 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) } // unless last matched container is code node_block, try new container starts: - while (container->tag != fenced_code && container->tag != indented_code && - container->tag != html_block) { + while (container->tag != BLOCK_FENCED_CODE && container->tag != BLOCK_INDENTED_CODE && + container->tag != BLOCK_HTML) { first_nonspace = offset; while (peek_at(&input, first_nonspace) == ' ') @@ -594,9 +594,9 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) blank = peek_at(&input, first_nonspace) == '\n'; if (indent >= CODE_INDENT) { - if (cur->tag != paragraph && !blank) { + if (cur->tag != BLOCK_PARAGRAPH && !blank) { offset += CODE_INDENT; - container = add_child(container, indented_code, line_number, offset + 1); + container = add_child(container, BLOCK_INDENTED_CODE, line_number, offset + 1); } else { // indent > 4 in lazy line break; } @@ -607,12 +607,12 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) // optional following character if (peek_at(&input, offset) == ' ') offset++; - container = add_child(container, block_quote, line_number, offset + 1); + container = add_child(container, BLOCK_BQUOTE, line_number, offset + 1); } else if ((matched = scan_atx_header_start(&input, first_nonspace))) { offset = first_nonspace + matched; - container = add_child(container, atx_header, line_number, offset + 1); + container = add_child(container, BLOCK_ATX_HEADER, line_number, offset + 1); int hashpos = chunk_strchr(&input, '#', first_nonspace); int level = 0; @@ -625,7 +625,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) } else if ((matched = scan_open_code_fence(&input, first_nonspace))) { - container = add_child(container, fenced_code, line_number, first_nonspace + 1); + container = add_child(container, BLOCK_FENCED_CODE, line_number, first_nonspace + 1); container->attributes.fenced_code_data.fence_char = peek_at(&input, first_nonspace); container->attributes.fenced_code_data.fence_length = matched; container->attributes.fenced_code_data.fence_offset = first_nonspace - offset; @@ -633,24 +633,24 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) } else if ((matched = scan_html_block_tag(&input, first_nonspace))) { - container = add_child(container, html_block, line_number, first_nonspace + 1); + container = add_child(container, BLOCK_HTML, line_number, first_nonspace + 1); // note, we don't adjust offset because the tag is part of the text - } else if (container->tag == paragraph && + } else if (container->tag == BLOCK_PARAGRAPH && (lev = scan_setext_header_line(&input, first_nonspace)) && // check that there is only one line in the paragraph: strbuf_strrchr(&container->string_content, '\n', strbuf_len(&container->string_content) - 2) < 0) { - container->tag = setext_header; + container->tag = BLOCK_SETEXT_HEADER; container->attributes.header_level = lev; offset = input.len - 1; - } else if (!(container->tag == paragraph && !all_matched) && + } else if (!(container->tag == BLOCK_PARAGRAPH && !all_matched) && (matched = scan_hrule(&input, first_nonspace))) { // it's only now that we know the line is not part of a setext header: - container = add_child(container, hrule, line_number, first_nonspace + 1); + container = add_child(container, BLOCK_HRULE, line_number, first_nonspace + 1); finalize(container, line_number); container = container->parent; offset = input.len - 1; @@ -679,15 +679,15 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) data->marker_offset = indent; - if (container->tag != list || + if (container->tag != BLOCK_LIST || !lists_match(container->attributes.list_data, *data)) { - container = add_child(container, list, line_number, + container = add_child(container, BLOCK_LIST, line_number, first_nonspace + 1); container->attributes.list_data = *data; } // add the list item - container = add_child(container, list_item, line_number, + container = add_child(container, BLOCK_LIST_ITEM, line_number, first_nonspace + 1); /* TODO: static */ container->attributes.list_data = *data; @@ -718,9 +718,9 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) // lists or breaking out of lists. we also don't set last_line_blank // on an empty list item. container->last_line_blank = (blank && - container->tag != block_quote && - container->tag != fenced_code && - !(container->tag == list_item && + container->tag != BLOCK_BQUOTE && + container->tag != BLOCK_FENCED_CODE && + !(container->tag == BLOCK_LIST_ITEM && container->children == NULL && container->start_line == line_number)); @@ -733,7 +733,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) if (cur != last_matched_container && container == last_matched_container && !blank && - cur->tag == paragraph && + cur->tag == BLOCK_PARAGRAPH && strbuf_len(&cur->string_content) > 0) { add_line(cur, &input, offset); @@ -747,11 +747,11 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) assert(cur != NULL); } - if (container->tag == indented_code) { + if (container->tag == BLOCK_INDENTED_CODE) { add_line(container, &input, offset); - } else if (container->tag == fenced_code) { + } else if (container->tag == BLOCK_FENCED_CODE) { matched = 0; if (indent <= 3 && @@ -769,7 +769,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) add_line(container, &input, offset); } - } else if (container->tag == html_block) { + } else if (container->tag == BLOCK_HTML) { add_line(container, &input, offset); @@ -777,7 +777,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) // ??? do nothing - } else if (container->tag == atx_header) { + } else if (container->tag == BLOCK_ATX_HEADER) { chop_trailing_hashtags(&input); add_line(container, &input, first_nonspace); @@ -788,10 +788,10 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) add_line(container, &input, first_nonspace); - } else if (container->tag != hrule && container->tag != setext_header) { + } else if (container->tag != BLOCK_HRULE && container->tag != BLOCK_SETEXT_HEADER) { // create paragraph container for line - container = add_child(container, paragraph, line_number, first_nonspace + 1); + container = add_child(container, BLOCK_PARAGRAPH, line_number, first_nonspace + 1); add_line(container, &input, first_nonspace); } else { diff --git a/src/html/html.c b/src/html/html.c index 6041fde..758ec80 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -39,11 +39,11 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) while(b != NULL) { switch(b->tag) { - case document: + case BLOCK_DOCUMENT: blocks_to_html(html, b->children, false); break; - case paragraph: + case BLOCK_PARAGRAPH: if (tight) { inlines_to_html(html, b->inline_content); } else { @@ -54,14 +54,14 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) } break; - case block_quote: + case BLOCK_BQUOTE: cr(html); strbuf_puts(html, "
    \n"); blocks_to_html(html, b->children, false); strbuf_puts(html, "
    \n"); break; - case list_item: + case BLOCK_LIST_ITEM: cr(html); strbuf_puts(html, "
  • "); blocks_to_html(html, b->children, tight); @@ -69,7 +69,7 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) strbuf_puts(html, "
  • \n"); break; - case list: + case BLOCK_LIST: // make sure a list starts at the beginning of the line: cr(html); data = &(b->attributes.list_data); @@ -87,21 +87,21 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) strbuf_putc(html, '\n'); break; - case atx_header: - case setext_header: + case BLOCK_ATX_HEADER: + case BLOCK_SETEXT_HEADER: cr(html); strbuf_printf(html, "", b->attributes.header_level); inlines_to_html(html, b->inline_content); strbuf_printf(html, "\n", b->attributes.header_level); break; - case indented_code: - case fenced_code: + case BLOCK_INDENTED_CODE: + case BLOCK_FENCED_CODE: cr(html); strbuf_puts(html, "tag == fenced_code) { + if (b->tag == BLOCK_FENCED_CODE) { strbuf *info = &b->attributes.fenced_code_data.info; if (strbuf_len(info) > 0) { @@ -121,15 +121,15 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) strbuf_puts(html, "\n"); break; - case html_block: + case BLOCK_HTML: strbuf_put(html, b->string_content.ptr, b->string_content.size); break; - case hrule: + case BLOCK_HRULE: strbuf_puts(html, "
    \n"); break; - case reference_def: + case BLOCK_REFERENCE_DEF: break; default: diff --git a/src/print.c b/src/print.c index 069d299..0ff86fa 100644 --- a/src/print.c +++ b/src/print.c @@ -45,20 +45,20 @@ extern void print_blocks(node_block* b, int indent) } switch(b->tag) { - case document: + case BLOCK_DOCUMENT: printf("document\n"); print_blocks(b->children, indent + 2); break; - case block_quote: + case BLOCK_BQUOTE: printf("block_quote\n"); print_blocks(b->children, indent + 2); break; - case list_item: + case BLOCK_LIST_ITEM: data = &(b->attributes.list_data); printf("list_item\n"); print_blocks(b->children, indent + 2); break; - case list: + case BLOCK_LIST: data = &(b->attributes.list_data); if (data->list_type == ordered) { printf("list (type=ordered tight=%s start=%d delim=%s)\n", @@ -72,27 +72,27 @@ extern void print_blocks(node_block* b, int indent) } print_blocks(b->children, indent + 2); break; - case atx_header: + case BLOCK_ATX_HEADER: printf("atx_header (level=%d)\n", b->attributes.header_level); print_inlines(b->inline_content, indent + 2); break; - case setext_header: + case BLOCK_SETEXT_HEADER: printf("setext_header (level=%d)\n", b->attributes.header_level); print_inlines(b->inline_content, indent + 2); break; - case paragraph: + case BLOCK_PARAGRAPH: printf("paragraph\n"); print_inlines(b->inline_content, indent + 2); break; - case hrule: + case BLOCK_HRULE: printf("hrule\n"); break; - case indented_code: + case BLOCK_INDENTED_CODE: printf("indented_code "); print_str(b->string_content.ptr, -1); putchar('\n'); break; - case fenced_code: + case BLOCK_FENCED_CODE: printf("fenced_code length=%d info=", b->attributes.fenced_code_data.fence_length); print_str(b->attributes.fenced_code_data.info.ptr, -1); @@ -100,12 +100,12 @@ extern void print_blocks(node_block* b, int indent) print_str(b->string_content.ptr, -1); putchar('\n'); break; - case html_block: + case BLOCK_HTML: printf("html_block "); print_str(b->string_content.ptr, -1); putchar('\n'); break; - case reference_def: + case BLOCK_REFERENCE_DEF: printf("reference_def\n"); break; default: diff --git a/src/stmd.h b/src/stmd.h index 957ab03..65063fa 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -67,30 +67,29 @@ struct FencedCodeData { strbuf info; }; -struct node_block { - enum { - document, - block_quote, - list, - list_item, - fenced_code, - indented_code, - html_block, - paragraph, - atx_header, - setext_header, - hrule, - reference_def +typedef struct Block { + enum { BLOCK_DOCUMENT, + BLOCK_BQUOTE, + BLOCK_LIST, + BLOCK_LIST_ITEM, + BLOCK_FENCED_CODE, + BLOCK_INDENTED_CODE, + BLOCK_HTML, + BLOCK_PARAGRAPH, + BLOCK_ATX_HEADER, + BLOCK_SETEXT_HEADER, + BLOCK_HRULE, + BLOCK_REFERENCE_DEF } tag; int start_line; int start_column; int end_line; bool open; bool last_line_blank; - struct node_block* children; - struct node_block* last_child; - struct node_block* parent; - struct node_block* top; + struct Block* children; + struct Block* last_child; + struct Block* parent; + struct Block* top; strbuf string_content; node_inl* inline_content; union { @@ -99,11 +98,9 @@ struct node_block { int header_level; reference** refmap; } attributes; - struct node_block * next; - struct node_block * prev; -}; - -typedef struct node_block node_block; + struct Block * next; + struct Block * prev; +} node_block; node_inl* parse_inlines(strbuf *input, reference** refmap); void free_inlines(node_inl* e); -- cgit v1.2.3 From 8308ed0259a9ee02c55070db656b389c7b4be71d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 19:09:23 +0200 Subject: Formatting --- src/stmd.h | 101 +++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 54 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/stmd.h b/src/stmd.h index 65063fa..be65371 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -49,58 +49,65 @@ typedef struct reference reference; // Types for blocks struct ListData { - enum { bullet, - ordered } list_type; - int marker_offset; - int padding; - int start; - enum { period, - parens } delimiter; - unsigned char bullet_char; - bool tight; + enum { + bullet, + ordered + } list_type; + int marker_offset; + int padding; + int start; + enum { + period, + parens + } delimiter; + unsigned char bullet_char; + bool tight; }; struct FencedCodeData { - int fence_length; - int fence_offset; - char fence_char; - strbuf info; + int fence_length; + int fence_offset; + char fence_char; + strbuf info; +}; + +struct node_block { + enum { + BLOCK_DOCUMENT, + BLOCK_BQUOTE, + BLOCK_LIST, + BLOCK_LIST_ITEM, + BLOCK_FENCED_CODE, + BLOCK_INDENTED_CODE, + BLOCK_HTML, + BLOCK_PARAGRAPH, + BLOCK_ATX_HEADER, + BLOCK_SETEXT_HEADER, + BLOCK_HRULE, + BLOCK_REFERENCE_DEF + } tag; + int start_line; + int start_column; + int end_line; + bool open; + bool last_line_blank; + struct node_block* children; + struct node_block* last_child; + struct node_block* parent; + struct node_block* top; + strbuf string_content; + node_inl* inline_content; + union { + struct ListData list_data; + struct FencedCodeData fenced_code_data; + int header_level; + reference** refmap; + } attributes; + struct node_block * next; + struct node_block * prev; }; -typedef struct Block { - enum { BLOCK_DOCUMENT, - BLOCK_BQUOTE, - BLOCK_LIST, - BLOCK_LIST_ITEM, - BLOCK_FENCED_CODE, - BLOCK_INDENTED_CODE, - BLOCK_HTML, - BLOCK_PARAGRAPH, - BLOCK_ATX_HEADER, - BLOCK_SETEXT_HEADER, - BLOCK_HRULE, - BLOCK_REFERENCE_DEF - } tag; - int start_line; - int start_column; - int end_line; - bool open; - bool last_line_blank; - struct Block* children; - struct Block* last_child; - struct Block* parent; - struct Block* top; - strbuf string_content; - node_inl* inline_content; - union { - struct ListData list_data; - struct FencedCodeData fenced_code_data; - int header_level; - reference** refmap; - } attributes; - struct Block * next; - struct Block * prev; -} node_block; +typedef struct node_block node_block; node_inl* parse_inlines(strbuf *input, reference** refmap); void free_inlines(node_inl* e); -- cgit v1.2.3 From add5dd1b9a9ba8c58cdc6ca0bb62d287acb56278 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 19:40:27 +0200 Subject: Remove warnings --- Makefile | 4 ++-- src/inlines.c | 17 +++++++++++++++-- src/scanners.re | 41 ++++++++++++++++++++++++----------------- 3 files changed, 41 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/Makefile b/Makefile index ed4ddd5..0d2eb8b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -CFLAGS=-g -O3 -Wall -Wextra -Wno-unused-variable -std=c99 -Isrc $(OPTFLAGS) -LDFLAGS=-g -O3 -Wall -Wno-unused-variable # -Werror +CFLAGS=-g -O3 -Wall -Wextra -std=c99 -Isrc $(OPTFLAGS) +LDFLAGS=-g -O3 -Wall -Werror SRCDIR=src DATADIR=data diff --git a/src/inlines.c b/src/inlines.c index 6bb89da..5e0f3e5 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -108,13 +108,26 @@ extern void add_reference(reference** refmap, reference* ref) } } +static unsigned char *bufdup(const unsigned char *buf) +{ + unsigned char *new = NULL; + + if (!buf) { + int len = strlen((char *)buf); + new = malloc(len + 1); + memcpy(new, buf, len + 1); + } + + return new; +} + inline static node_inl* make_link_from_reference(node_inl* label, reference *ref) { node_inl* e = (node_inl*) malloc(sizeof(node_inl)); e->tag = INL_LINK; e->content.linkable.label = label; - e->content.linkable.url = strdup(ref->url); - e->content.linkable.title = ref->title ? strdup(ref->title) : NULL; + e->content.linkable.url = bufdup(ref->url); + e->content.linkable.title = bufdup(ref->title); e->next = NULL; return e; } diff --git a/src/scanners.re b/src/scanners.re index 71103f6..28aba9d 100644 --- a/src/scanners.re +++ b/src/scanners.re @@ -1,9 +1,5 @@ #include -#define SCAN_DATA \ - const unsigned char *marker = NULL; \ - const unsigned char *start = p; \ - /*!re2c re2c:define:YYCTYPE = "unsigned char"; re2c:define:YYCURSOR = p; @@ -61,7 +57,8 @@ // Try to match URI autolink after first <, returning number of chars matched. extern int _scan_autolink_uri(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c scheme [:]([^\x00-\x20<>\\]|escaped_char)*[>] { return (p - start); } .? { return 0; } @@ -71,7 +68,8 @@ extern int _scan_autolink_uri(const unsigned char *p) // Try to match email autolink after first <, returning num of chars matched. extern int _scan_autolink_email(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+ [@] @@ -85,7 +83,8 @@ extern int _scan_autolink_email(const unsigned char *p) // Try to match an HTML tag after first <, returning num of chars matched. extern int _scan_html_tag(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c htmltag { return (p - start); } .? { return 0; } @@ -96,7 +95,8 @@ extern int _scan_html_tag(const unsigned char *p) // returning num of chars matched. extern int _scan_html_block_tag(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [<] [/] blocktagname (spacechar | [>]) { return (p - start); } [<] blocktagname (spacechar | [/>]) { return (p - start); } @@ -111,7 +111,8 @@ extern int _scan_html_block_tag(const unsigned char *p) // Newlines aren't ever allowed. extern int _scan_link_url(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [ \n]* [<] ([^<>\n\\\x00] | escaped_char | [\\])* [>] { return (p - start); } [ \n]* (reg_char+ | escaped_char | in_parens_nosp)* { return (p - start); } @@ -124,7 +125,8 @@ extern int _scan_link_url(const unsigned char *p) // level of internal nesting (quotes within quotes). extern int _scan_link_title(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c ["] (escaped_char|[^"\x00])* ["] { return (p - start); } ['] (escaped_char|[^'\x00])* ['] { return (p - start); } @@ -136,7 +138,7 @@ extern int _scan_link_title(const unsigned char *p) // Match space characters, including newlines. extern int _scan_spacechars(const unsigned char *p) { - SCAN_DATA; + const unsigned char *start = p; \ /*!re2c [ \t\n]* { return (p - start); } . { return 0; } @@ -146,7 +148,8 @@ extern int _scan_spacechars(const unsigned char *p) // Match ATX header start. extern int _scan_atx_header_start(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [#]{1,6} ([ ]+|[\n]) { return (p - start); } .? { return 0; } @@ -157,7 +160,7 @@ extern int _scan_atx_header_start(const unsigned char *p) // 2 for level-2, 0 for no match. extern int _scan_setext_header_line(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; /*!re2c [=]+ [ ]* [\n] { return 1; } [-]+ [ ]* [\n] { return 2; } @@ -170,7 +173,8 @@ extern int _scan_setext_header_line(const unsigned char *p) // spaces between the hyphens or asterisks." extern int _scan_hrule(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c ([*][ ]*){3,} [ \t]* [\n] { return (p - start); } ([_][ ]*){3,} [ \t]* [\n] { return (p - start); } @@ -182,7 +186,8 @@ extern int _scan_hrule(const unsigned char *p) // Scan an opening code fence. extern int _scan_open_code_fence(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [`]{3,} / [^`\n\x00]*[\n] { return (p - start); } [~]{3,} / [^~\n\x00]*[\n] { return (p - start); } @@ -193,7 +198,8 @@ extern int _scan_open_code_fence(const unsigned char *p) // Scan a closing code fence with length at least len. extern int _scan_close_code_fence(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c ([`]{3,} | [~]{3,}) / spacechar* [\n] { return (p - start); } .? { return 0; } @@ -204,7 +210,8 @@ extern int _scan_close_code_fence(const unsigned char *p) // Returns number of chars matched. extern int _scan_entity(const unsigned char *p) { - SCAN_DATA; + const unsigned char *marker = NULL; + const unsigned char *start = p; /*!re2c [&] ([#] ([Xx][A-Fa-f0-9]{1,8}|[0-9]{1,8}) |[A-Za-z][A-Za-z0-9]{1,31} ) [;] { return (p - start); } -- cgit v1.2.3 From 278b89d092cae8fe9cdd6346c69512886d36abbd Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 4 Sep 2014 20:04:21 +0200 Subject: Silly me --- src/inlines.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/inlines.c b/src/inlines.c index 5e0f3e5..6b17027 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -112,7 +112,7 @@ static unsigned char *bufdup(const unsigned char *buf) { unsigned char *new = NULL; - if (!buf) { + if (buf) { int len = strlen((char *)buf); new = malloc(len + 1); memcpy(new, buf, len + 1); -- cgit v1.2.3 From 61e3e606e64221eaa5cf3d83dc598d5a42818d10 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 6 Sep 2014 20:48:05 +0200 Subject: UTF8-aware detabbing and entity handling --- Makefile | 13 ++++++----- src/blocks.c | 35 ++++++------------------------ src/html/houdini.h | 2 ++ src/html/html.c | 1 - src/inlines.c | 63 ++++++++++++++++++++++-------------------------------- src/print.c | 5 ----- src/stmd.h | 3 --- src/utf8.c | 59 ++++++++++++++++++++++++++++++++++++++++++++------ 8 files changed, 95 insertions(+), 86 deletions(-) (limited to 'src') diff --git a/Makefile b/Makefile index 0d2eb8b..b5e487d 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -CFLAGS=-g -O3 -Wall -Wextra -std=c99 -Isrc $(OPTFLAGS) -LDFLAGS=-g -O3 -Wall -Werror +CFLAGS=-g -pg -O3 -Wall -Wextra -std=c99 -Isrc $(OPTFLAGS) +LDFLAGS=-g -pg -O3 -Wall -Werror SRCDIR=src DATADIR=data @@ -41,11 +41,11 @@ testjs: spec.txt benchjs: node js/bench.js ${BENCHINP} -HTML_OBJ=$(SRCDIR)/html/html.o $(SRCDIR)/html/houdini_href_e.o $(SRCDIR)/html/houdini_html_e.o +HTML_OBJ=$(SRCDIR)/html/html.o $(SRCDIR)/html/houdini_href_e.o $(SRCDIR)/html/houdini_html_e.o $(SRCDIR)/html/houdini_html_u.o STMD_OBJ=$(SRCDIR)/inlines.o $(SRCDIR)/buffer.o $(SRCDIR)/blocks.o $(SRCDIR)/scanners.c $(SRCDIR)/print.o $(SRCDIR)/utf8.o -$(PROG): $(SRCDIR)/main.c $(HTML_OBJ) $(STMD_OBJ) - $(CC) $(LDFLAGS) -o $@ $^ +$(PROG): $(SRCDIR)/html/html_unescape.h $(SRCDIR)/case_fold_switch.inc $(HTML_OBJ) $(STMD_OBJ) $(SRCDIR)/main.c + $(CC) $(LDFLAGS) -o $@ $(HTML_OBJ) $(STMD_OBJ) $(SRCDIR)/main.c $(SRCDIR)/scanners.c: $(SRCDIR)/scanners.re re2c --case-insensitive -bis $< > $@ || (rm $@ && false) @@ -53,6 +53,9 @@ $(SRCDIR)/scanners.c: $(SRCDIR)/scanners.re $(SRCDIR)/case_fold_switch.inc: $(DATADIR)/CaseFolding-3.2.0.txt perl mkcasefold.pl < $< > $@ +$(SRCDIR)/html/html_unescape.h: $(SRCDIR)/html/html_unescape.gperf + gperf -I -t -N find_entity -H hash_entity -K entity -C -l --null-strings -m5 $< > $@ + .PHONY: leakcheck clean fuzztest dingus upload dingus: diff --git a/src/blocks.c b/src/blocks.c index f671b5e..8c7d49c 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -5,6 +5,8 @@ #include #include "stmd.h" +#include "utf8.h" +#include "html/houdini.h" #include "scanners.h" #include "uthash.h" @@ -184,7 +186,7 @@ static void finalize(node_block* b, int line_number) firstlinelen = strbuf_strchr(&b->string_content, '\n', 0); strbuf_init(&b->attributes.fenced_code_data.info, 0); - strbuf_set( + houdini_unescape_html_f( &b->attributes.fenced_code_data.info, b->string_content.ptr, firstlinelen @@ -369,31 +371,6 @@ static int lists_match(struct ListData list_data, list_data.bullet_char == item_data.bullet_char); } -static void expand_tabs(strbuf *ob, const unsigned char *line, size_t size) -{ - size_t i = 0, tab = 0; - - while (i < size) { - size_t org = i; - - while (i < size && line[i] != '\t') { - i++; tab++; - } - - if (i > org) - strbuf_put(ob, line + org, i - org); - - if (i >= size) - break; - - do { - strbuf_putc(ob, ' '); tab++; - } while (tab % 4); - - i++; - } -} - static node_block *finalize_document(node_block *document, int linenum) { while (document != document->top) { @@ -415,7 +392,7 @@ extern node_block *stmd_parse_file(FILE *f) node_block *document = make_document(); while (fgets((char *)buffer, sizeof(buffer), f)) { - expand_tabs(&line, buffer, strlen((char *)buffer)); + utf8proc_detab(&line, buffer, strlen((char *)buffer)); incorporate_line(&line, linenum, &document); strbuf_clear(&line); linenum++; @@ -436,10 +413,10 @@ extern node_block *stmd_parse_document(const unsigned char *buffer, size_t len) const unsigned char *eol = memchr(buffer, '\n', end - buffer); if (!eol) { - expand_tabs(&line, buffer, end - buffer); + utf8proc_detab(&line, buffer, end - buffer); buffer = end; } else { - expand_tabs(&line, buffer, (eol - buffer) + 1); + utf8proc_detab(&line, buffer, (eol - buffer) + 1); buffer += (eol - buffer) + 1; } diff --git a/src/html/houdini.h b/src/html/houdini.h index 1e54d20..5fd690d 100644 --- a/src/html/houdini.h +++ b/src/html/houdini.h @@ -25,9 +25,11 @@ extern "C" { #define HOUDINI_ESCAPED_SIZE(x) (((x) * 12) / 10) #define HOUDINI_UNESCAPED_SIZE(x) (x) +extern size_t houdini_unescape_ent(strbuf *ob, const uint8_t *src, size_t size); extern int houdini_escape_html(strbuf *ob, const uint8_t *src, size_t size); extern int houdini_escape_html0(strbuf *ob, const uint8_t *src, size_t size, int secure); extern int houdini_unescape_html(strbuf *ob, const uint8_t *src, size_t size); +extern void houdini_unescape_html_f(strbuf *ob, const uint8_t *src, size_t size); extern int houdini_escape_xml(strbuf *ob, const uint8_t *src, size_t size); extern int houdini_escape_uri(strbuf *ob, const uint8_t *src, size_t size); extern int houdini_escape_url(strbuf *ob, const uint8_t *src, size_t size); diff --git a/src/html/html.c b/src/html/html.c index 758ec80..595dfcd 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -166,7 +166,6 @@ void inlines_to_html(strbuf *html, node_inl* ils) break; case INL_RAW_HTML: - case INL_ENTITY: strbuf_put(html, ils->content.literal.data, ils->content.literal.len); diff --git a/src/inlines.c b/src/inlines.c index 6b17027..7b27150 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -5,6 +5,8 @@ #include #include "stmd.h" +#include "html/houdini.h" +#include "utf8.h" #include "uthash.h" #include "scanners.h" @@ -176,7 +178,6 @@ inline static node_inl* make_simple(int t) #define make_str(s) make_literal(INL_STRING, s) #define make_code(s) make_literal(INL_CODE, s) #define make_raw_html(s) make_literal(INL_RAW_HTML, s) -#define make_entity(s) make_literal(INL_ENTITY, s) #define make_linebreak() make_simple(INL_LINEBREAK) #define make_softbreak() make_simple(INL_SOFTBREAK) #define make_emph(contents) make_inlines(INL_EMPH, contents) @@ -191,7 +192,6 @@ extern void free_inlines(node_inl* e) case INL_STRING: case INL_RAW_HTML: case INL_CODE: - case INL_ENTITY: chunk_free(&e->content.literal); break; case INL_LINEBREAK: @@ -540,45 +540,34 @@ static node_inl* handle_backslash(subject *subj) // Assumes the subject has an '&' character at the current position. static node_inl* handle_entity(subject* subj) { - int match; - node_inl *result; - match = scan_entity(&subj->input, subj->pos); - if (match) { - result = make_entity(chunk_dup(&subj->input, subj->pos, match)); - subj->pos += match; - } else { - advance(subj); - result = make_str(chunk_literal("&")); - } - return result; + strbuf ent = GH_BUF_INIT; + size_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(chunk_literal("&")); + + subj->pos += len; + return make_str(chunk_buf_detach(&ent)); } // Like make_str, but parses entities. // Returns an inline sequence consisting of str and entity elements. static node_inl *make_str_with_entities(chunk *content) { - node_inl *result = NULL; - node_inl *new; - int searchpos; - char c; - subject subj; - - subject_from_chunk(&subj, content, NULL); + strbuf unescaped = GH_BUF_INIT; - while ((c = peek_char(&subj))) { - switch (c) { - case '&': - new = handle_entity(&subj); - break; - default: - searchpos = chunk_strchr(&subj.input, '&', subj.pos); - new = make_str(chunk_dup(&subj.input, subj.pos, searchpos - subj.pos)); - subj.pos = searchpos; - } - result = append_inlines(result, new); + if (houdini_unescape_html(&unescaped, content->data, (size_t)content->len)) { + return make_str(chunk_buf_detach(&unescaped)); + } else { + return make_str(*content); } - - return result; } // Destructively unescape a string: remove backslashes before punctuation chars. @@ -611,9 +600,9 @@ static unsigned char *clean_url(chunk *url, int is_email) strbuf_puts(&buf, "mailto:"); if (url->data[0] == '<' && url->data[url->len - 1] == '>') { - strbuf_put(&buf, url->data + 1, url->len - 2); + houdini_unescape_html_f(&buf, url->data + 1, url->len - 2); } else { - strbuf_put(&buf, url->data, url->len); + houdini_unescape_html_f(&buf, url->data, url->len); } unescape_buffer(&buf); @@ -636,9 +625,9 @@ static unsigned char *clean_title(chunk *title) if ((first == '\'' && last == '\'') || (first == '(' && last == ')') || (first == '"' && last == '"')) { - strbuf_set(&buf, title->data + 1, title->len - 2); + houdini_unescape_html_f(&buf, title->data + 1, title->len - 2); } else { - strbuf_set(&buf, title->data, title->len); + houdini_unescape_html_f(&buf, title->data, title->len); } unescape_buffer(&buf); diff --git a/src/print.c b/src/print.c index 0ff86fa..9240dac 100644 --- a/src/print.c +++ b/src/print.c @@ -145,11 +145,6 @@ extern void print_inlines(node_inl* ils, int indent) print_str(ils->content.literal.data, ils->content.literal.len); putchar('\n'); break; - case INL_ENTITY: - printf("entity "); - print_str(ils->content.literal.data, ils->content.literal.len); - putchar('\n'); - break; case INL_LINK: case INL_IMAGE: printf("%s url=", ils->tag == INL_LINK ? "link" : "image"); diff --git a/src/stmd.h b/src/stmd.h index be65371..c80eeda 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -17,7 +17,6 @@ struct node_inl { INL_LINEBREAK, INL_CODE, INL_RAW_HTML, - INL_ENTITY, INL_EMPH, INL_STRONG, INL_LINK, @@ -133,6 +132,4 @@ void print_blocks(node_block* blk, int indent); void blocks_to_html(strbuf *html, node_block *b, bool tight); void inlines_to_html(strbuf *html, node_inl *b); -void utf8proc_case_fold(strbuf *dest, const unsigned char *str, int len); - #endif diff --git a/src/utf8.c b/src/utf8.c index cebd872..12d7ba5 100644 --- a/src/utf8.c +++ b/src/utf8.c @@ -3,7 +3,7 @@ #include #include -#include "stmd.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, @@ -23,6 +23,12 @@ static const int8_t utf8proc_utf8class[256] = { 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(strbuf *buf) +{ + static const unsigned char repl[] = {239, 191, 189}; + strbuf_put(buf, repl, 3); +} + ssize_t utf8proc_charlen(const uint8_t *str, ssize_t str_len) { ssize_t length, i; @@ -46,6 +52,46 @@ ssize_t utf8proc_charlen(const uint8_t *str, ssize_t str_len) return length; } +void utf8proc_detab(strbuf *ob, const unsigned char *line, size_t size) +{ + static const unsigned char whitespace[] = " "; + + size_t i = 0, tab = 0; + + while (i < size) { + size_t org = i; + + while (i < size && line[i] != '\t' && line[i] <= 0x80) { + i++; tab++; + } + + if (i > org) + strbuf_put(ob, line + org, i - org); + + if (i >= size) + break; + + if (line[i] == '\t') { + int numspaces = 4 - (tab % 4); + strbuf_put(ob, whitespace, numspaces); + i += 1; + tab += numspaces; + } else { + ssize_t charlen = utf8proc_charlen(line + i, size - i); + + if (charlen < 0) { + encode_unknown(ob); + i++; + } else { + strbuf_put(ob, line + i, charlen); + i += charlen; + } + + tab += 1; + } + } +} + ssize_t utf8proc_iterate(const uint8_t *str, ssize_t str_len, int32_t *dst) { ssize_t length; @@ -89,9 +135,9 @@ void utf8proc_encode_char(int32_t uc, strbuf *buf) unsigned char dst[4]; int len = 0; - if (uc < 0x00) { - assert(false); - } else if (uc < 0x80) { + assert(uc >= 0); + + if (uc < 0x80) { dst[0] = uc; len = 1; } else if (uc < 0x800) { @@ -116,7 +162,8 @@ void utf8proc_encode_char(int32_t uc, strbuf *buf) dst[3] = 0x80 + (uc & 0x3F); len = 4; } else { - assert(false); + encode_unknown(buf); + return; } strbuf_put(buf, dst, len); @@ -133,7 +180,7 @@ void utf8proc_case_fold(strbuf *dest, const unsigned char *str, int len) ssize_t char_len = utf8proc_iterate(str, len, &c); if (char_len < 0) { - bufpush(0xFFFD); + encode_unknown(dest); continue; } -- cgit v1.2.3 From a5cf11dac52606141dd246f88d8c59688462e395 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 6 Sep 2014 20:48:54 +0200 Subject: Entity declarations --- src/html/houdini_html_u.c | 99 + src/html/html_unescape.gperf | 2131 +++++++++ src/html/html_unescape.h | 9746 ++++++++++++++++++++++++++++++++++++++++++ src/utf8.h | 12 + 4 files changed, 11988 insertions(+) create mode 100644 src/html/houdini_html_u.c create mode 100644 src/html/html_unescape.gperf create mode 100644 src/html/html_unescape.h create mode 100644 src/utf8.h (limited to 'src') diff --git a/src/html/houdini_html_u.c b/src/html/houdini_html_u.c new file mode 100644 index 0000000..762f980 --- /dev/null +++ b/src/html/houdini_html_u.c @@ -0,0 +1,99 @@ +#include +#include +#include + +#include "houdini.h" +#include "utf8.h" +#include "html_unescape.h" + +size_t +houdini_unescape_ent(strbuf *ob, const uint8_t *src, size_t size) +{ + size_t i = 0; + + if (size > 3 && src[0] == '#') { + int codepoint = 0; + + if (_isdigit(src[1])) { + for (i = 1; i < size && _isdigit(src[i]); ++i) + codepoint = (codepoint * 10) + (src[i] - '0'); + } + + else if (src[1] == 'x' || src[1] == 'X') { + for (i = 2; i < size && _isxdigit(src[i]); ++i) + codepoint = (codepoint * 16) + ((src[i] | 32) % 39 - 9); + } + + if (i < size && src[i] == ';') { + utf8proc_encode_char(codepoint, ob); + return i + 1; + } + } + + else { + if (size > MAX_WORD_LENGTH) + size = MAX_WORD_LENGTH; + + for (i = MIN_WORD_LENGTH; i < size; ++i) { + if (src[i] == ' ') + break; + + if (src[i] == ';') { + const struct html_ent *entity = find_entity((char *)src, i); + + if (entity != NULL) { + strbuf_put(ob, entity->utf8, entity->utf8_len); + return i + 1; + } + + break; + } + } + } + + return 0; +} + +int +houdini_unescape_html(strbuf *ob, const uint8_t *src, size_t size) +{ + size_t i = 0, org, ent; + + while (i < size) { + org = i; + while (i < size && src[i] != '&') + i++; + + if (likely(i > org)) { + if (unlikely(org == 0)) { + if (i >= size) + return 0; + + strbuf_grow(ob, HOUDINI_UNESCAPED_SIZE(size)); + } + + strbuf_put(ob, src + org, i - org); + } + + /* escaping */ + if (i >= size) + break; + + i++; + + ent = houdini_unescape_ent(ob, src + i, size - i); + i += ent; + + /* not really an entity */ + if (ent == 0) + strbuf_putc(ob, '&'); + } + + return 1; +} + +void houdini_unescape_html_f(strbuf *ob, const uint8_t *src, size_t size) +{ + if (!houdini_unescape_html(ob, src, size)) + strbuf_put(ob, src, size); +} diff --git a/src/html/html_unescape.gperf b/src/html/html_unescape.gperf new file mode 100644 index 0000000..4d46f67 --- /dev/null +++ b/src/html/html_unescape.gperf @@ -0,0 +1,2131 @@ +struct html_ent { + const char *entity; + unsigned int utf8_len; + unsigned char utf8[4]; +}; +%% +"Aacute", 2, {195, 129} +"aacute", 2, {195, 161} +"Abreve", 2, {196, 130} +"abreve", 2, {196, 131} +"ac", 3, {226, 136, 190} +"acd", 3, {226, 136, 191} +"acE", 3, {226, 136, 190} +"Acirc", 2, {195, 130} +"acirc", 2, {195, 162} +"acute", 2, {194, 180} +"Acy", 2, {208, 144} +"acy", 2, {208, 176} +"AElig", 2, {195, 134} +"aelig", 2, {195, 166} +"af", 3, {226, 129, 161} +"Afr", 4, {240, 157, 148, 132} +"afr", 4, {240, 157, 148, 158} +"Agrave", 2, {195, 128} +"agrave", 2, {195, 160} +"alefsym", 3, {226, 132, 181} +"aleph", 3, {226, 132, 181} +"Alpha", 2, {206, 145} +"alpha", 2, {206, 177} +"Amacr", 2, {196, 128} +"amacr", 2, {196, 129} +"amalg", 3, {226, 168, 191} +"amp", 1, {38} +"AMP", 1, {38} +"andand", 3, {226, 169, 149} +"And", 3, {226, 169, 147} +"and", 3, {226, 136, 167} +"andd", 3, {226, 169, 156} +"andslope", 3, {226, 169, 152} +"andv", 3, {226, 169, 154} +"ang", 3, {226, 136, 160} +"ange", 3, {226, 166, 164} +"angle", 3, {226, 136, 160} +"angmsdaa", 3, {226, 166, 168} +"angmsdab", 3, {226, 166, 169} +"angmsdac", 3, {226, 166, 170} +"angmsdad", 3, {226, 166, 171} +"angmsdae", 3, {226, 166, 172} +"angmsdaf", 3, {226, 166, 173} +"angmsdag", 3, {226, 166, 174} +"angmsdah", 3, {226, 166, 175} +"angmsd", 3, {226, 136, 161} +"angrt", 3, {226, 136, 159} +"angrtvb", 3, {226, 138, 190} +"angrtvbd", 3, {226, 166, 157} +"angsph", 3, {226, 136, 162} +"angst", 2, {195, 133} +"angzarr", 3, {226, 141, 188} +"Aogon", 2, {196, 132} +"aogon", 2, {196, 133} +"Aopf", 4, {240, 157, 148, 184} +"aopf", 4, {240, 157, 149, 146} +"apacir", 3, {226, 169, 175} +"ap", 3, {226, 137, 136} +"apE", 3, {226, 169, 176} +"ape", 3, {226, 137, 138} +"apid", 3, {226, 137, 139} +"apos", 1, {39} +"ApplyFunction", 3, {226, 129, 161} +"approx", 3, {226, 137, 136} +"approxeq", 3, {226, 137, 138} +"Aring", 2, {195, 133} +"aring", 2, {195, 165} +"Ascr", 4, {240, 157, 146, 156} +"ascr", 4, {240, 157, 146, 182} +"Assign", 3, {226, 137, 148} +"ast", 1, {42} +"asymp", 3, {226, 137, 136} +"asympeq", 3, {226, 137, 141} +"Atilde", 2, {195, 131} +"atilde", 2, {195, 163} +"Auml", 2, {195, 132} +"auml", 2, {195, 164} +"awconint", 3, {226, 136, 179} +"awint", 3, {226, 168, 145} +"backcong", 3, {226, 137, 140} +"backepsilon", 2, {207, 182} +"backprime", 3, {226, 128, 181} +"backsim", 3, {226, 136, 189} +"backsimeq", 3, {226, 139, 141} +"Backslash", 3, {226, 136, 150} +"Barv", 3, {226, 171, 167} +"barvee", 3, {226, 138, 189} +"barwed", 3, {226, 140, 133} +"Barwed", 3, {226, 140, 134} +"barwedge", 3, {226, 140, 133} +"bbrk", 3, {226, 142, 181} +"bbrktbrk", 3, {226, 142, 182} +"bcong", 3, {226, 137, 140} +"Bcy", 2, {208, 145} +"bcy", 2, {208, 177} +"bdquo", 3, {226, 128, 158} +"becaus", 3, {226, 136, 181} +"because", 3, {226, 136, 181} +"Because", 3, {226, 136, 181} +"bemptyv", 3, {226, 166, 176} +"bepsi", 2, {207, 182} +"bernou", 3, {226, 132, 172} +"Bernoullis", 3, {226, 132, 172} +"Beta", 2, {206, 146} +"beta", 2, {206, 178} +"beth", 3, {226, 132, 182} +"between", 3, {226, 137, 172} +"Bfr", 4, {240, 157, 148, 133} +"bfr", 4, {240, 157, 148, 159} +"bigcap", 3, {226, 139, 130} +"bigcirc", 3, {226, 151, 175} +"bigcup", 3, {226, 139, 131} +"bigodot", 3, {226, 168, 128} +"bigoplus", 3, {226, 168, 129} +"bigotimes", 3, {226, 168, 130} +"bigsqcup", 3, {226, 168, 134} +"bigstar", 3, {226, 152, 133} +"bigtriangledown", 3, {226, 150, 189} +"bigtriangleup", 3, {226, 150, 179} +"biguplus", 3, {226, 168, 132} +"bigvee", 3, {226, 139, 129} +"bigwedge", 3, {226, 139, 128} +"bkarow", 3, {226, 164, 141} +"blacklozenge", 3, {226, 167, 171} +"blacksquare", 3, {226, 150, 170} +"blacktriangle", 3, {226, 150, 180} +"blacktriangledown", 3, {226, 150, 190} +"blacktriangleleft", 3, {226, 151, 130} +"blacktriangleright", 3, {226, 150, 184} +"blank", 3, {226, 144, 163} +"blk12", 3, {226, 150, 146} +"blk14", 3, {226, 150, 145} +"blk34", 3, {226, 150, 147} +"block", 3, {226, 150, 136} +"bne", 1, {61} +"bnequiv", 3, {226, 137, 161} +"bNot", 3, {226, 171, 173} +"bnot", 3, {226, 140, 144} +"Bopf", 4, {240, 157, 148, 185} +"bopf", 4, {240, 157, 149, 147} +"bot", 3, {226, 138, 165} +"bottom", 3, {226, 138, 165} +"bowtie", 3, {226, 139, 136} +"boxbox", 3, {226, 167, 137} +"boxdl", 3, {226, 148, 144} +"boxdL", 3, {226, 149, 149} +"boxDl", 3, {226, 149, 150} +"boxDL", 3, {226, 149, 151} +"boxdr", 3, {226, 148, 140} +"boxdR", 3, {226, 149, 146} +"boxDr", 3, {226, 149, 147} +"boxDR", 3, {226, 149, 148} +"boxh", 3, {226, 148, 128} +"boxH", 3, {226, 149, 144} +"boxhd", 3, {226, 148, 172} +"boxHd", 3, {226, 149, 164} +"boxhD", 3, {226, 149, 165} +"boxHD", 3, {226, 149, 166} +"boxhu", 3, {226, 148, 180} +"boxHu", 3, {226, 149, 167} +"boxhU", 3, {226, 149, 168} +"boxHU", 3, {226, 149, 169} +"boxminus", 3, {226, 138, 159} +"boxplus", 3, {226, 138, 158} +"boxtimes", 3, {226, 138, 160} +"boxul", 3, {226, 148, 152} +"boxuL", 3, {226, 149, 155} +"boxUl", 3, {226, 149, 156} +"boxUL", 3, {226, 149, 157} +"boxur", 3, {226, 148, 148} +"boxuR", 3, {226, 149, 152} +"boxUr", 3, {226, 149, 153} +"boxUR", 3, {226, 149, 154} +"boxv", 3, {226, 148, 130} +"boxV", 3, {226, 149, 145} +"boxvh", 3, {226, 148, 188} +"boxvH", 3, {226, 149, 170} +"boxVh", 3, {226, 149, 171} +"boxVH", 3, {226, 149, 172} +"boxvl", 3, {226, 148, 164} +"boxvL", 3, {226, 149, 161} +"boxVl", 3, {226, 149, 162} +"boxVL", 3, {226, 149, 163} +"boxvr", 3, {226, 148, 156} +"boxvR", 3, {226, 149, 158} +"boxVr", 3, {226, 149, 159} +"boxVR", 3, {226, 149, 160} +"bprime", 3, {226, 128, 181} +"breve", 2, {203, 152} +"Breve", 2, {203, 152} +"brvbar", 2, {194, 166} +"bscr", 4, {240, 157, 146, 183} +"Bscr", 3, {226, 132, 172} +"bsemi", 3, {226, 129, 143} +"bsim", 3, {226, 136, 189} +"bsime", 3, {226, 139, 141} +"bsolb", 3, {226, 167, 133} +"bsol", 1, {92} +"bsolhsub", 3, {226, 159, 136} +"bull", 3, {226, 128, 162} +"bullet", 3, {226, 128, 162} +"bump", 3, {226, 137, 142} +"bumpE", 3, {226, 170, 174} +"bumpe", 3, {226, 137, 143} +"Bumpeq", 3, {226, 137, 142} +"bumpeq", 3, {226, 137, 143} +"Cacute", 2, {196, 134} +"cacute", 2, {196, 135} +"capand", 3, {226, 169, 132} +"capbrcup", 3, {226, 169, 137} +"capcap", 3, {226, 169, 139} +"cap", 3, {226, 136, 169} +"Cap", 3, {226, 139, 146} +"capcup", 3, {226, 169, 135} +"capdot", 3, {226, 169, 128} +"CapitalDifferentialD", 3, {226, 133, 133} +"caps", 3, {226, 136, 169} +"caret", 3, {226, 129, 129} +"caron", 2, {203, 135} +"Cayleys", 3, {226, 132, 173} +"ccaps", 3, {226, 169, 141} +"Ccaron", 2, {196, 140} +"ccaron", 2, {196, 141} +"Ccedil", 2, {195, 135} +"ccedil", 2, {195, 167} +"Ccirc", 2, {196, 136} +"ccirc", 2, {196, 137} +"Cconint", 3, {226, 136, 176} +"ccups", 3, {226, 169, 140} +"ccupssm", 3, {226, 169, 144} +"Cdot", 2, {196, 138} +"cdot", 2, {196, 139} +"cedil", 2, {194, 184} +"Cedilla", 2, {194, 184} +"cemptyv", 3, {226, 166, 178} +"cent", 2, {194, 162} +"centerdot", 2, {194, 183} +"CenterDot", 2, {194, 183} +"cfr", 4, {240, 157, 148, 160} +"Cfr", 3, {226, 132, 173} +"CHcy", 2, {208, 167} +"chcy", 2, {209, 135} +"check", 3, {226, 156, 147} +"checkmark", 3, {226, 156, 147} +"Chi", 2, {206, 167} +"chi", 2, {207, 135} +"circ", 2, {203, 134} +"circeq", 3, {226, 137, 151} +"circlearrowleft", 3, {226, 134, 186} +"circlearrowright", 3, {226, 134, 187} +"circledast", 3, {226, 138, 155} +"circledcirc", 3, {226, 138, 154} +"circleddash", 3, {226, 138, 157} +"CircleDot", 3, {226, 138, 153} +"circledR", 2, {194, 174} +"circledS", 3, {226, 147, 136} +"CircleMinus", 3, {226, 138, 150} +"CirclePlus", 3, {226, 138, 149} +"CircleTimes", 3, {226, 138, 151} +"cir", 3, {226, 151, 139} +"cirE", 3, {226, 167, 131} +"cire", 3, {226, 137, 151} +"cirfnint", 3, {226, 168, 144} +"cirmid", 3, {226, 171, 175} +"cirscir", 3, {226, 167, 130} +"ClockwiseContourIntegral", 3, {226, 136, 178} +"CloseCurlyDoubleQuote", 3, {226, 128, 157} +"CloseCurlyQuote", 3, {226, 128, 153} +"clubs", 3, {226, 153, 163} +"clubsuit", 3, {226, 153, 163} +"colon", 1, {58} +"Colon", 3, {226, 136, 183} +"Colone", 3, {226, 169, 180} +"colone", 3, {226, 137, 148} +"coloneq", 3, {226, 137, 148} +"comma", 1, {44} +"commat", 1, {64} +"comp", 3, {226, 136, 129} +"compfn", 3, {226, 136, 152} +"complement", 3, {226, 136, 129} +"complexes", 3, {226, 132, 130} +"cong", 3, {226, 137, 133} +"congdot", 3, {226, 169, 173} +"Congruent", 3, {226, 137, 161} +"conint", 3, {226, 136, 174} +"Conint", 3, {226, 136, 175} +"ContourIntegral", 3, {226, 136, 174} +"copf", 4, {240, 157, 149, 148} +"Copf", 3, {226, 132, 130} +"coprod", 3, {226, 136, 144} +"Coproduct", 3, {226, 136, 144} +"copy", 2, {194, 169} +"COPY", 2, {194, 169} +"copysr", 3, {226, 132, 151} +"CounterClockwiseContourIntegral", 3, {226, 136, 179} +"crarr", 3, {226, 134, 181} +"cross", 3, {226, 156, 151} +"Cross", 3, {226, 168, 175} +"Cscr", 4, {240, 157, 146, 158} +"cscr", 4, {240, 157, 146, 184} +"csub", 3, {226, 171, 143} +"csube", 3, {226, 171, 145} +"csup", 3, {226, 171, 144} +"csupe", 3, {226, 171, 146} +"ctdot", 3, {226, 139, 175} +"cudarrl", 3, {226, 164, 184} +"cudarrr", 3, {226, 164, 181} +"cuepr", 3, {226, 139, 158} +"cuesc", 3, {226, 139, 159} +"cularr", 3, {226, 134, 182} +"cularrp", 3, {226, 164, 189} +"cupbrcap", 3, {226, 169, 136} +"cupcap", 3, {226, 169, 134} +"CupCap", 3, {226, 137, 141} +"cup", 3, {226, 136, 170} +"Cup", 3, {226, 139, 147} +"cupcup", 3, {226, 169, 138} +"cupdot", 3, {226, 138, 141} +"cupor", 3, {226, 169, 133} +"cups", 3, {226, 136, 170} +"curarr", 3, {226, 134, 183} +"curarrm", 3, {226, 164, 188} +"curlyeqprec", 3, {226, 139, 158} +"curlyeqsucc", 3, {226, 139, 159} +"curlyvee", 3, {226, 139, 142} +"curlywedge", 3, {226, 139, 143} +"curren", 2, {194, 164} +"curvearrowleft", 3, {226, 134, 182} +"curvearrowright", 3, {226, 134, 183} +"cuvee", 3, {226, 139, 142} +"cuwed", 3, {226, 139, 143} +"cwconint", 3, {226, 136, 178} +"cwint", 3, {226, 136, 177} +"cylcty", 3, {226, 140, 173} +"dagger", 3, {226, 128, 160} +"Dagger", 3, {226, 128, 161} +"daleth", 3, {226, 132, 184} +"darr", 3, {226, 134, 147} +"Darr", 3, {226, 134, 161} +"dArr", 3, {226, 135, 147} +"dash", 3, {226, 128, 144} +"Dashv", 3, {226, 171, 164} +"dashv", 3, {226, 138, 163} +"dbkarow", 3, {226, 164, 143} +"dblac", 2, {203, 157} +"Dcaron", 2, {196, 142} +"dcaron", 2, {196, 143} +"Dcy", 2, {208, 148} +"dcy", 2, {208, 180} +"ddagger", 3, {226, 128, 161} +"ddarr", 3, {226, 135, 138} +"DD", 3, {226, 133, 133} +"dd", 3, {226, 133, 134} +"DDotrahd", 3, {226, 164, 145} +"ddotseq", 3, {226, 169, 183} +"deg", 2, {194, 176} +"Del", 3, {226, 136, 135} +"Delta", 2, {206, 148} +"delta", 2, {206, 180} +"demptyv", 3, {226, 166, 177} +"dfisht", 3, {226, 165, 191} +"Dfr", 4, {240, 157, 148, 135} +"dfr", 4, {240, 157, 148, 161} +"dHar", 3, {226, 165, 165} +"dharl", 3, {226, 135, 131} +"dharr", 3, {226, 135, 130} +"DiacriticalAcute", 2, {194, 180} +"DiacriticalDot", 2, {203, 153} +"DiacriticalDoubleAcute", 2, {203, 157} +"DiacriticalGrave", 1, {96} +"DiacriticalTilde", 2, {203, 156} +"diam", 3, {226, 139, 132} +"diamond", 3, {226, 139, 132} +"Diamond", 3, {226, 139, 132} +"diamondsuit", 3, {226, 153, 166} +"diams", 3, {226, 153, 166} +"die", 2, {194, 168} +"DifferentialD", 3, {226, 133, 134} +"digamma", 2, {207, 157} +"disin", 3, {226, 139, 178} +"div", 2, {195, 183} +"divide", 2, {195, 183} +"divideontimes", 3, {226, 139, 135} +"divonx", 3, {226, 139, 135} +"DJcy", 2, {208, 130} +"djcy", 2, {209, 146} +"dlcorn", 3, {226, 140, 158} +"dlcrop", 3, {226, 140, 141} +"dollar", 1, {36} +"Dopf", 4, {240, 157, 148, 187} +"dopf", 4, {240, 157, 149, 149} +"Dot", 2, {194, 168} +"dot", 2, {203, 153} +"DotDot", 3, {226, 131, 156} +"doteq", 3, {226, 137, 144} +"doteqdot", 3, {226, 137, 145} +"DotEqual", 3, {226, 137, 144} +"dotminus", 3, {226, 136, 184} +"dotplus", 3, {226, 136, 148} +"dotsquare", 3, {226, 138, 161} +"doublebarwedge", 3, {226, 140, 134} +"DoubleContourIntegral", 3, {226, 136, 175} +"DoubleDot", 2, {194, 168} +"DoubleDownArrow", 3, {226, 135, 147} +"DoubleLeftArrow", 3, {226, 135, 144} +"DoubleLeftRightArrow", 3, {226, 135, 148} +"DoubleLeftTee", 3, {226, 171, 164} +"DoubleLongLeftArrow", 3, {226, 159, 184} +"DoubleLongLeftRightArrow", 3, {226, 159, 186} +"DoubleLongRightArrow", 3, {226, 159, 185} +"DoubleRightArrow", 3, {226, 135, 146} +"DoubleRightTee", 3, {226, 138, 168} +"DoubleUpArrow", 3, {226, 135, 145} +"DoubleUpDownArrow", 3, {226, 135, 149} +"DoubleVerticalBar", 3, {226, 136, 165} +"DownArrowBar", 3, {226, 164, 147} +"downarrow", 3, {226, 134, 147} +"DownArrow", 3, {226, 134, 147} +"Downarrow", 3, {226, 135, 147} +"DownArrowUpArrow", 3, {226, 135, 181} +"DownBreve", 2, {204, 145} +"downdownarrows", 3, {226, 135, 138} +"downharpoonleft", 3, {226, 135, 131} +"downharpoonright", 3, {226, 135, 130} +"DownLeftRightVector", 3, {226, 165, 144} +"DownLeftTeeVector", 3, {226, 165, 158} +"DownLeftVectorBar", 3, {226, 165, 150} +"DownLeftVector", 3, {226, 134, 189} +"DownRightTeeVector", 3, {226, 165, 159} +"DownRightVectorBar", 3, {226, 165, 151} +"DownRightVector", 3, {226, 135, 129} +"DownTeeArrow", 3, {226, 134, 167} +"DownTee", 3, {226, 138, 164} +"drbkarow", 3, {226, 164, 144} +"drcorn", 3, {226, 140, 159} +"drcrop", 3, {226, 140, 140} +"Dscr", 4, {240, 157, 146, 159} +"dscr", 4, {240, 157, 146, 185} +"DScy", 2, {208, 133} +"dscy", 2, {209, 149} +"dsol", 3, {226, 167, 182} +"Dstrok", 2, {196, 144} +"dstrok", 2, {196, 145} +"dtdot", 3, {226, 139, 177} +"dtri", 3, {226, 150, 191} +"dtrif", 3, {226, 150, 190} +"duarr", 3, {226, 135, 181} +"duhar", 3, {226, 165, 175} +"dwangle", 3, {226, 166, 166} +"DZcy", 2, {208, 143} +"dzcy", 2, {209, 159} +"dzigrarr", 3, {226, 159, 191} +"Eacute", 2, {195, 137} +"eacute", 2, {195, 169} +"easter", 3, {226, 169, 174} +"Ecaron", 2, {196, 154} +"ecaron", 2, {196, 155} +"Ecirc", 2, {195, 138} +"ecirc", 2, {195, 170} +"ecir", 3, {226, 137, 150} +"ecolon", 3, {226, 137, 149} +"Ecy", 2, {208, 173} +"ecy", 2, {209, 141} +"eDDot", 3, {226, 169, 183} +"Edot", 2, {196, 150} +"edot", 2, {196, 151} +"eDot", 3, {226, 137, 145} +"ee", 3, {226, 133, 135} +"efDot", 3, {226, 137, 146} +"Efr", 4, {240, 157, 148, 136} +"efr", 4, {240, 157, 148, 162} +"eg", 3, {226, 170, 154} +"Egrave", 2, {195, 136} +"egrave", 2, {195, 168} +"egs", 3, {226, 170, 150} +"egsdot", 3, {226, 170, 152} +"el", 3, {226, 170, 153} +"Element", 3, {226, 136, 136} +"elinters", 3, {226, 143, 167} +"ell", 3, {226, 132, 147} +"els", 3, {226, 170, 149} +"elsdot", 3, {226, 170, 151} +"Emacr", 2, {196, 146} +"emacr", 2, {196, 147} +"empty", 3, {226, 136, 133} +"emptyset", 3, {226, 136, 133} +"EmptySmallSquare", 3, {226, 151, 187} +"emptyv", 3, {226, 136, 133} +"EmptyVerySmallSquare", 3, {226, 150, 171} +"emsp13", 3, {226, 128, 132} +"emsp14", 3, {226, 128, 133} +"emsp", 3, {226, 128, 131} +"ENG", 2, {197, 138} +"eng", 2, {197, 139} +"ensp", 3, {226, 128, 130} +"Eogon", 2, {196, 152} +"eogon", 2, {196, 153} +"Eopf", 4, {240, 157, 148, 188} +"eopf", 4, {240, 157, 149, 150} +"epar", 3, {226, 139, 149} +"eparsl", 3, {226, 167, 163} +"eplus", 3, {226, 169, 177} +"epsi", 2, {206, 181} +"Epsilon", 2, {206, 149} +"epsilon", 2, {206, 181} +"epsiv", 2, {207, 181} +"eqcirc", 3, {226, 137, 150} +"eqcolon", 3, {226, 137, 149} +"eqsim", 3, {226, 137, 130} +"eqslantgtr", 3, {226, 170, 150} +"eqslantless", 3, {226, 170, 149} +"Equal", 3, {226, 169, 181} +"equals", 1, {61} +"EqualTilde", 3, {226, 137, 130} +"equest", 3, {226, 137, 159} +"Equilibrium", 3, {226, 135, 140} +"equiv", 3, {226, 137, 161} +"equivDD", 3, {226, 169, 184} +"eqvparsl", 3, {226, 167, 165} +"erarr", 3, {226, 165, 177} +"erDot", 3, {226, 137, 147} +"escr", 3, {226, 132, 175} +"Escr", 3, {226, 132, 176} +"esdot", 3, {226, 137, 144} +"Esim", 3, {226, 169, 179} +"esim", 3, {226, 137, 130} +"Eta", 2, {206, 151} +"eta", 2, {206, 183} +"ETH", 2, {195, 144} +"eth", 2, {195, 176} +"Euml", 2, {195, 139} +"euml", 2, {195, 171} +"euro", 3, {226, 130, 172} +"excl", 1, {33} +"exist", 3, {226, 136, 131} +"Exists", 3, {226, 136, 131} +"expectation", 3, {226, 132, 176} +"exponentiale", 3, {226, 133, 135} +"ExponentialE", 3, {226, 133, 135} +"fallingdotseq", 3, {226, 137, 146} +"Fcy", 2, {208, 164} +"fcy", 2, {209, 132} +"female", 3, {226, 153, 128} +"ffilig", 3, {239, 172, 131} +"fflig", 3, {239, 172, 128} +"ffllig", 3, {239, 172, 132} +"Ffr", 4, {240, 157, 148, 137} +"ffr", 4, {240, 157, 148, 163} +"filig", 3, {239, 172, 129} +"FilledSmallSquare", 3, {226, 151, 188} +"FilledVerySmallSquare", 3, {226, 150, 170} +"fjlig", 1, {102} +"flat", 3, {226, 153, 173} +"fllig", 3, {239, 172, 130} +"fltns", 3, {226, 150, 177} +"fnof", 2, {198, 146} +"Fopf", 4, {240, 157, 148, 189} +"fopf", 4, {240, 157, 149, 151} +"forall", 3, {226, 136, 128} +"ForAll", 3, {226, 136, 128} +"fork", 3, {226, 139, 148} +"forkv", 3, {226, 171, 153} +"Fouriertrf", 3, {226, 132, 177} +"fpartint", 3, {226, 168, 141} +"frac12", 2, {194, 189} +"frac13", 3, {226, 133, 147} +"frac14", 2, {194, 188} +"frac15", 3, {226, 133, 149} +"frac16", 3, {226, 133, 153} +"frac18", 3, {226, 133, 155} +"frac23", 3, {226, 133, 148} +"frac25", 3, {226, 133, 150} +"frac34", 2, {194, 190} +"frac35", 3, {226, 133, 151} +"frac38", 3, {226, 133, 156} +"frac45", 3, {226, 133, 152} +"frac56", 3, {226, 133, 154} +"frac58", 3, {226, 133, 157} +"frac78", 3, {226, 133, 158} +"frasl", 3, {226, 129, 132} +"frown", 3, {226, 140, 162} +"fscr", 4, {240, 157, 146, 187} +"Fscr", 3, {226, 132, 177} +"gacute", 2, {199, 181} +"Gamma", 2, {206, 147} +"gamma", 2, {206, 179} +"Gammad", 2, {207, 156} +"gammad", 2, {207, 157} +"gap", 3, {226, 170, 134} +"Gbreve", 2, {196, 158} +"gbreve", 2, {196, 159} +"Gcedil", 2, {196, 162} +"Gcirc", 2, {196, 156} +"gcirc", 2, {196, 157} +"Gcy", 2, {208, 147} +"gcy", 2, {208, 179} +"Gdot", 2, {196, 160} +"gdot", 2, {196, 161} +"ge", 3, {226, 137, 165} +"gE", 3, {226, 137, 167} +"gEl", 3, {226, 170, 140} +"gel", 3, {226, 139, 155} +"geq", 3, {226, 137, 165} +"geqq", 3, {226, 137, 167} +"geqslant", 3, {226, 169, 190} +"gescc", 3, {226, 170, 169} +"ges", 3, {226, 169, 190} +"gesdot", 3, {226, 170, 128} +"gesdoto", 3, {226, 170, 130} +"gesdotol", 3, {226, 170, 132} +"gesl", 3, {226, 139, 155} +"gesles", 3, {226, 170, 148} +"Gfr", 4, {240, 157, 148, 138} +"gfr", 4, {240, 157, 148, 164} +"gg", 3, {226, 137, 171} +"Gg", 3, {226, 139, 153} +"ggg", 3, {226, 139, 153} +"gimel", 3, {226, 132, 183} +"GJcy", 2, {208, 131} +"gjcy", 2, {209, 147} +"gla", 3, {226, 170, 165} +"gl", 3, {226, 137, 183} +"glE", 3, {226, 170, 146} +"glj", 3, {226, 170, 164} +"gnap", 3, {226, 170, 138} +"gnapprox", 3, {226, 170, 138} +"gne", 3, {226, 170, 136} +"gnE", 3, {226, 137, 169} +"gneq", 3, {226, 170, 136} +"gneqq", 3, {226, 137, 169} +"gnsim", 3, {226, 139, 167} +"Gopf", 4, {240, 157, 148, 190} +"gopf", 4, {240, 157, 149, 152} +"grave", 1, {96} +"GreaterEqual", 3, {226, 137, 165} +"GreaterEqualLess", 3, {226, 139, 155} +"GreaterFullEqual", 3, {226, 137, 167} +"GreaterGreater", 3, {226, 170, 162} +"GreaterLess", 3, {226, 137, 183} +"GreaterSlantEqual", 3, {226, 169, 190} +"GreaterTilde", 3, {226, 137, 179} +"Gscr", 4, {240, 157, 146, 162} +"gscr", 3, {226, 132, 138} +"gsim", 3, {226, 137, 179} +"gsime", 3, {226, 170, 142} +"gsiml", 3, {226, 170, 144} +"gtcc", 3, {226, 170, 167} +"gtcir", 3, {226, 169, 186} +"gt", 1, {62} +"GT", 1, {62} +"Gt", 3, {226, 137, 171} +"gtdot", 3, {226, 139, 151} +"gtlPar", 3, {226, 166, 149} +"gtquest", 3, {226, 169, 188} +"gtrapprox", 3, {226, 170, 134} +"gtrarr", 3, {226, 165, 184} +"gtrdot", 3, {226, 139, 151} +"gtreqless", 3, {226, 139, 155} +"gtreqqless", 3, {226, 170, 140} +"gtrless", 3, {226, 137, 183} +"gtrsim", 3, {226, 137, 179} +"gvertneqq", 3, {226, 137, 169} +"gvnE", 3, {226, 137, 169} +"Hacek", 2, {203, 135} +"hairsp", 3, {226, 128, 138} +"half", 2, {194, 189} +"hamilt", 3, {226, 132, 139} +"HARDcy", 2, {208, 170} +"hardcy", 2, {209, 138} +"harrcir", 3, {226, 165, 136} +"harr", 3, {226, 134, 148} +"hArr", 3, {226, 135, 148} +"harrw", 3, {226, 134, 173} +"Hat", 1, {94} +"hbar", 3, {226, 132, 143} +"Hcirc", 2, {196, 164} +"hcirc", 2, {196, 165} +"hearts", 3, {226, 153, 165} +"heartsuit", 3, {226, 153, 165} +"hellip", 3, {226, 128, 166} +"hercon", 3, {226, 138, 185} +"hfr", 4, {240, 157, 148, 165} +"Hfr", 3, {226, 132, 140} +"HilbertSpace", 3, {226, 132, 139} +"hksearow", 3, {226, 164, 165} +"hkswarow", 3, {226, 164, 166} +"hoarr", 3, {226, 135, 191} +"homtht", 3, {226, 136, 187} +"hookleftarrow", 3, {226, 134, 169} +"hookrightarrow", 3, {226, 134, 170} +"hopf", 4, {240, 157, 149, 153} +"Hopf", 3, {226, 132, 141} +"horbar", 3, {226, 128, 149} +"HorizontalLine", 3, {226, 148, 128} +"hscr", 4, {240, 157, 146, 189} +"Hscr", 3, {226, 132, 139} +"hslash", 3, {226, 132, 143} +"Hstrok", 2, {196, 166} +"hstrok", 2, {196, 167} +"HumpDownHump", 3, {226, 137, 142} +"HumpEqual", 3, {226, 137, 143} +"hybull", 3, {226, 129, 131} +"hyphen", 3, {226, 128, 144} +"Iacute", 2, {195, 141} +"iacute", 2, {195, 173} +"ic", 3, {226, 129, 163} +"Icirc", 2, {195, 142} +"icirc", 2, {195, 174} +"Icy", 2, {208, 152} +"icy", 2, {208, 184} +"Idot", 2, {196, 176} +"IEcy", 2, {208, 149} +"iecy", 2, {208, 181} +"iexcl", 2, {194, 161} +"iff", 3, {226, 135, 148} +"ifr", 4, {240, 157, 148, 166} +"Ifr", 3, {226, 132, 145} +"Igrave", 2, {195, 140} +"igrave", 2, {195, 172} +"ii", 3, {226, 133, 136} +"iiiint", 3, {226, 168, 140} +"iiint", 3, {226, 136, 173} +"iinfin", 3, {226, 167, 156} +"iiota", 3, {226, 132, 169} +"IJlig", 2, {196, 178} +"ijlig", 2, {196, 179} +"Imacr", 2, {196, 170} +"imacr", 2, {196, 171} +"image", 3, {226, 132, 145} +"ImaginaryI", 3, {226, 133, 136} +"imagline", 3, {226, 132, 144} +"imagpart", 3, {226, 132, 145} +"imath", 2, {196, 177} +"Im", 3, {226, 132, 145} +"imof", 3, {226, 138, 183} +"imped", 2, {198, 181} +"Implies", 3, {226, 135, 146} +"incare", 3, {226, 132, 133} +"in", 3, {226, 136, 136} +"infin", 3, {226, 136, 158} +"infintie", 3, {226, 167, 157} +"inodot", 2, {196, 177} +"intcal", 3, {226, 138, 186} +"int", 3, {226, 136, 171} +"Int", 3, {226, 136, 172} +"integers", 3, {226, 132, 164} +"Integral", 3, {226, 136, 171} +"intercal", 3, {226, 138, 186} +"Intersection", 3, {226, 139, 130} +"intlarhk", 3, {226, 168, 151} +"intprod", 3, {226, 168, 188} +"InvisibleComma", 3, {226, 129, 163} +"InvisibleTimes", 3, {226, 129, 162} +"IOcy", 2, {208, 129} +"iocy", 2, {209, 145} +"Iogon", 2, {196, 174} +"iogon", 2, {196, 175} +"Iopf", 4, {240, 157, 149, 128} +"iopf", 4, {240, 157, 149, 154} +"Iota", 2, {206, 153} +"iota", 2, {206, 185} +"iprod", 3, {226, 168, 188} +"iquest", 2, {194, 191} +"iscr", 4, {240, 157, 146, 190} +"Iscr", 3, {226, 132, 144} +"isin", 3, {226, 136, 136} +"isindot", 3, {226, 139, 181} +"isinE", 3, {226, 139, 185} +"isins", 3, {226, 139, 180} +"isinsv", 3, {226, 139, 179} +"isinv", 3, {226, 136, 136} +"it", 3, {226, 129, 162} +"Itilde", 2, {196, 168} +"itilde", 2, {196, 169} +"Iukcy", 2, {208, 134} +"iukcy", 2, {209, 150} +"Iuml", 2, {195, 143} +"iuml", 2, {195, 175} +"Jcirc", 2, {196, 180} +"jcirc", 2, {196, 181} +"Jcy", 2, {208, 153} +"jcy", 2, {208, 185} +"Jfr", 4, {240, 157, 148, 141} +"jfr", 4, {240, 157, 148, 167} +"jmath", 2, {200, 183} +"Jopf", 4, {240, 157, 149, 129} +"jopf", 4, {240, 157, 149, 155} +"Jscr", 4, {240, 157, 146, 165} +"jscr", 4, {240, 157, 146, 191} +"Jsercy", 2, {208, 136} +"jsercy", 2, {209, 152} +"Jukcy", 2, {208, 132} +"jukcy", 2, {209, 148} +"Kappa", 2, {206, 154} +"kappa", 2, {206, 186} +"kappav", 2, {207, 176} +"Kcedil", 2, {196, 182} +"kcedil", 2, {196, 183} +"Kcy", 2, {208, 154} +"kcy", 2, {208, 186} +"Kfr", 4, {240, 157, 148, 142} +"kfr", 4, {240, 157, 148, 168} +"kgreen", 2, {196, 184} +"KHcy", 2, {208, 165} +"khcy", 2, {209, 133} +"KJcy", 2, {208, 140} +"kjcy", 2, {209, 156} +"Kopf", 4, {240, 157, 149, 130} +"kopf", 4, {240, 157, 149, 156} +"Kscr", 4, {240, 157, 146, 166} +"kscr", 4, {240, 157, 147, 128} +"lAarr", 3, {226, 135, 154} +"Lacute", 2, {196, 185} +"lacute", 2, {196, 186} +"laemptyv", 3, {226, 166, 180} +"lagran", 3, {226, 132, 146} +"Lambda", 2, {206, 155} +"lambda", 2, {206, 187} +"lang", 3, {226, 159, 168} +"Lang", 3, {226, 159, 170} +"langd", 3, {226, 166, 145} +"langle", 3, {226, 159, 168} +"lap", 3, {226, 170, 133} +"Laplacetrf", 3, {226, 132, 146} +"laquo", 2, {194, 171} +"larrb", 3, {226, 135, 164} +"larrbfs", 3, {226, 164, 159} +"larr", 3, {226, 134, 144} +"Larr", 3, {226, 134, 158} +"lArr", 3, {226, 135, 144} +"larrfs", 3, {226, 164, 157} +"larrhk", 3, {226, 134, 169} +"larrlp", 3, {226, 134, 171} +"larrpl", 3, {226, 164, 185} +"larrsim", 3, {226, 165, 179} +"larrtl", 3, {226, 134, 162} +"latail", 3, {226, 164, 153} +"lAtail", 3, {226, 164, 155} +"lat", 3, {226, 170, 171} +"late", 3, {226, 170, 173} +"lates", 3, {226, 170, 173} +"lbarr", 3, {226, 164, 140} +"lBarr", 3, {226, 164, 142} +"lbbrk", 3, {226, 157, 178} +"lbrace", 1, {123} +"lbrack", 1, {91} +"lbrke", 3, {226, 166, 139} +"lbrksld", 3, {226, 166, 143} +"lbrkslu", 3, {226, 166, 141} +"Lcaron", 2, {196, 189} +"lcaron", 2, {196, 190} +"Lcedil", 2, {196, 187} +"lcedil", 2, {196, 188} +"lceil", 3, {226, 140, 136} +"lcub", 1, {123} +"Lcy", 2, {208, 155} +"lcy", 2, {208, 187} +"ldca", 3, {226, 164, 182} +"ldquo", 3, {226, 128, 156} +"ldquor", 3, {226, 128, 158} +"ldrdhar", 3, {226, 165, 167} +"ldrushar", 3, {226, 165, 139} +"ldsh", 3, {226, 134, 178} +"le", 3, {226, 137, 164} +"lE", 3, {226, 137, 166} +"LeftAngleBracket", 3, {226, 159, 168} +"LeftArrowBar", 3, {226, 135, 164} +"leftarrow", 3, {226, 134, 144} +"LeftArrow", 3, {226, 134, 144} +"Leftarrow", 3, {226, 135, 144} +"LeftArrowRightArrow", 3, {226, 135, 134} +"leftarrowtail", 3, {226, 134, 162} +"LeftCeiling", 3, {226, 140, 136} +"LeftDoubleBracket", 3, {226, 159, 166} +"LeftDownTeeVector", 3, {226, 165, 161} +"LeftDownVectorBar", 3, {226, 165, 153} +"LeftDownVector", 3, {226, 135, 131} +"LeftFloor", 3, {226, 140, 138} +"leftharpoondown", 3, {226, 134, 189} +"leftharpoonup", 3, {226, 134, 188} +"leftleftarrows", 3, {226, 135, 135} +"leftrightarrow", 3, {226, 134, 148} +"LeftRightArrow", 3, {226, 134, 148} +"Leftrightarrow", 3, {226, 135, 148} +"leftrightarrows", 3, {226, 135, 134} +"leftrightharpoons", 3, {226, 135, 139} +"leftrightsquigarrow", 3, {226, 134, 173} +"LeftRightVector", 3, {226, 165, 142} +"LeftTeeArrow", 3, {226, 134, 164} +"LeftTee", 3, {226, 138, 163} +"LeftTeeVector", 3, {226, 165, 154} +"leftthreetimes", 3, {226, 139, 139} +"LeftTriangleBar", 3, {226, 167, 143} +"LeftTriangle", 3, {226, 138, 178} +"LeftTriangleEqual", 3, {226, 138, 180} +"LeftUpDownVector", 3, {226, 165, 145} +"LeftUpTeeVector", 3, {226, 165, 160} +"LeftUpVectorBar", 3, {226, 165, 152} +"LeftUpVector", 3, {226, 134, 191} +"LeftVectorBar", 3, {226, 165, 146} +"LeftVector", 3, {226, 134, 188} +"lEg", 3, {226, 170, 139} +"leg", 3, {226, 139, 154} +"leq", 3, {226, 137, 164} +"leqq", 3, {226, 137, 166} +"leqslant", 3, {226, 169, 189} +"lescc", 3, {226, 170, 168} +"les", 3, {226, 169, 189} +"lesdot", 3, {226, 169, 191} +"lesdoto", 3, {226, 170, 129} +"lesdotor", 3, {226, 170, 131} +"lesg", 3, {226, 139, 154} +"lesges", 3, {226, 170, 147} +"lessapprox", 3, {226, 170, 133} +"lessdot", 3, {226, 139, 150} +"lesseqgtr", 3, {226, 139, 154} +"lesseqqgtr", 3, {226, 170, 139} +"LessEqualGreater", 3, {226, 139, 154} +"LessFullEqual", 3, {226, 137, 166} +"LessGreater", 3, {226, 137, 182} +"lessgtr", 3, {226, 137, 182} +"LessLess", 3, {226, 170, 161} +"lesssim", 3, {226, 137, 178} +"LessSlantEqual", 3, {226, 169, 189} +"LessTilde", 3, {226, 137, 178} +"lfisht", 3, {226, 165, 188} +"lfloor", 3, {226, 140, 138} +"Lfr", 4, {240, 157, 148, 143} +"lfr", 4, {240, 157, 148, 169} +"lg", 3, {226, 137, 182} +"lgE", 3, {226, 170, 145} +"lHar", 3, {226, 165, 162} +"lhard", 3, {226, 134, 189} +"lharu", 3, {226, 134, 188} +"lharul", 3, {226, 165, 170} +"lhblk", 3, {226, 150, 132} +"LJcy", 2, {208, 137} +"ljcy", 2, {209, 153} +"llarr", 3, {226, 135, 135} +"ll", 3, {226, 137, 170} +"Ll", 3, {226, 139, 152} +"llcorner", 3, {226, 140, 158} +"Lleftarrow", 3, {226, 135, 154} +"llhard", 3, {226, 165, 171} +"lltri", 3, {226, 151, 186} +"Lmidot", 2, {196, 191} +"lmidot", 2, {197, 128} +"lmoustache", 3, {226, 142, 176} +"lmoust", 3, {226, 142, 176} +"lnap", 3, {226, 170, 137} +"lnapprox", 3, {226, 170, 137} +"lne", 3, {226, 170, 135} +"lnE", 3, {226, 137, 168} +"lneq", 3, {226, 170, 135} +"lneqq", 3, {226, 137, 168} +"lnsim", 3, {226, 139, 166} +"loang", 3, {226, 159, 172} +"loarr", 3, {226, 135, 189} +"lobrk", 3, {226, 159, 166} +"longleftarrow", 3, {226, 159, 181} +"LongLeftArrow", 3, {226, 159, 181} +"Longleftarrow", 3, {226, 159, 184} +"longleftrightarrow", 3, {226, 159, 183} +"LongLeftRightArrow", 3, {226, 159, 183} +"Longleftrightarrow", 3, {226, 159, 186} +"longmapsto", 3, {226, 159, 188} +"longrightarrow", 3, {226, 159, 182} +"LongRightArrow", 3, {226, 159, 182} +"Longrightarrow", 3, {226, 159, 185} +"looparrowleft", 3, {226, 134, 171} +"looparrowright", 3, {226, 134, 172} +"lopar", 3, {226, 166, 133} +"Lopf", 4, {240, 157, 149, 131} +"lopf", 4, {240, 157, 149, 157} +"loplus", 3, {226, 168, 173} +"lotimes", 3, {226, 168, 180} +"lowast", 3, {226, 136, 151} +"lowbar", 1, {95} +"LowerLeftArrow", 3, {226, 134, 153} +"LowerRightArrow", 3, {226, 134, 152} +"loz", 3, {226, 151, 138} +"lozenge", 3, {226, 151, 138} +"lozf", 3, {226, 167, 171} +"lpar", 1, {40} +"lparlt", 3, {226, 166, 147} +"lrarr", 3, {226, 135, 134} +"lrcorner", 3, {226, 140, 159} +"lrhar", 3, {226, 135, 139} +"lrhard", 3, {226, 165, 173} +"lrm", 3, {226, 128, 142} +"lrtri", 3, {226, 138, 191} +"lsaquo", 3, {226, 128, 185} +"lscr", 4, {240, 157, 147, 129} +"Lscr", 3, {226, 132, 146} +"lsh", 3, {226, 134, 176} +"Lsh", 3, {226, 134, 176} +"lsim", 3, {226, 137, 178} +"lsime", 3, {226, 170, 141} +"lsimg", 3, {226, 170, 143} +"lsqb", 1, {91} +"lsquo", 3, {226, 128, 152} +"lsquor", 3, {226, 128, 154} +"Lstrok", 2, {197, 129} +"lstrok", 2, {197, 130} +"ltcc", 3, {226, 170, 166} +"ltcir", 3, {226, 169, 185} +"lt", 1, {60} +"LT", 1, {60} +"Lt", 3, {226, 137, 170} +"ltdot", 3, {226, 139, 150} +"lthree", 3, {226, 139, 139} +"ltimes", 3, {226, 139, 137} +"ltlarr", 3, {226, 165, 182} +"ltquest", 3, {226, 169, 187} +"ltri", 3, {226, 151, 131} +"ltrie", 3, {226, 138, 180} +"ltrif", 3, {226, 151, 130} +"ltrPar", 3, {226, 166, 150} +"lurdshar", 3, {226, 165, 138} +"luruhar", 3, {226, 165, 166} +"lvertneqq", 3, {226, 137, 168} +"lvnE", 3, {226, 137, 168} +"macr", 2, {194, 175} +"male", 3, {226, 153, 130} +"malt", 3, {226, 156, 160} +"maltese", 3, {226, 156, 160} +"Map", 3, {226, 164, 133} +"map", 3, {226, 134, 166} +"mapsto", 3, {226, 134, 166} +"mapstodown", 3, {226, 134, 167} +"mapstoleft", 3, {226, 134, 164} +"mapstoup", 3, {226, 134, 165} +"marker", 3, {226, 150, 174} +"mcomma", 3, {226, 168, 169} +"Mcy", 2, {208, 156} +"mcy", 2, {208, 188} +"mdash", 3, {226, 128, 148} +"mDDot", 3, {226, 136, 186} +"measuredangle", 3, {226, 136, 161} +"MediumSpace", 3, {226, 129, 159} +"Mellintrf", 3, {226, 132, 179} +"Mfr", 4, {240, 157, 148, 144} +"mfr", 4, {240, 157, 148, 170} +"mho", 3, {226, 132, 167} +"micro", 2, {194, 181} +"midast", 1, {42} +"midcir", 3, {226, 171, 176} +"mid", 3, {226, 136, 163} +"middot", 2, {194, 183} +"minusb", 3, {226, 138, 159} +"minus", 3, {226, 136, 146} +"minusd", 3, {226, 136, 184} +"minusdu", 3, {226, 168, 170} +"MinusPlus", 3, {226, 136, 147} +"mlcp", 3, {226, 171, 155} +"mldr", 3, {226, 128, 166} +"mnplus", 3, {226, 136, 147} +"models", 3, {226, 138, 167} +"Mopf", 4, {240, 157, 149, 132} +"mopf", 4, {240, 157, 149, 158} +"mp", 3, {226, 136, 147} +"mscr", 4, {240, 157, 147, 130} +"Mscr", 3, {226, 132, 179} +"mstpos", 3, {226, 136, 190} +"Mu", 2, {206, 156} +"mu", 2, {206, 188} +"multimap", 3, {226, 138, 184} +"mumap", 3, {226, 138, 184} +"nabla", 3, {226, 136, 135} +"Nacute", 2, {197, 131} +"nacute", 2, {197, 132} +"nang", 3, {226, 136, 160} +"nap", 3, {226, 137, 137} +"napE", 3, {226, 169, 176} +"napid", 3, {226, 137, 139} +"napos", 2, {197, 137} +"napprox", 3, {226, 137, 137} +"natural", 3, {226, 153, 174} +"naturals", 3, {226, 132, 149} +"natur", 3, {226, 153, 174} +"nbsp", 2, {194, 160} +"nbump", 3, {226, 137, 142} +"nbumpe", 3, {226, 137, 143} +"ncap", 3, {226, 169, 131} +"Ncaron", 2, {197, 135} +"ncaron", 2, {197, 136} +"Ncedil", 2, {197, 133} +"ncedil", 2, {197, 134} +"ncong", 3, {226, 137, 135} +"ncongdot", 3, {226, 169, 173} +"ncup", 3, {226, 169, 130} +"Ncy", 2, {208, 157} +"ncy", 2, {208, 189} +"ndash", 3, {226, 128, 147} +"nearhk", 3, {226, 164, 164} +"nearr", 3, {226, 134, 151} +"neArr", 3, {226, 135, 151} +"nearrow", 3, {226, 134, 151} +"ne", 3, {226, 137, 160} +"nedot", 3, {226, 137, 144} +"NegativeMediumSpace", 3, {226, 128, 139} +"NegativeThickSpace", 3, {226, 128, 139} +"NegativeThinSpace", 3, {226, 128, 139} +"NegativeVeryThinSpace", 3, {226, 128, 139} +"nequiv", 3, {226, 137, 162} +"nesear", 3, {226, 164, 168} +"nesim", 3, {226, 137, 130} +"NestedGreaterGreater", 3, {226, 137, 171} +"NestedLessLess", 3, {226, 137, 170} +"NewLine", 1, {10} +"nexist", 3, {226, 136, 132} +"nexists", 3, {226, 136, 132} +"Nfr", 4, {240, 157, 148, 145} +"nfr", 4, {240, 157, 148, 171} +"ngE", 3, {226, 137, 167} +"nge", 3, {226, 137, 177} +"ngeq", 3, {226, 137, 177} +"ngeqq", 3, {226, 137, 167} +"ngeqslant", 3, {226, 169, 190} +"nges", 3, {226, 169, 190} +"nGg", 3, {226, 139, 153} +"ngsim", 3, {226, 137, 181} +"nGt", 3, {226, 137, 171} +"ngt", 3, {226, 137, 175} +"ngtr", 3, {226, 137, 175} +"nGtv", 3, {226, 137, 171} +"nharr", 3, {226, 134, 174} +"nhArr", 3, {226, 135, 142} +"nhpar", 3, {226, 171, 178} +"ni", 3, {226, 136, 139} +"nis", 3, {226, 139, 188} +"nisd", 3, {226, 139, 186} +"niv", 3, {226, 136, 139} +"NJcy", 2, {208, 138} +"njcy", 2, {209, 154} +"nlarr", 3, {226, 134, 154} +"nlArr", 3, {226, 135, 141} +"nldr", 3, {226, 128, 165} +"nlE", 3, {226, 137, 166} +"nle", 3, {226, 137, 176} +"nleftarrow", 3, {226, 134, 154} +"nLeftarrow", 3, {226, 135, 141} +"nleftrightarrow", 3, {226, 134, 174} +"nLeftrightarrow", 3, {226, 135, 142} +"nleq", 3, {226, 137, 176} +"nleqq", 3, {226, 137, 166} +"nleqslant", 3, {226, 169, 189} +"nles", 3, {226, 169, 189} +"nless", 3, {226, 137, 174} +"nLl", 3, {226, 139, 152} +"nlsim", 3, {226, 137, 180} +"nLt", 3, {226, 137, 170} +"nlt", 3, {226, 137, 174} +"nltri", 3, {226, 139, 170} +"nltrie", 3, {226, 139, 172} +"nLtv", 3, {226, 137, 170} +"nmid", 3, {226, 136, 164} +"NoBreak", 3, {226, 129, 160} +"NonBreakingSpace", 2, {194, 160} +"nopf", 4, {240, 157, 149, 159} +"Nopf", 3, {226, 132, 149} +"Not", 3, {226, 171, 172} +"not", 2, {194, 172} +"NotCongruent", 3, {226, 137, 162} +"NotCupCap", 3, {226, 137, 173} +"NotDoubleVerticalBar", 3, {226, 136, 166} +"NotElement", 3, {226, 136, 137} +"NotEqual", 3, {226, 137, 160} +"NotEqualTilde", 3, {226, 137, 130} +"NotExists", 3, {226, 136, 132} +"NotGreater", 3, {226, 137, 175} +"NotGreaterEqual", 3, {226, 137, 177} +"NotGreaterFullEqual", 3, {226, 137, 167} +"NotGreaterGreater", 3, {226, 137, 171} +"NotGreaterLess", 3, {226, 137, 185} +"NotGreaterSlantEqual", 3, {226, 169, 190} +"NotGreaterTilde", 3, {226, 137, 181} +"NotHumpDownHump", 3, {226, 137, 142} +"NotHumpEqual", 3, {226, 137, 143} +"notin", 3, {226, 136, 137} +"notindot", 3, {226, 139, 181} +"notinE", 3, {226, 139, 185} +"notinva", 3, {226, 136, 137} +"notinvb", 3, {226, 139, 183} +"notinvc", 3, {226, 139, 182} +"NotLeftTriangleBar", 3, {226, 167, 143} +"NotLeftTriangle", 3, {226, 139, 170} +"NotLeftTriangleEqual", 3, {226, 139, 172} +"NotLess", 3, {226, 137, 174} +"NotLessEqual", 3, {226, 137, 176} +"NotLessGreater", 3, {226, 137, 184} +"NotLessLess", 3, {226, 137, 170} +"NotLessSlantEqual", 3, {226, 169, 189} +"NotLessTilde", 3, {226, 137, 180} +"NotNestedGreaterGreater", 3, {226, 170, 162} +"NotNestedLessLess", 3, {226, 170, 161} +"notni", 3, {226, 136, 140} +"notniva", 3, {226, 136, 140} +"notnivb", 3, {226, 139, 190} +"notnivc", 3, {226, 139, 189} +"NotPrecedes", 3, {226, 138, 128} +"NotPrecedesEqual", 3, {226, 170, 175} +"NotPrecedesSlantEqual", 3, {226, 139, 160} +"NotReverseElement", 3, {226, 136, 140} +"NotRightTriangleBar", 3, {226, 167, 144} +"NotRightTriangle", 3, {226, 139, 171} +"NotRightTriangleEqual", 3, {226, 139, 173} +"NotSquareSubset", 3, {226, 138, 143} +"NotSquareSubsetEqual", 3, {226, 139, 162} +"NotSquareSuperset", 3, {226, 138, 144} +"NotSquareSupersetEqual", 3, {226, 139, 163} +"NotSubset", 3, {226, 138, 130} +"NotSubsetEqual", 3, {226, 138, 136} +"NotSucceeds", 3, {226, 138, 129} +"NotSucceedsEqual", 3, {226, 170, 176} +"NotSucceedsSlantEqual", 3, {226, 139, 161} +"NotSucceedsTilde", 3, {226, 137, 191} +"NotSuperset", 3, {226, 138, 131} +"NotSupersetEqual", 3, {226, 138, 137} +"NotTilde", 3, {226, 137, 129} +"NotTildeEqual", 3, {226, 137, 132} +"NotTildeFullEqual", 3, {226, 137, 135} +"NotTildeTilde", 3, {226, 137, 137} +"NotVerticalBar", 3, {226, 136, 164} +"nparallel", 3, {226, 136, 166} +"npar", 3, {226, 136, 166} +"nparsl", 3, {226, 171, 189} +"npart", 3, {226, 136, 130} +"npolint", 3, {226, 168, 148} +"npr", 3, {226, 138, 128} +"nprcue", 3, {226, 139, 160} +"nprec", 3, {226, 138, 128} +"npreceq", 3, {226, 170, 175} +"npre", 3, {226, 170, 175} +"nrarrc", 3, {226, 164, 179} +"nrarr", 3, {226, 134, 155} +"nrArr", 3, {226, 135, 143} +"nrarrw", 3, {226, 134, 157} +"nrightarrow", 3, {226, 134, 155} +"nRightarrow", 3, {226, 135, 143} +"nrtri", 3, {226, 139, 171} +"nrtrie", 3, {226, 139, 173} +"nsc", 3, {226, 138, 129} +"nsccue", 3, {226, 139, 161} +"nsce", 3, {226, 170, 176} +"Nscr", 4, {240, 157, 146, 169} +"nscr", 4, {240, 157, 147, 131} +"nshortmid", 3, {226, 136, 164} +"nshortparallel", 3, {226, 136, 166} +"nsim", 3, {226, 137, 129} +"nsime", 3, {226, 137, 132} +"nsimeq", 3, {226, 137, 132} +"nsmid", 3, {226, 136, 164} +"nspar", 3, {226, 136, 166} +"nsqsube", 3, {226, 139, 162} +"nsqsupe", 3, {226, 139, 163} +"nsub", 3, {226, 138, 132} +"nsubE", 3, {226, 171, 133} +"nsube", 3, {226, 138, 136} +"nsubset", 3, {226, 138, 130} +"nsubseteq", 3, {226, 138, 136} +"nsubseteqq", 3, {226, 171, 133} +"nsucc", 3, {226, 138, 129} +"nsucceq", 3, {226, 170, 176} +"nsup", 3, {226, 138, 133} +"nsupE", 3, {226, 171, 134} +"nsupe", 3, {226, 138, 137} +"nsupset", 3, {226, 138, 131} +"nsupseteq", 3, {226, 138, 137} +"nsupseteqq", 3, {226, 171, 134} +"ntgl", 3, {226, 137, 185} +"Ntilde", 2, {195, 145} +"ntilde", 2, {195, 177} +"ntlg", 3, {226, 137, 184} +"ntriangleleft", 3, {226, 139, 170} +"ntrianglelefteq", 3, {226, 139, 172} +"ntriangleright", 3, {226, 139, 171} +"ntrianglerighteq", 3, {226, 139, 173} +"Nu", 2, {206, 157} +"nu", 2, {206, 189} +"num", 1, {35} +"numero", 3, {226, 132, 150} +"numsp", 3, {226, 128, 135} +"nvap", 3, {226, 137, 141} +"nvdash", 3, {226, 138, 172} +"nvDash", 3, {226, 138, 173} +"nVdash", 3, {226, 138, 174} +"nVDash", 3, {226, 138, 175} +"nvge", 3, {226, 137, 165} +"nvgt", 1, {62} +"nvHarr", 3, {226, 164, 132} +"nvinfin", 3, {226, 167, 158} +"nvlArr", 3, {226, 164, 130} +"nvle", 3, {226, 137, 164} +"nvlt", 1, {60} +"nvltrie", 3, {226, 138, 180} +"nvrArr", 3, {226, 164, 131} +"nvrtrie", 3, {226, 138, 181} +"nvsim", 3, {226, 136, 188} +"nwarhk", 3, {226, 164, 163} +"nwarr", 3, {226, 134, 150} +"nwArr", 3, {226, 135, 150} +"nwarrow", 3, {226, 134, 150} +"nwnear", 3, {226, 164, 167} +"Oacute", 2, {195, 147} +"oacute", 2, {195, 179} +"oast", 3, {226, 138, 155} +"Ocirc", 2, {195, 148} +"ocirc", 2, {195, 180} +"ocir", 3, {226, 138, 154} +"Ocy", 2, {208, 158} +"ocy", 2, {208, 190} +"odash", 3, {226, 138, 157} +"Odblac", 2, {197, 144} +"odblac", 2, {197, 145} +"odiv", 3, {226, 168, 184} +"odot", 3, {226, 138, 153} +"odsold", 3, {226, 166, 188} +"OElig", 2, {197, 146} +"oelig", 2, {197, 147} +"ofcir", 3, {226, 166, 191} +"Ofr", 4, {240, 157, 148, 146} +"ofr", 4, {240, 157, 148, 172} +"ogon", 2, {203, 155} +"Ograve", 2, {195, 146} +"ograve", 2, {195, 178} +"ogt", 3, {226, 167, 129} +"ohbar", 3, {226, 166, 181} +"ohm", 2, {206, 169} +"oint", 3, {226, 136, 174} +"olarr", 3, {226, 134, 186} +"olcir", 3, {226, 166, 190} +"olcross", 3, {226, 166, 187} +"oline", 3, {226, 128, 190} +"olt", 3, {226, 167, 128} +"Omacr", 2, {197, 140} +"omacr", 2, {197, 141} +"Omega", 2, {206, 169} +"omega", 2, {207, 137} +"Omicron", 2, {206, 159} +"omicron", 2, {206, 191} +"omid", 3, {226, 166, 182} +"ominus", 3, {226, 138, 150} +"Oopf", 4, {240, 157, 149, 134} +"oopf", 4, {240, 157, 149, 160} +"opar", 3, {226, 166, 183} +"OpenCurlyDoubleQuote", 3, {226, 128, 156} +"OpenCurlyQuote", 3, {226, 128, 152} +"operp", 3, {226, 166, 185} +"oplus", 3, {226, 138, 149} +"orarr", 3, {226, 134, 187} +"Or", 3, {226, 169, 148} +"or", 3, {226, 136, 168} +"ord", 3, {226, 169, 157} +"order", 3, {226, 132, 180} +"orderof", 3, {226, 132, 180} +"ordf", 2, {194, 170} +"ordm", 2, {194, 186} +"origof", 3, {226, 138, 182} +"oror", 3, {226, 169, 150} +"orslope", 3, {226, 169, 151} +"orv", 3, {226, 169, 155} +"oS", 3, {226, 147, 136} +"Oscr", 4, {240, 157, 146, 170} +"oscr", 3, {226, 132, 180} +"Oslash", 2, {195, 152} +"oslash", 2, {195, 184} +"osol", 3, {226, 138, 152} +"Otilde", 2, {195, 149} +"otilde", 2, {195, 181} +"otimesas", 3, {226, 168, 182} +"Otimes", 3, {226, 168, 183} +"otimes", 3, {226, 138, 151} +"Ouml", 2, {195, 150} +"ouml", 2, {195, 182} +"ovbar", 3, {226, 140, 189} +"OverBar", 3, {226, 128, 190} +"OverBrace", 3, {226, 143, 158} +"OverBracket", 3, {226, 142, 180} +"OverParenthesis", 3, {226, 143, 156} +"para", 2, {194, 182} +"parallel", 3, {226, 136, 165} +"par", 3, {226, 136, 165} +"parsim", 3, {226, 171, 179} +"parsl", 3, {226, 171, 189} +"part", 3, {226, 136, 130} +"PartialD", 3, {226, 136, 130} +"Pcy", 2, {208, 159} +"pcy", 2, {208, 191} +"percnt", 1, {37} +"period", 1, {46} +"permil", 3, {226, 128, 176} +"perp", 3, {226, 138, 165} +"pertenk", 3, {226, 128, 177} +"Pfr", 4, {240, 157, 148, 147} +"pfr", 4, {240, 157, 148, 173} +"Phi", 2, {206, 166} +"phi", 2, {207, 134} +"phiv", 2, {207, 149} +"phmmat", 3, {226, 132, 179} +"phone", 3, {226, 152, 142} +"Pi", 2, {206, 160} +"pi", 2, {207, 128} +"pitchfork", 3, {226, 139, 148} +"piv", 2, {207, 150} +"planck", 3, {226, 132, 143} +"planckh", 3, {226, 132, 142} +"plankv", 3, {226, 132, 143} +"plusacir", 3, {226, 168, 163} +"plusb", 3, {226, 138, 158} +"pluscir", 3, {226, 168, 162} +"plus", 1, {43} +"plusdo", 3, {226, 136, 148} +"plusdu", 3, {226, 168, 165} +"pluse", 3, {226, 169, 178} +"PlusMinus", 2, {194, 177} +"plusmn", 2, {194, 177} +"plussim", 3, {226, 168, 166} +"plustwo", 3, {226, 168, 167} +"pm", 2, {194, 177} +"Poincareplane", 3, {226, 132, 140} +"pointint", 3, {226, 168, 149} +"popf", 4, {240, 157, 149, 161} +"Popf", 3, {226, 132, 153} +"pound", 2, {194, 163} +"prap", 3, {226, 170, 183} +"Pr", 3, {226, 170, 187} +"pr", 3, {226, 137, 186} +"prcue", 3, {226, 137, 188} +"precapprox", 3, {226, 170, 183} +"prec", 3, {226, 137, 186} +"preccurlyeq", 3, {226, 137, 188} +"Precedes", 3, {226, 137, 186} +"PrecedesEqual", 3, {226, 170, 175} +"PrecedesSlantEqual", 3, {226, 137, 188} +"PrecedesTilde", 3, {226, 137, 190} +"preceq", 3, {226, 170, 175} +"precnapprox", 3, {226, 170, 185} +"precneqq", 3, {226, 170, 181} +"precnsim", 3, {226, 139, 168} +"pre", 3, {226, 170, 175} +"prE", 3, {226, 170, 179} +"precsim", 3, {226, 137, 190} +"prime", 3, {226, 128, 178} +"Prime", 3, {226, 128, 179} +"primes", 3, {226, 132, 153} +"prnap", 3, {226, 170, 185} +"prnE", 3, {226, 170, 181} +"prnsim", 3, {226, 139, 168} +"prod", 3, {226, 136, 143} +"Product", 3, {226, 136, 143} +"profalar", 3, {226, 140, 174} +"profline", 3, {226, 140, 146} +"profsurf", 3, {226, 140, 147} +"prop", 3, {226, 136, 157} +"Proportional", 3, {226, 136, 157} +"Proportion", 3, {226, 136, 183} +"propto", 3, {226, 136, 157} +"prsim", 3, {226, 137, 190} +"prurel", 3, {226, 138, 176} +"Pscr", 4, {240, 157, 146, 171} +"pscr", 4, {240, 157, 147, 133} +"Psi", 2, {206, 168} +"psi", 2, {207, 136} +"puncsp", 3, {226, 128, 136} +"Qfr", 4, {240, 157, 148, 148} +"qfr", 4, {240, 157, 148, 174} +"qint", 3, {226, 168, 140} +"qopf", 4, {240, 157, 149, 162} +"Qopf", 3, {226, 132, 154} +"qprime", 3, {226, 129, 151} +"Qscr", 4, {240, 157, 146, 172} +"qscr", 4, {240, 157, 147, 134} +"quaternions", 3, {226, 132, 141} +"quatint", 3, {226, 168, 150} +"quest", 1, {63} +"questeq", 3, {226, 137, 159} +"quot", 1, {34} +"QUOT", 1, {34} +"rAarr", 3, {226, 135, 155} +"race", 3, {226, 136, 189} +"Racute", 2, {197, 148} +"racute", 2, {197, 149} +"radic", 3, {226, 136, 154} +"raemptyv", 3, {226, 166, 179} +"rang", 3, {226, 159, 169} +"Rang", 3, {226, 159, 171} +"rangd", 3, {226, 166, 146} +"range", 3, {226, 166, 165} +"rangle", 3, {226, 159, 169} +"raquo", 2, {194, 187} +"rarrap", 3, {226, 165, 181} +"rarrb", 3, {226, 135, 165} +"rarrbfs", 3, {226, 164, 160} +"rarrc", 3, {226, 164, 179} +"rarr", 3, {226, 134, 146} +"Rarr", 3, {226, 134, 160} +"rArr", 3, {226, 135, 146} +"rarrfs", 3, {226, 164, 158} +"rarrhk", 3, {226, 134, 170} +"rarrlp", 3, {226, 134, 172} +"rarrpl", 3, {226, 165, 133} +"rarrsim", 3, {226, 165, 180} +"Rarrtl", 3, {226, 164, 150} +"rarrtl", 3, {226, 134, 163} +"rarrw", 3, {226, 134, 157} +"ratail", 3, {226, 164, 154} +"rAtail", 3, {226, 164, 156} +"ratio", 3, {226, 136, 182} +"rationals", 3, {226, 132, 154} +"rbarr", 3, {226, 164, 141} +"rBarr", 3, {226, 164, 143} +"RBarr", 3, {226, 164, 144} +"rbbrk", 3, {226, 157, 179} +"rbrace", 1, {125} +"rbrack", 1, {93} +"rbrke", 3, {226, 166, 140} +"rbrksld", 3, {226, 166, 142} +"rbrkslu", 3, {226, 166, 144} +"Rcaron", 2, {197, 152} +"rcaron", 2, {197, 153} +"Rcedil", 2, {197, 150} +"rcedil", 2, {197, 151} +"rceil", 3, {226, 140, 137} +"rcub", 1, {125} +"Rcy", 2, {208, 160} +"rcy", 2, {209, 128} +"rdca", 3, {226, 164, 183} +"rdldhar", 3, {226, 165, 169} +"rdquo", 3, {226, 128, 157} +"rdquor", 3, {226, 128, 157} +"rdsh", 3, {226, 134, 179} +"real", 3, {226, 132, 156} +"realine", 3, {226, 132, 155} +"realpart", 3, {226, 132, 156} +"reals", 3, {226, 132, 157} +"Re", 3, {226, 132, 156} +"rect", 3, {226, 150, 173} +"reg", 2, {194, 174} +"REG", 2, {194, 174} +"ReverseElement", 3, {226, 136, 139} +"ReverseEquilibrium", 3, {226, 135, 139} +"ReverseUpEquilibrium", 3, {226, 165, 175} +"rfisht", 3, {226, 165, 189} +"rfloor", 3, {226, 140, 139} +"rfr", 4, {240, 157, 148, 175} +"Rfr", 3, {226, 132, 156} +"rHar", 3, {226, 165, 164} +"rhard", 3, {226, 135, 129} +"rharu", 3, {226, 135, 128} +"rharul", 3, {226, 165, 172} +"Rho", 2, {206, 161} +"rho", 2, {207, 129} +"rhov", 2, {207, 177} +"RightAngleBracket", 3, {226, 159, 169} +"RightArrowBar", 3, {226, 135, 165} +"rightarrow", 3, {226, 134, 146} +"RightArrow", 3, {226, 134, 146} +"Rightarrow", 3, {226, 135, 146} +"RightArrowLeftArrow", 3, {226, 135, 132} +"rightarrowtail", 3, {226, 134, 163} +"RightCeiling", 3, {226, 140, 137} +"RightDoubleBracket", 3, {226, 159, 167} +"RightDownTeeVector", 3, {226, 165, 157} +"RightDownVectorBar", 3, {226, 165, 149} +"RightDownVector", 3, {226, 135, 130} +"RightFloor", 3, {226, 140, 139} +"rightharpoondown", 3, {226, 135, 129} +"rightharpoonup", 3, {226, 135, 128} +"rightleftarrows", 3, {226, 135, 132} +"rightleftharpoons", 3, {226, 135, 140} +"rightrightarrows", 3, {226, 135, 137} +"rightsquigarrow", 3, {226, 134, 157} +"RightTeeArrow", 3, {226, 134, 166} +"RightTee", 3, {226, 138, 162} +"RightTeeVector", 3, {226, 165, 155} +"rightthreetimes", 3, {226, 139, 140} +"RightTriangleBar", 3, {226, 167, 144} +"RightTriangle", 3, {226, 138, 179} +"RightTriangleEqual", 3, {226, 138, 181} +"RightUpDownVector", 3, {226, 165, 143} +"RightUpTeeVector", 3, {226, 165, 156} +"RightUpVectorBar", 3, {226, 165, 148} +"RightUpVector", 3, {226, 134, 190} +"RightVectorBar", 3, {226, 165, 147} +"RightVector", 3, {226, 135, 128} +"ring", 2, {203, 154} +"risingdotseq", 3, {226, 137, 147} +"rlarr", 3, {226, 135, 132} +"rlhar", 3, {226, 135, 140} +"rlm", 3, {226, 128, 143} +"rmoustache", 3, {226, 142, 177} +"rmoust", 3, {226, 142, 177} +"rnmid", 3, {226, 171, 174} +"roang", 3, {226, 159, 173} +"roarr", 3, {226, 135, 190} +"robrk", 3, {226, 159, 167} +"ropar", 3, {226, 166, 134} +"ropf", 4, {240, 157, 149, 163} +"Ropf", 3, {226, 132, 157} +"roplus", 3, {226, 168, 174} +"rotimes", 3, {226, 168, 181} +"RoundImplies", 3, {226, 165, 176} +"rpar", 1, {41} +"rpargt", 3, {226, 166, 148} +"rppolint", 3, {226, 168, 146} +"rrarr", 3, {226, 135, 137} +"Rrightarrow", 3, {226, 135, 155} +"rsaquo", 3, {226, 128, 186} +"rscr", 4, {240, 157, 147, 135} +"Rscr", 3, {226, 132, 155} +"rsh", 3, {226, 134, 177} +"Rsh", 3, {226, 134, 177} +"rsqb", 1, {93} +"rsquo", 3, {226, 128, 153} +"rsquor", 3, {226, 128, 153} +"rthree", 3, {226, 139, 140} +"rtimes", 3, {226, 139, 138} +"rtri", 3, {226, 150, 185} +"rtrie", 3, {226, 138, 181} +"rtrif", 3, {226, 150, 184} +"rtriltri", 3, {226, 167, 142} +"RuleDelayed", 3, {226, 167, 180} +"ruluhar", 3, {226, 165, 168} +"rx", 3, {226, 132, 158} +"Sacute", 2, {197, 154} +"sacute", 2, {197, 155} +"sbquo", 3, {226, 128, 154} +"scap", 3, {226, 170, 184} +"Scaron", 2, {197, 160} +"scaron", 2, {197, 161} +"Sc", 3, {226, 170, 188} +"sc", 3, {226, 137, 187} +"sccue", 3, {226, 137, 189} +"sce", 3, {226, 170, 176} +"scE", 3, {226, 170, 180} +"Scedil", 2, {197, 158} +"scedil", 2, {197, 159} +"Scirc", 2, {197, 156} +"scirc", 2, {197, 157} +"scnap", 3, {226, 170, 186} +"scnE", 3, {226, 170, 182} +"scnsim", 3, {226, 139, 169} +"scpolint", 3, {226, 168, 147} +"scsim", 3, {226, 137, 191} +"Scy", 2, {208, 161} +"scy", 2, {209, 129} +"sdotb", 3, {226, 138, 161} +"sdot", 3, {226, 139, 133} +"sdote", 3, {226, 169, 166} +"searhk", 3, {226, 164, 165} +"searr", 3, {226, 134, 152} +"seArr", 3, {226, 135, 152} +"searrow", 3, {226, 134, 152} +"sect", 2, {194, 167} +"semi", 1, {59} +"seswar", 3, {226, 164, 169} +"setminus", 3, {226, 136, 150} +"setmn", 3, {226, 136, 150} +"sext", 3, {226, 156, 182} +"Sfr", 4, {240, 157, 148, 150} +"sfr", 4, {240, 157, 148, 176} +"sfrown", 3, {226, 140, 162} +"sharp", 3, {226, 153, 175} +"SHCHcy", 2, {208, 169} +"shchcy", 2, {209, 137} +"SHcy", 2, {208, 168} +"shcy", 2, {209, 136} +"ShortDownArrow", 3, {226, 134, 147} +"ShortLeftArrow", 3, {226, 134, 144} +"shortmid", 3, {226, 136, 163} +"shortparallel", 3, {226, 136, 165} +"ShortRightArrow", 3, {226, 134, 146} +"ShortUpArrow", 3, {226, 134, 145} +"shy", 2, {194, 173} +"Sigma", 2, {206, 163} +"sigma", 2, {207, 131} +"sigmaf", 2, {207, 130} +"sigmav", 2, {207, 130} +"sim", 3, {226, 136, 188} +"simdot", 3, {226, 169, 170} +"sime", 3, {226, 137, 131} +"simeq", 3, {226, 137, 131} +"simg", 3, {226, 170, 158} +"simgE", 3, {226, 170, 160} +"siml", 3, {226, 170, 157} +"simlE", 3, {226, 170, 159} +"simne", 3, {226, 137, 134} +"simplus", 3, {226, 168, 164} +"simrarr", 3, {226, 165, 178} +"slarr", 3, {226, 134, 144} +"SmallCircle", 3, {226, 136, 152} +"smallsetminus", 3, {226, 136, 150} +"smashp", 3, {226, 168, 179} +"smeparsl", 3, {226, 167, 164} +"smid", 3, {226, 136, 163} +"smile", 3, {226, 140, 163} +"smt", 3, {226, 170, 170} +"smte", 3, {226, 170, 172} +"smtes", 3, {226, 170, 172} +"SOFTcy", 2, {208, 172} +"softcy", 2, {209, 140} +"solbar", 3, {226, 140, 191} +"solb", 3, {226, 167, 132} +"sol", 1, {47} +"Sopf", 4, {240, 157, 149, 138} +"sopf", 4, {240, 157, 149, 164} +"spades", 3, {226, 153, 160} +"spadesuit", 3, {226, 153, 160} +"spar", 3, {226, 136, 165} +"sqcap", 3, {226, 138, 147} +"sqcaps", 3, {226, 138, 147} +"sqcup", 3, {226, 138, 148} +"sqcups", 3, {226, 138, 148} +"Sqrt", 3, {226, 136, 154} +"sqsub", 3, {226, 138, 143} +"sqsube", 3, {226, 138, 145} +"sqsubset", 3, {226, 138, 143} +"sqsubseteq", 3, {226, 138, 145} +"sqsup", 3, {226, 138, 144} +"sqsupe", 3, {226, 138, 146} +"sqsupset", 3, {226, 138, 144} +"sqsupseteq", 3, {226, 138, 146} +"square", 3, {226, 150, 161} +"Square", 3, {226, 150, 161} +"SquareIntersection", 3, {226, 138, 147} +"SquareSubset", 3, {226, 138, 143} +"SquareSubsetEqual", 3, {226, 138, 145} +"SquareSuperset", 3, {226, 138, 144} +"SquareSupersetEqual", 3, {226, 138, 146} +"SquareUnion", 3, {226, 138, 148} +"squarf", 3, {226, 150, 170} +"squ", 3, {226, 150, 161} +"squf", 3, {226, 150, 170} +"srarr", 3, {226, 134, 146} +"Sscr", 4, {240, 157, 146, 174} +"sscr", 4, {240, 157, 147, 136} +"ssetmn", 3, {226, 136, 150} +"ssmile", 3, {226, 140, 163} +"sstarf", 3, {226, 139, 134} +"Star", 3, {226, 139, 134} +"star", 3, {226, 152, 134} +"starf", 3, {226, 152, 133} +"straightepsilon", 2, {207, 181} +"straightphi", 2, {207, 149} +"strns", 2, {194, 175} +"sub", 3, {226, 138, 130} +"Sub", 3, {226, 139, 144} +"subdot", 3, {226, 170, 189} +"subE", 3, {226, 171, 133} +"sube", 3, {226, 138, 134} +"subedot", 3, {226, 171, 131} +"submult", 3, {226, 171, 129} +"subnE", 3, {226, 171, 139} +"subne", 3, {226, 138, 138} +"subplus", 3, {226, 170, 191} +"subrarr", 3, {226, 165, 185} +"subset", 3, {226, 138, 130} +"Subset", 3, {226, 139, 144} +"subseteq", 3, {226, 138, 134} +"subseteqq", 3, {226, 171, 133} +"SubsetEqual", 3, {226, 138, 134} +"subsetneq", 3, {226, 138, 138} +"subsetneqq", 3, {226, 171, 139} +"subsim", 3, {226, 171, 135} +"subsub", 3, {226, 171, 149} +"subsup", 3, {226, 171, 147} +"succapprox", 3, {226, 170, 184} +"succ", 3, {226, 137, 187} +"succcurlyeq", 3, {226, 137, 189} +"Succeeds", 3, {226, 137, 187} +"SucceedsEqual", 3, {226, 170, 176} +"SucceedsSlantEqual", 3, {226, 137, 189} +"SucceedsTilde", 3, {226, 137, 191} +"succeq", 3, {226, 170, 176} +"succnapprox", 3, {226, 170, 186} +"succneqq", 3, {226, 170, 182} +"succnsim", 3, {226, 139, 169} +"succsim", 3, {226, 137, 191} +"SuchThat", 3, {226, 136, 139} +"sum", 3, {226, 136, 145} +"Sum", 3, {226, 136, 145} +"sung", 3, {226, 153, 170} +"sup1", 2, {194, 185} +"sup2", 2, {194, 178} +"sup3", 2, {194, 179} +"sup", 3, {226, 138, 131} +"Sup", 3, {226, 139, 145} +"supdot", 3, {226, 170, 190} +"supdsub", 3, {226, 171, 152} +"supE", 3, {226, 171, 134} +"supe", 3, {226, 138, 135} +"supedot", 3, {226, 171, 132} +"Superset", 3, {226, 138, 131} +"SupersetEqual", 3, {226, 138, 135} +"suphsol", 3, {226, 159, 137} +"suphsub", 3, {226, 171, 151} +"suplarr", 3, {226, 165, 187} +"supmult", 3, {226, 171, 130} +"supnE", 3, {226, 171, 140} +"supne", 3, {226, 138, 139} +"supplus", 3, {226, 171, 128} +"supset", 3, {226, 138, 131} +"Supset", 3, {226, 139, 145} +"supseteq", 3, {226, 138, 135} +"supseteqq", 3, {226, 171, 134} +"supsetneq", 3, {226, 138, 139} +"supsetneqq", 3, {226, 171, 140} +"supsim", 3, {226, 171, 136} +"supsub", 3, {226, 171, 148} +"supsup", 3, {226, 171, 150} +"swarhk", 3, {226, 164, 166} +"swarr", 3, {226, 134, 153} +"swArr", 3, {226, 135, 153} +"swarrow", 3, {226, 134, 153} +"swnwar", 3, {226, 164, 170} +"szlig", 2, {195, 159} +"Tab", 1, {9} +"target", 3, {226, 140, 150} +"Tau", 2, {206, 164} +"tau", 2, {207, 132} +"tbrk", 3, {226, 142, 180} +"Tcaron", 2, {197, 164} +"tcaron", 2, {197, 165} +"Tcedil", 2, {197, 162} +"tcedil", 2, {197, 163} +"Tcy", 2, {208, 162} +"tcy", 2, {209, 130} +"tdot", 3, {226, 131, 155} +"telrec", 3, {226, 140, 149} +"Tfr", 4, {240, 157, 148, 151} +"tfr", 4, {240, 157, 148, 177} +"there4", 3, {226, 136, 180} +"therefore", 3, {226, 136, 180} +"Therefore", 3, {226, 136, 180} +"Theta", 2, {206, 152} +"theta", 2, {206, 184} +"thetasym", 2, {207, 145} +"thetav", 2, {207, 145} +"thickapprox", 3, {226, 137, 136} +"thicksim", 3, {226, 136, 188} +"ThickSpace", 3, {226, 129, 159} +"ThinSpace", 3, {226, 128, 137} +"thinsp", 3, {226, 128, 137} +"thkap", 3, {226, 137, 136} +"thksim", 3, {226, 136, 188} +"THORN", 2, {195, 158} +"thorn", 2, {195, 190} +"tilde", 2, {203, 156} +"Tilde", 3, {226, 136, 188} +"TildeEqual", 3, {226, 137, 131} +"TildeFullEqual", 3, {226, 137, 133} +"TildeTilde", 3, {226, 137, 136} +"timesbar", 3, {226, 168, 177} +"timesb", 3, {226, 138, 160} +"times", 2, {195, 151} +"timesd", 3, {226, 168, 176} +"tint", 3, {226, 136, 173} +"toea", 3, {226, 164, 168} +"topbot", 3, {226, 140, 182} +"topcir", 3, {226, 171, 177} +"top", 3, {226, 138, 164} +"Topf", 4, {240, 157, 149, 139} +"topf", 4, {240, 157, 149, 165} +"topfork", 3, {226, 171, 154} +"tosa", 3, {226, 164, 169} +"tprime", 3, {226, 128, 180} +"trade", 3, {226, 132, 162} +"TRADE", 3, {226, 132, 162} +"triangle", 3, {226, 150, 181} +"triangledown", 3, {226, 150, 191} +"triangleleft", 3, {226, 151, 131} +"trianglelefteq", 3, {226, 138, 180} +"triangleq", 3, {226, 137, 156} +"triangleright", 3, {226, 150, 185} +"trianglerighteq", 3, {226, 138, 181} +"tridot", 3, {226, 151, 172} +"trie", 3, {226, 137, 156} +"triminus", 3, {226, 168, 186} +"TripleDot", 3, {226, 131, 155} +"triplus", 3, {226, 168, 185} +"trisb", 3, {226, 167, 141} +"tritime", 3, {226, 168, 187} +"trpezium", 3, {226, 143, 162} +"Tscr", 4, {240, 157, 146, 175} +"tscr", 4, {240, 157, 147, 137} +"TScy", 2, {208, 166} +"tscy", 2, {209, 134} +"TSHcy", 2, {208, 139} +"tshcy", 2, {209, 155} +"Tstrok", 2, {197, 166} +"tstrok", 2, {197, 167} +"twixt", 3, {226, 137, 172} +"twoheadleftarrow", 3, {226, 134, 158} +"twoheadrightarrow", 3, {226, 134, 160} +"Uacute", 2, {195, 154} +"uacute", 2, {195, 186} +"uarr", 3, {226, 134, 145} +"Uarr", 3, {226, 134, 159} +"uArr", 3, {226, 135, 145} +"Uarrocir", 3, {226, 165, 137} +"Ubrcy", 2, {208, 142} +"ubrcy", 2, {209, 158} +"Ubreve", 2, {197, 172} +"ubreve", 2, {197, 173} +"Ucirc", 2, {195, 155} +"ucirc", 2, {195, 187} +"Ucy", 2, {208, 163} +"ucy", 2, {209, 131} +"udarr", 3, {226, 135, 133} +"Udblac", 2, {197, 176} +"udblac", 2, {197, 177} +"udhar", 3, {226, 165, 174} +"ufisht", 3, {226, 165, 190} +"Ufr", 4, {240, 157, 148, 152} +"ufr", 4, {240, 157, 148, 178} +"Ugrave", 2, {195, 153} +"ugrave", 2, {195, 185} +"uHar", 3, {226, 165, 163} +"uharl", 3, {226, 134, 191} +"uharr", 3, {226, 134, 190} +"uhblk", 3, {226, 150, 128} +"ulcorn", 3, {226, 140, 156} +"ulcorner", 3, {226, 140, 156} +"ulcrop", 3, {226, 140, 143} +"ultri", 3, {226, 151, 184} +"Umacr", 2, {197, 170} +"umacr", 2, {197, 171} +"uml", 2, {194, 168} +"UnderBar", 1, {95} +"UnderBrace", 3, {226, 143, 159} +"UnderBracket", 3, {226, 142, 181} +"UnderParenthesis", 3, {226, 143, 157} +"Union", 3, {226, 139, 131} +"UnionPlus", 3, {226, 138, 142} +"Uogon", 2, {197, 178} +"uogon", 2, {197, 179} +"Uopf", 4, {240, 157, 149, 140} +"uopf", 4, {240, 157, 149, 166} +"UpArrowBar", 3, {226, 164, 146} +"uparrow", 3, {226, 134, 145} +"UpArrow", 3, {226, 134, 145} +"Uparrow", 3, {226, 135, 145} +"UpArrowDownArrow", 3, {226, 135, 133} +"updownarrow", 3, {226, 134, 149} +"UpDownArrow", 3, {226, 134, 149} +"Updownarrow", 3, {226, 135, 149} +"UpEquilibrium", 3, {226, 165, 174} +"upharpoonleft", 3, {226, 134, 191} +"upharpoonright", 3, {226, 134, 190} +"uplus", 3, {226, 138, 142} +"UpperLeftArrow", 3, {226, 134, 150} +"UpperRightArrow", 3, {226, 134, 151} +"upsi", 2, {207, 133} +"Upsi", 2, {207, 146} +"upsih", 2, {207, 146} +"Upsilon", 2, {206, 165} +"upsilon", 2, {207, 133} +"UpTeeArrow", 3, {226, 134, 165} +"UpTee", 3, {226, 138, 165} +"upuparrows", 3, {226, 135, 136} +"urcorn", 3, {226, 140, 157} +"urcorner", 3, {226, 140, 157} +"urcrop", 3, {226, 140, 142} +"Uring", 2, {197, 174} +"uring", 2, {197, 175} +"urtri", 3, {226, 151, 185} +"Uscr", 4, {240, 157, 146, 176} +"uscr", 4, {240, 157, 147, 138} +"utdot", 3, {226, 139, 176} +"Utilde", 2, {197, 168} +"utilde", 2, {197, 169} +"utri", 3, {226, 150, 181} +"utrif", 3, {226, 150, 180} +"uuarr", 3, {226, 135, 136} +"Uuml", 2, {195, 156} +"uuml", 2, {195, 188} +"uwangle", 3, {226, 166, 167} +"vangrt", 3, {226, 166, 156} +"varepsilon", 2, {207, 181} +"varkappa", 2, {207, 176} +"varnothing", 3, {226, 136, 133} +"varphi", 2, {207, 149} +"varpi", 2, {207, 150} +"varpropto", 3, {226, 136, 157} +"varr", 3, {226, 134, 149} +"vArr", 3, {226, 135, 149} +"varrho", 2, {207, 177} +"varsigma", 2, {207, 130} +"varsubsetneq", 3, {226, 138, 138} +"varsubsetneqq", 3, {226, 171, 139} +"varsupsetneq", 3, {226, 138, 139} +"varsupsetneqq", 3, {226, 171, 140} +"vartheta", 2, {207, 145} +"vartriangleleft", 3, {226, 138, 178} +"vartriangleright", 3, {226, 138, 179} +"vBar", 3, {226, 171, 168} +"Vbar", 3, {226, 171, 171} +"vBarv", 3, {226, 171, 169} +"Vcy", 2, {208, 146} +"vcy", 2, {208, 178} +"vdash", 3, {226, 138, 162} +"vDash", 3, {226, 138, 168} +"Vdash", 3, {226, 138, 169} +"VDash", 3, {226, 138, 171} +"Vdashl", 3, {226, 171, 166} +"veebar", 3, {226, 138, 187} +"vee", 3, {226, 136, 168} +"Vee", 3, {226, 139, 129} +"veeeq", 3, {226, 137, 154} +"vellip", 3, {226, 139, 174} +"verbar", 1, {124} +"Verbar", 3, {226, 128, 150} +"vert", 1, {124} +"Vert", 3, {226, 128, 150} +"VerticalBar", 3, {226, 136, 163} +"VerticalLine", 1, {124} +"VerticalSeparator", 3, {226, 157, 152} +"VerticalTilde", 3, {226, 137, 128} +"VeryThinSpace", 3, {226, 128, 138} +"Vfr", 4, {240, 157, 148, 153} +"vfr", 4, {240, 157, 148, 179} +"vltri", 3, {226, 138, 178} +"vnsub", 3, {226, 138, 130} +"vnsup", 3, {226, 138, 131} +"Vopf", 4, {240, 157, 149, 141} +"vopf", 4, {240, 157, 149, 167} +"vprop", 3, {226, 136, 157} +"vrtri", 3, {226, 138, 179} +"Vscr", 4, {240, 157, 146, 177} +"vscr", 4, {240, 157, 147, 139} +"vsubnE", 3, {226, 171, 139} +"vsubne", 3, {226, 138, 138} +"vsupnE", 3, {226, 171, 140} +"vsupne", 3, {226, 138, 139} +"Vvdash", 3, {226, 138, 170} +"vzigzag", 3, {226, 166, 154} +"Wcirc", 2, {197, 180} +"wcirc", 2, {197, 181} +"wedbar", 3, {226, 169, 159} +"wedge", 3, {226, 136, 167} +"Wedge", 3, {226, 139, 128} +"wedgeq", 3, {226, 137, 153} +"weierp", 3, {226, 132, 152} +"Wfr", 4, {240, 157, 148, 154} +"wfr", 4, {240, 157, 148, 180} +"Wopf", 4, {240, 157, 149, 142} +"wopf", 4, {240, 157, 149, 168} +"wp", 3, {226, 132, 152} +"wr", 3, {226, 137, 128} +"wreath", 3, {226, 137, 128} +"Wscr", 4, {240, 157, 146, 178} +"wscr", 4, {240, 157, 147, 140} +"xcap", 3, {226, 139, 130} +"xcirc", 3, {226, 151, 175} +"xcup", 3, {226, 139, 131} +"xdtri", 3, {226, 150, 189} +"Xfr", 4, {240, 157, 148, 155} +"xfr", 4, {240, 157, 148, 181} +"xharr", 3, {226, 159, 183} +"xhArr", 3, {226, 159, 186} +"Xi", 2, {206, 158} +"xi", 2, {206, 190} +"xlarr", 3, {226, 159, 181} +"xlArr", 3, {226, 159, 184} +"xmap", 3, {226, 159, 188} +"xnis", 3, {226, 139, 187} +"xodot", 3, {226, 168, 128} +"Xopf", 4, {240, 157, 149, 143} +"xopf", 4, {240, 157, 149, 169} +"xoplus", 3, {226, 168, 129} +"xotime", 3, {226, 168, 130} +"xrarr", 3, {226, 159, 182} +"xrArr", 3, {226, 159, 185} +"Xscr", 4, {240, 157, 146, 179} +"xscr", 4, {240, 157, 147, 141} +"xsqcup", 3, {226, 168, 134} +"xuplus", 3, {226, 168, 132} +"xutri", 3, {226, 150, 179} +"xvee", 3, {226, 139, 129} +"xwedge", 3, {226, 139, 128} +"Yacute", 2, {195, 157} +"yacute", 2, {195, 189} +"YAcy", 2, {208, 175} +"yacy", 2, {209, 143} +"Ycirc", 2, {197, 182} +"ycirc", 2, {197, 183} +"Ycy", 2, {208, 171} +"ycy", 2, {209, 139} +"yen", 2, {194, 165} +"Yfr", 4, {240, 157, 148, 156} +"yfr", 4, {240, 157, 148, 182} +"YIcy", 2, {208, 135} +"yicy", 2, {209, 151} +"Yopf", 4, {240, 157, 149, 144} +"yopf", 4, {240, 157, 149, 170} +"Yscr", 4, {240, 157, 146, 180} +"yscr", 4, {240, 157, 147, 142} +"YUcy", 2, {208, 174} +"yucy", 2, {209, 142} +"yuml", 2, {195, 191} +"Yuml", 2, {197, 184} +"Zacute", 2, {197, 185} +"zacute", 2, {197, 186} +"Zcaron", 2, {197, 189} +"zcaron", 2, {197, 190} +"Zcy", 2, {208, 151} +"zcy", 2, {208, 183} +"Zdot", 2, {197, 187} +"zdot", 2, {197, 188} +"zeetrf", 3, {226, 132, 168} +"ZeroWidthSpace", 3, {226, 128, 139} +"Zeta", 2, {206, 150} +"zeta", 2, {206, 182} +"zfr", 4, {240, 157, 148, 183} +"Zfr", 3, {226, 132, 168} +"ZHcy", 2, {208, 150} +"zhcy", 2, {208, 182} +"zigrarr", 3, {226, 135, 157} +"zopf", 4, {240, 157, 149, 171} +"Zopf", 3, {226, 132, 164} +"Zscr", 4, {240, 157, 146, 181} +"zscr", 4, {240, 157, 147, 143} +"zwj", 3, {226, 128, 141} +"zwnj", 3, {226, 128, 140} diff --git a/src/html/html_unescape.h b/src/html/html_unescape.h new file mode 100644 index 0000000..5d12662 --- /dev/null +++ b/src/html/html_unescape.h @@ -0,0 +1,9746 @@ +/* C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -I -t -N find_entity -H hash_entity -K entity -C -l --null-strings -m5 src/html/html_unescape.gperf */ +/* Computed positions: -k'1-7,10,12,$' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 1 "src/html/html_unescape.gperf" +struct html_ent { + const char *entity; + unsigned int utf8_len; + unsigned char utf8[4]; +}; +#include + +#define TOTAL_KEYWORDS 2125 +#define MIN_WORD_LENGTH 2 +#define MAX_WORD_LENGTH 31 +#define MIN_HASH_VALUE 39 +#define MAX_HASH_VALUE 16000 +/* maximum key range = 15962, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +hash_entity (str, len) + register const char *str; + register unsigned int len; +{ + static const unsigned short asso_values[] = + { + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 2, + 3, 7, 2, 4, 8, 16001, 10, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 1890, 1538, 220, 165, 1045, + 535, 1971, 1187, 1262, 35, 126, 201, 133, 350, 1487, + 1965, 3, 478, 134, 8, 147, 73, 41, 23, 212, + 9, 16001, 2, 16001, 2, 16001, 16001, 4154, 29, 3168, + 429, 10, 146, 1925, 2307, 280, 1313, 1924, 4, 651, + 27, 1031, 65, 176, 2, 6, 17, 15, 107, 482, + 3207, 3865, 757, 131, 178, 4, 4, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, + 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001, 16001 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[11]]; + /*FALLTHROUGH*/ + case 11: + case 10: + hval += asso_values[(unsigned char)str[9]]; + /*FALLTHROUGH*/ + case 9: + case 8: + case 7: + hval += asso_values[(unsigned char)str[6]]; + /*FALLTHROUGH*/ + case 6: + hval += asso_values[(unsigned char)str[5]]; + /*FALLTHROUGH*/ + case 5: + hval += asso_values[(unsigned char)str[4]+1]; + /*FALLTHROUGH*/ + case 4: + hval += asso_values[(unsigned char)str[3]+3]; + /*FALLTHROUGH*/ + case 3: + hval += asso_values[(unsigned char)str[2]+1]; + /*FALLTHROUGH*/ + case 2: + hval += asso_values[(unsigned char)str[1]+4]; + /*FALLTHROUGH*/ + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval + asso_values[(unsigned char)str[len - 1]]; +} + +#ifdef __GNUC__ +__inline +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct html_ent * +find_entity (str, len) + register const char *str; + register unsigned int len; +{ + static const unsigned char lengthtable[] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 6, 0, 6, 5, 0, 5, 3, 4, + 3, 4, 0, 4, 0, 2, 5, 4, 0, 0, 0, 2, 0, 7, + 0, 7, 3, 0, 5, 0, 0, 0, 0, 0, 4, 0, 0, 6, + 0, 0, 0, 3, 6, 0, 4, 0, 0, 0, 0, 6, 4, 5, + 0, 0, 0, 5, 0, 5, 0, 6, 0, 0, 0, 4, 5, 5, + 5, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, + 0, 0, 0, 3, 4, 0, 3, 0, 0, 5, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 0, + 5, 0, 5, 6, 0, 6, 5, 0, 2, 5, 0, 5, 0, 0, + 0, 0, 4, 0, 0, 0, 3, 0, 3, 5, 0, 0, 5, 0, + 0, 0, 6, 0, 10, 0, 4, 0, 0, 5, 3, 5, 0, 0, + 0, 0, 0, 0, 0, 5, 0, 3, 0, 0, 0, 0, 6, 6, + 0, 6, 0, 0, 0, 0, 6, 0, 6, 0, 2, 0, 0, 0, + 4, 7, 0, 7, 0, 5, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 4, 0, 4, 6, 0, 3, 0, 0, 0, 0, 0, 0, 4, + 4, 3, 0, 4, 0, 0, 2, 0, 0, 0, 4, 0, 4, 0, + 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 2, 0, 0, 0, 5, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 3, 2, 4, 0, 6, 0, 0, 3, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 4, 0, 0, 0, + 0, 4, 6, 0, 0, 0, 5, 5, 5, 0, 13, 0, 0, 4, + 0, 0, 5, 0, 4, 4, 5, 17, 18, 0, 0, 0, 0, 0, + 5, 0, 0, 17, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, + 5, 5, 0, 0, 0, 8, 0, 0, 0, 3, 0, 0, 6, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 5, 6, 0, 0, + 0, 4, 0, 0, 5, 0, 6, 6, 6, 6, 6, 6, 6, 0, + 0, 6, 0, 6, 0, 6, 6, 6, 6, 6, 6, 0, 0, 0, + 6, 0, 6, 3, 4, 0, 0, 4, 3, 5, 0, 0, 3, 0, + 0, 0, 11, 5, 0, 0, 0, 4, 0, 0, 6, 0, 0, 0, + 5, 0, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 0, 0, 5, 3, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 4, 0, 4, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 5, 0, 0, 0, 0, + 3, 6, 0, 0, 0, 0, 0, 8, 8, 0, 0, 0, 4, 6, + 0, 0, 8, 0, 8, 0, 2, 0, 0, 0, 0, 4, 0, 0, + 0, 4, 0, 6, 0, 0, 0, 0, 6, 0, 4, 0, 0, 0, + 0, 6, 0, 5, 6, 2, 5, 8, 5, 0, 0, 4, 0, 4, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 9, 0, 4, 4, + 4, 0, 4, 6, 4, 4, 4, 0, 0, 0, 5, 4, 5, 4, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 4, 5, 4, + 5, 0, 0, 4, 0, 5, 0, 0, 0, 4, 0, 0, 0, 0, + 4, 4, 0, 5, 0, 0, 11, 0, 0, 6, 0, 0, 3, 0, + 0, 0, 0, 6, 0, 4, 0, 0, 4, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 7, 4, 4, 0, 7, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 3, 8, 4, 0, 0, 0, 5, 0, 6, 0, + 0, 0, 0, 6, 0, 4, 0, 0, 0, 5, 0, 6, 0, 0, + 0, 5, 5, 0, 0, 3, 6, 2, 0, 0, 4, 0, 0, 7, + 0, 4, 0, 4, 4, 4, 3, 5, 0, 0, 0, 0, 0, 0, + 6, 0, 4, 4, 0, 0, 0, 12, 13, 0, 0, 6, 8, 0, + 2, 0, 0, 17, 0, 0, 0, 4, 0, 5, 0, 7, 0, 5, + 0, 0, 0, 5, 4, 5, 0, 0, 3, 0, 0, 0, 5, 0, + 5, 12, 13, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 0, 0, 7, 0, 0, 6, 6, 6, 0, 4, 0, + 0, 0, 0, 17, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 6, 9, 0, 0, + 0, 9, 0, 0, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19, 0, 5, 0, 0, 17, 0, 0, + 14, 0, 0, 0, 0, 12, 4, 0, 0, 0, 4, 0, 2, 0, + 4, 0, 6, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, + 4, 0, 4, 4, 4, 0, 0, 0, 0, 4, 0, 4, 0, 4, + 9, 0, 0, 4, 2, 0, 0, 4, 2, 4, 4, 0, 0, 0, + 0, 4, 6, 0, 0, 6, 9, 4, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 6, 0, 0, + 0, 0, 6, 4, 6, 4, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 9, 0, 0, 4, 0, 0, 0, 0, 0, + 7, 4, 4, 7, 0, 7, 5, 0, 0, 6, 4, 4, 4, 0, + 4, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 4, 4, 6, 0, 0, 0, 3, 5, 3, + 5, 11, 4, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 0, + 7, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 3, 5, 4, + 0, 0, 0, 5, 0, 6, 9, 7, 2, 0, 4, 0, 0, 4, + 0, 0, 0, 0, 4, 5, 6, 0, 0, 0, 0, 9, 10, 0, + 0, 0, 5, 0, 0, 0, 0, 11, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 4, 8, 6, 0, 0, 0, 0, 0, 8, 0, 0, + 0, 0, 0, 0, 0, 5, 6, 0, 0, 0, 13, 5, 5, 6, + 0, 0, 0, 0, 2, 0, 0, 0, 4, 2, 4, 0, 0, 6, + 4, 0, 4, 0, 0, 0, 4, 0, 21, 0, 0, 0, 6, 0, + 3, 0, 0, 0, 6, 6, 0, 3, 13, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 7, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 4, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 7, 3, 0, 0, + 0, 0, 0, 0, 0, 7, 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, + 3, 15, 3, 3, 3, 0, 0, 0, 3, 3, 6, 3, 6, 0, + 0, 0, 0, 3, 0, 0, 4, 3, 0, 3, 0, 12, 0, 0, + 0, 3, 0, 4, 0, 0, 0, 3, 0, 12, 0, 4, 5, 0, + 9, 0, 0, 7, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 5, 0, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, + 0, 5, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 5, + 0, 3, 3, 0, 0, 6, 0, 0, 0, 0, 0, 4, 0, 0, + 3, 3, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 3, 7, 0, 0, 8, 0, 0, 0, 0, + 0, 0, 3, 4, 0, 6, 0, 0, 0, 15, 0, 0, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 2, 0, 0, 0, 0, 9, 3, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 7, 3, 24, 0, 0, + 0, 0, 5, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 7, 4, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 3, 3, + 0, 4, 0, 7, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 5, 2, 0, 0, 0, 6, 0, 3, 8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 9, 5, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 15, 7, 8, 4, 0, 5, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 4, 4, 5, 0, 0, 0, 0, 6, 14, 3, + 15, 0, 6, 0, 0, 0, 3, 0, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 5, 16, 0, 5, 10, 0, 0, 0, + 5, 7, 0, 5, 0, 0, 6, 0, 3, 0, 0, 11, 5, 0, + 0, 4, 5, 0, 0, 5, 0, 0, 3, 0, 0, 0, 0, 8, + 0, 0, 0, 5, 0, 0, 0, 6, 3, 0, 0, 0, 0, 0, + 5, 0, 0, 3, 3, 3, 0, 0, 0, 6, 0, 0, 5, 6, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 11, 0, 6, 0, 6, 0, 0, 13, 0, 0, 7, + 0, 0, 0, 0, 7, 0, 6, 4, 5, 0, 3, 0, 0, 5, + 3, 0, 0, 0, 0, 0, 6, 0, 0, 4, 0, 0, 0, 0, + 3, 6, 5, 0, 0, 0, 0, 11, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 0, 11, 0, 5, 5, 0, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 8, 0, 7, 4, 0, 0, 0, 0, 5, 4, 9, + 0, 0, 5, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 0, 6, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 4, 0, 0, 14, 5, 0, 0, 8, + 0, 0, 0, 20, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 3, 0, 0, 4, 6, 0, 0, 0, 0, 6, 0, 0, 0, 7, + 0, 3, 6, 4, 6, 0, 0, 0, 0, 0, 0, 6, 3, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 11, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 4, + 0, 0, 0, 0, 0, 0, 0, 13, 18, 5, 0, 3, 0, 7, + 0, 4, 0, 0, 0, 4, 0, 0, 10, 11, 0, 0, 0, 6, + 0, 6, 0, 0, 5, 0, 5, 12, 12, 0, 0, 0, 4, 0, + 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, + 14, 0, 0, 0, 2, 4, 8, 4, 0, 3, 0, 0, 7, 0, + 3, 0, 0, 0, 3, 2, 0, 0, 0, 0, 6, 0, 6, 4, + 6, 7, 6, 6, 6, 0, 10, 0, 0, 0, 3, 6, 0, 4, + 0, 0, 0, 0, 0, 4, 0, 6, 6, 0, 4, 0, 0, 0, + 7, 0, 0, 7, 0, 0, 4, 0, 4, 0, 5, 6, 0, 6, + 0, 3, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 8, 14, 0, 3, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 7, 5, 0, 0, 0, 4, 0, 0, 0, + 17, 7, 0, 0, 4, 0, 0, 7, 0, 5, 0, 0, 7, 5, + 0, 0, 4, 0, 7, 2, 20, 0, 0, 0, 0, 13, 0, 0, + 0, 0, 6, 0, 7, 3, 5, 4, 0, 0, 0, 0, 5, 5, + 0, 0, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 5, 0, 0, 6, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 4, 9, 0, 5, 12, 0, 0, 0, 0, 5, 0, 5, + 4, 0, 0, 0, 9, 0, 0, 0, 10, 10, 0, 0, 4, 6, + 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 6, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 6, 6, 0, 3, 0, 0, 0, + 7, 0, 0, 0, 0, 7, 4, 0, 0, 0, 0, 0, 4, 0, + 9, 0, 0, 3, 0, 0, 0, 7, 0, 4, 0, 0, 5, 6, + 0, 0, 6, 3, 5, 4, 0, 0, 0, 0, 0, 6, 0, 5, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 5, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 6, 0, 0, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 6, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 0, 6, 0, 6, 0, 0, 6, + 0, 0, 18, 0, 6, 0, 20, 15, 0, 0, 4, 4, 0, 0, + 0, 6, 0, 0, 0, 3, 0, 0, 0, 0, 0, 5, 4, 4, + 0, 7, 0, 6, 0, 4, 0, 5, 0, 0, 0, 0, 5, 0, + 0, 0, 4, 4, 0, 0, 0, 0, 4, 0, 4, 0, 11, 0, + 20, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 0, 0, 8, 0, 0, 0, 6, 0, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 4, 0, 0, 3, 0, 0, 6, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 9, 0, 0, 0, 5, + 0, 0, 0, 5, 0, 3, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 3, 0, 0, 17, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 9, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 7, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 14, 0, + 0, 11, 0, 6, 0, 6, 0, 7, 5, 0, 0, 0, 6, 12, + 12, 0, 0, 0, 0, 16, 0, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 7, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 6, 0, 14, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 5, 0, 5, 0, 0, 0, 0, 0, 11, 6, 6, 3, 0, 0, + 0, 0, 7, 0, 6, 0, 6, 6, 4, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, + 4, 4, 0, 0, 0, 0, 3, 3, 6, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0, 4, 6, 0, + 4, 4, 0, 0, 0, 0, 13, 0, 4, 0, 0, 0, 0, 4, + 2, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 10, 0, 9, 0, 0, 4, 6, 0, 5, 0, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 8, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 12, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, 18, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 7, 0, 0, 0, 0, 5, 0, 5, + 0, 0, 0, 6, 0, 0, 5, 0, 0, 6, 0, 6, 0, 0, + 13, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 6, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 6, 15, 0, 0, 7, 0, 3, 0, 3, 0, 0, 0, + 9, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 15, + 0, 0, 0, 6, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 9, 4, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 2, 15, 0, 0, + 0, 5, 0, 5, 0, 4, 0, 0, 0, 0, 0, 0, 16, 0, + 3, 3, 10, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 4, + 5, 4, 0, 0, 6, 0, 5, 4, 0, 5, 5, 3, 5, 0, + 4, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 3, 0, 0, 6, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 8, 6, 0, 0, 0, 0, 0, 0, 0, 5, 16, 0, + 5, 7, 0, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 0, 7, 0, 0, 5, 0, 0, + 0, 0, 6, 0, 5, 4, 5, 0, 5, 5, 0, 0, 0, 0, + 5, 2, 6, 4, 0, 5, 0, 0, 5, 0, 4, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 3, 5, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 6, 5, 0, 0, 4, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 4, 2, 6, 0, 6, 3, 3, 0, 0, + 3, 0, 4, 0, 6, 0, 3, 0, 0, 6, 0, 5, 31, 0, + 0, 0, 0, 0, 0, 0, 3, 6, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 6, + 0, 8, 0, 5, 4, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 5, 0, 0, 5, 0, + 0, 0, 19, 0, 0, 0, 0, 24, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 5, + 0, 0, 0, 6, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, + 0, 16, 5, 0, 0, 3, 4, 4, 0, 5, 4, 5, 0, 0, + 0, 13, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 6, 0, 3, + 0, 7, 0, 10, 0, 0, 0, 0, 6, 0, 6, 0, 0, 13, + 0, 0, 0, 5, 0, 8, 0, 6, 0, 6, 8, 6, 0, 0, + 6, 6, 0, 10, 0, 8, 6, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 11, 0, 0, 0, 6, 0, 0, 0, + 0, 7, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 0, 0, 17, 6, 0, 0, 0, 0, 0, 16, 0, 0, + 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 0, 7, 0, + 14, 7, 6, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 10, 4, 14, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 4, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 6, 3, 8, 4, 6, 6, 0, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 6, 0, 4, 0, 2, 0, 20, 21, 0, 0, 2, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 0, 14, 4, 6, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 5, 0, 0, + 4, 6, 0, 2, 7, 0, 6, 5, 0, 8, 0, 0, 5, 0, + 4, 0, 0, 0, 5, 0, 4, 15, 5, 0, 4, 6, 0, 0, + 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 17, 5, 0, + 0, 0, 9, 6, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 7, 5, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 12, 0, 0, 0, 6, 0, 0, 0, 0, 10, 3, 0, 0, + 0, 4, 0, 5, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 9, 0, 6, 0, 6, 0, 0, 0, 0, 19, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 5, 0, 6, 3, 6, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, 2, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 0, 6, 0, 6, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 17, 0, + 0, 7, 0, 0, 2, 6, 2, 0, 0, 0, 2, 0, 0, 0, + 0, 3, 8, 0, 0, 3, 0, 5, 0, 5, 6, 0, 0, 0, + 0, 18, 0, 0, 0, 0, 5, 0, 7, 0, 0, 9, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 4, 0, 0, 4, 0, 9, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, 0, 4, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 5, 0, 5, 6, + 0, 0, 0, 3, 3, 5, 0, 0, 0, 0, 6, 0, 0, 0, + 6, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 4, + 6, 13, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 8, 6, 8, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 12, 0, 6, 0, 0, 0, 6, 0, 0, + 0, 6, 4, 0, 0, 7, 6, 5, 0, 0, 6, 0, 5, 5, + 5, 0, 0, 0, 9, 0, 0, 0, 0, 0, 5, 0, 6, 8, + 0, 0, 6, 0, 5, 8, 0, 0, 0, 6, 0, 4, 0, 9, + 0, 0, 0, 0, 4, 6, 4, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, + 11, 0, 0, 8, 9, 0, 0, 0, 0, 3, 5, 3, 0, 0, + 0, 0, 6, 4, 0, 0, 0, 9, 4, 3, 0, 2, 0, 0, + 0, 0, 0, 7, 5, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 14, 3, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 10, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 10, 7, + 5, 0, 6, 0, 6, 0, 3, 17, 0, 0, 0, 0, 0, 0, + 20, 0, 14, 4, 0, 0, 0, 0, 0, 0, 19, 6, 6, 0, + 10, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 6, 0, + 0, 3, 0, 0, 0, 4, 5, 0, 0, 4, 0, 5, 0, 0, + 0, 0, 0, 0, 7, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 7, 0, 3, 0, 4, 0, 3, 0, 4, 0, 0, 13, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 6, 0, 0, 0, 0, 0, 7, 0, 13, 0, 0, 15, 0, 0, + 5, 9, 0, 0, 0, 6, 0, 6, 0, 0, 4, 6, 0, 0, + 6, 4, 4, 0, 16, 0, 4, 0, 3, 0, 0, 11, 5, 15, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 0, 0, 5, 0, 5, 4, 0, 0, 4, 0, + 20, 4, 0, 0, 0, 0, 0, 5, 15, 4, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 22, 0, 0, 7, + 8, 0, 4, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 6, 7, 0, 0, 0, 0, 6, 0, 6, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 4, 0, 5, 0, 12, 15, 6, 0, + 13, 0, 4, 0, 5, 4, 6, 0, 0, 0, 0, 4, 0, 0, + 4, 3, 5, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 9, 0, 0, 20, 0, 4, 10, + 0, 0, 0, 0, 4, 0, 5, 0, 0, 8, 6, 0, 5, 4, + 0, 0, 3, 0, 4, 0, 0, 6, 6, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 9, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 17, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 14, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 14, 0, 0, 0, 0, 0, 0, 5, 6, 0, 5, 0, 0, + 0, 0, 0, 0, 5, 0, 8, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 16, 15, 4, 0, 0, 11, 0, 0, 0, 8, 0, 0, + 0, 0, 0, 0, 0, 2, 0, 5, 0, 10, 0, 0, 5, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, + 5, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 6, 5, 4, 0, 0, 0, + 0, 5, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 6, 0, + 0, 0, 0, 2, 4, 5, 0, 0, 0, 8, 0, 0, 3, 0, + 8, 0, 0, 4, 18, 0, 0, 0, 0, 4, 5, 0, 0, 0, + 16, 0, 0, 0, 0, 7, 0, 2, 3, 5, 0, 0, 5, 0, + 4, 4, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 14, 0, 0, 0, 0, 5, 0, 0, 6, 0, 6, 0, + 5, 0, 5, 0, 5, 15, 0, 0, 8, 17, 12, 0, 0, 0, + 0, 0, 6, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 5, 0, 0, 20, 0, 0, 0, 0, 0, + 11, 0, 5, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 13, + 0, 0, 0, 0, 0, 6, 0, 6, 0, 6, 0, 6, 0, 5, + 8, 0, 0, 0, 0, 0, 6, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 0, 0, + 0, 13, 0, 0, 0, 0, 0, 8, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 16, 0, 14, 0, 18, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 16, 0, 0, 0, 0, 0, + 0, 14, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 5, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 8, 17, 0, 0, 0, 5, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, 9, 0, 15, 0, 5, 0, 5, 0, + 0, 0, 0, 0, 0, 6, 5, 0, 0, 0, 0, 6, 4, 0, + 0, 9, 0, 0, 0, 0, 0, 6, 0, 6, 0, 0, 8, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 6, 2, 0, 0, 6, 0, 12, 6, 0, 0, 0, 16, 0, 0, + 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 14, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 10, 8, 0, 5, 0, 0, 6, + 0, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 5, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 14, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 5, 0, 9, 0, + 0, 0, 5, 0, 0, 0, 0, 4, 6, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 21, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 6, 0, 0, 0, 0, 0, 3, 5, 0, + 0, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 2, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 5, 0, 0, 0, 0, 0, 0, 0, 0, 8, 5, 14, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 5, 6, 0, 0, 4, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 13, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 12, 0, 0, 0, 18, 10, 0, 0, 18, 0, 7, 0, 0, + 0, 6, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 0, 5, 0, 0, 0, 0, 6, 0, 0, 5, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 5, 0, 12, 4, 12, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 4, 0, 0, 0, 0, + 7, 5, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 5, 0, 0, 0, 5, 6, 7, 7, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 8, 0, 0, 0, 0, 5, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 16, 0, 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 4, 6, 0, 0, 0, 5, 0, 0, 0, 8, 0, 0, 0, 0, + 0, 17, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 0, 17, 0, 5, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 8, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 8, 4, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 4, 0, 4, 6, 8, 0, 5, 0, + 0, 4, 4, 0, 5, 4, 5, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 5, 0, 0, 18, 0, 5, 0, 0, 0, 19, 0, 0, + 8, 0, 14, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11, 0, 5, 13, 0, 0, 0, 7, + 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 3, 0, 0, + 4, 0, 6, 13, 0, 8, 0, 5, 0, 0, 0, 5, 0, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, + 3, 0, 3, 0, 3, 0, 3, 3, 3, 4, 0, 4, 0, 3, + 5, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, + 4, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 5, + 0, 18, 0, 0, 15, 7, 0, 3, 0, 0, 6, 5, 0, 5, + 0, 3, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 7, 10, 0, 0, 0, 0, 0, 4, 0, 0, 9, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 12, 0, 0, 0, 5, 6, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 17, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 0, 6, 5, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 5, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 15, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 0, 9, 6, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 7, 0, 0, 20, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 5, 0, 0, + 0, 3, 0, 0, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 14, 0, 0, 0, 0, 5, 6, 0, 0, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 8, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 0, 0, 6, 8, 0, 0, 17, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 13, 0, 0, 0, 0, 7, 0, 0, 3, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 7, 5, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 6, 11, 19, 0, + 0, 5, 17, 0, 0, 0, 0, 0, 16, 5, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, + 7, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 7, 0, 7, 8, 0, 0, 0, 0, 0, 13, 0, 16, 5, 4, + 0, 0, 0, 6, 0, 0, 5, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 9, 6, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, + 9, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 7, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 6, 0, 0, 0, + 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 4, 10, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 10, 0, 10, 0, + 0, 0, 21, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, + 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 11, 0, 20, 0, 3, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 3, 0, 0, 0, 0, 5, 14, 5, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 5, 0, + 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 4, 0, 0, 0, 0, 0, 0, 4, 0, 4, 0, 0, 0, + 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 5, 0, 0, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 7, 0, + 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 5, 0, + 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 0, 0, 0, 0, 0, 16, 5, 0, 15, 0, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 0, 0, 0, 6, 0, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 11, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5, 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 8, 0, 0, + 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 4, + 0, 0, 11, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 18, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 18, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 15, 0, 0, + 0, 0, 5, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 0, 0, 12, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 13, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 0, 0, 18, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 15, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 11, 0, + 0, 5, 0, 0, 0, 7, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 21, 16, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 10, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, + 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 + }; + static const struct html_ent wordlist[] = + { + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1502 "src/html/html_unescape.gperf" + {"rarr", 3, {226, 134, 146}}, + {(char*)0}, +#line 834 "src/html/html_unescape.gperf" + {"larr", 3, {226, 134, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 845 "src/html/html_unescape.gperf" + {"lat", 3, {226, 170, 171}}, + {(char*)0}, {(char*)0}, +#line 1904 "src/html/html_unescape.gperf" + {"uarr", 3, {226, 134, 145}}, + {(char*)0}, {(char*)0}, +#line 1236 "src/html/html_unescape.gperf" + {"npr", 3, {226, 138, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1511 "src/html/html_unescape.gperf" + {"rarrtl", 3, {226, 134, 163}}, + {(char*)0}, +#line 842 "src/html/html_unescape.gperf" + {"larrtl", 3, {226, 134, 162}}, +#line 1602 "src/html/html_unescape.gperf" + {"roarr", 3, {226, 135, 190}}, + {(char*)0}, +#line 964 "src/html/html_unescape.gperf" + {"loarr", 3, {226, 135, 189}}, +#line 1169 "src/html/html_unescape.gperf" + {"not", 2, {194, 172}}, +#line 1610 "src/html/html_unescape.gperf" + {"rpar", 1, {41}}, +#line 147 "src/html/html_unescape.gperf" + {"bot", 3, {226, 138, 165}}, +#line 990 "src/html/html_unescape.gperf" + {"lpar", 1, {40}}, + {(char*)0}, +#line 1716 "src/html/html_unescape.gperf" + {"spar", 3, {226, 136, 165}}, + {(char*)0}, +#line 946 "src/html/html_unescape.gperf" + {"ll", 3, {226, 137, 170}}, +#line 1927 "src/html/html_unescape.gperf" + {"uharr", 3, {226, 134, 190}}, +#line 506 "src/html/html_unescape.gperf" + {"epar", 3, {226, 139, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 483 "src/html/html_unescape.gperf" + {"el", 3, {226, 170, 153}}, + {(char*)0}, +#line 1608 "src/html/html_unescape.gperf" + {"rotimes", 3, {226, 168, 181}}, + {(char*)0}, +#line 982 "src/html/html_unescape.gperf" + {"lotimes", 3, {226, 168, 180}}, +#line 1389 "src/html/html_unescape.gperf" + {"par", 3, {226, 136, 165}}, + {(char*)0}, +#line 1133 "src/html/html_unescape.gperf" + {"nharr", 3, {226, 134, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1232 "src/html/html_unescape.gperf" + {"npar", 3, {226, 136, 166}}, + {(char*)0}, {(char*)0}, +#line 1873 "src/html/html_unescape.gperf" + {"tprime", 3, {226, 128, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 487 "src/html/html_unescape.gperf" + {"els", 3, {226, 170, 149}}, +#line 507 "src/html/html_unescape.gperf" + {"eparsl", 3, {226, 167, 163}}, + {(char*)0}, +#line 501 "src/html/html_unescape.gperf" + {"ensp", 3, {226, 128, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 194 "src/html/html_unescape.gperf" + {"bprime", 3, {226, 128, 181}}, +#line 956 "src/html/html_unescape.gperf" + {"lnap", 3, {226, 170, 137}}, +#line 138 "src/html/html_unescape.gperf" + {"blk14", 3, {226, 150, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 137 "src/html/html_unescape.gperf" + {"blk12", 3, {226, 150, 146}}, + {(char*)0}, +#line 139 "src/html/html_unescape.gperf" + {"blk34", 3, {226, 150, 147}}, + {(char*)0}, +#line 1233 "src/html/html_unescape.gperf" + {"nparsl", 3, {226, 171, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1144 "src/html/html_unescape.gperf" + {"nldr", 3, {226, 128, 165}}, +#line 1595 "src/html/html_unescape.gperf" + {"rlarr", 3, {226, 135, 132}}, +#line 1234 "src/html/html_unescape.gperf" + {"npart", 3, {226, 136, 130}}, +#line 945 "src/html/html_unescape.gperf" + {"llarr", 3, {226, 135, 135}}, +#line 1159 "src/html/html_unescape.gperf" + {"nlt", 3, {226, 137, 174}}, +#line 1697 "src/html/html_unescape.gperf" + {"slarr", 3, {226, 134, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1231 "src/html/html_unescape.gperf" + {"nparallel", 3, {226, 136, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1826 "src/html/html_unescape.gperf" + {"Tau", 2, {206, 164}}, +#line 1992 "src/html/html_unescape.gperf" + {"varr", 3, {226, 134, 149}}, + {(char*)0}, +#line 1739 "src/html/html_unescape.gperf" + {"squ", 3, {226, 150, 161}}, + {(char*)0}, {(char*)0}, +#line 1142 "src/html/html_unescape.gperf" + {"nlarr", 3, {226, 134, 154}}, + {(char*)0}, {(char*)0}, +#line 1827 "src/html/html_unescape.gperf" + {"tau", 2, {207, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 958 "src/html/html_unescape.gperf" + {"lne", 3, {226, 170, 135}}, +#line 1613 "src/html/html_unescape.gperf" + {"rrarr", 3, {226, 135, 137}}, + {(char*)0}, +#line 992 "src/html/html_unescape.gperf" + {"lrarr", 3, {226, 135, 134}}, + {(char*)0}, +#line 1741 "src/html/html_unescape.gperf" + {"srarr", 3, {226, 134, 146}}, +#line 1557 "src/html/html_unescape.gperf" + {"rharul", 3, {226, 165, 172}}, + {(char*)0}, +#line 941 "src/html/html_unescape.gperf" + {"lharul", 3, {226, 165, 170}}, +#line 526 "src/html/html_unescape.gperf" + {"erarr", 3, {226, 165, 177}}, + {(char*)0}, +#line 1434 "src/html/html_unescape.gperf" + {"pr", 3, {226, 137, 186}}, +#line 1556 "src/html/html_unescape.gperf" + {"rharu", 3, {226, 135, 128}}, + {(char*)0}, +#line 940 "src/html/html_unescape.gperf" + {"lharu", 3, {226, 134, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1905 "src/html/html_unescape.gperf" + {"Uarr", 3, {226, 134, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1129 "src/html/html_unescape.gperf" + {"nGt", 3, {226, 137, 171}}, + {(char*)0}, +#line 141 "src/html/html_unescape.gperf" + {"bne", 1, {61}}, +#line 1242 "src/html/html_unescape.gperf" + {"nrarr", 3, {226, 134, 155}}, + {(char*)0}, {(char*)0}, +#line 1819 "src/html/html_unescape.gperf" + {"swarr", 3, {226, 134, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1498 "src/html/html_unescape.gperf" + {"rarrap", 3, {226, 165, 181}}, + {(char*)0}, +#line 1967 "src/html/html_unescape.gperf" + {"upuparrows", 3, {226, 135, 136}}, + {(char*)0}, +#line 345 "src/html/html_unescape.gperf" + {"Darr", 3, {226, 134, 161}}, + {(char*)0}, {(char*)0}, +#line 1517 "src/html/html_unescape.gperf" + {"rbarr", 3, {226, 164, 141}}, +#line 398 "src/html/html_unescape.gperf" + {"Dot", 2, {194, 168}}, +#line 848 "src/html/html_unescape.gperf" + {"lbarr", 3, {226, 164, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1307 "src/html/html_unescape.gperf" + {"nwarr", 3, {226, 134, 150}}, + {(char*)0}, +#line 1704 "src/html/html_unescape.gperf" + {"smt", 3, {226, 170, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 497 "src/html/html_unescape.gperf" + {"emsp14", 3, {226, 128, 133}}, +#line 1508 "src/html/html_unescape.gperf" + {"rarrpl", 3, {226, 165, 133}}, + {(char*)0}, +#line 840 "src/html/html_unescape.gperf" + {"larrpl", 3, {226, 164, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1406 "src/html/html_unescape.gperf" + {"phmmat", 3, {226, 132, 179}}, + {(char*)0}, +#line 496 "src/html/html_unescape.gperf" + {"emsp13", 3, {226, 128, 132}}, + {(char*)0}, +#line 1014 "src/html/html_unescape.gperf" + {"LT", 1, {60}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 835 "src/html/html_unescape.gperf" + {"Larr", 3, {226, 134, 158}}, +#line 1525 "src/html/html_unescape.gperf" + {"rbrkslu", 3, {226, 166, 144}}, + {(char*)0}, +#line 855 "src/html/html_unescape.gperf" + {"lbrkslu", 3, {226, 166, 141}}, + {(char*)0}, +#line 1082 "src/html/html_unescape.gperf" + {"napos", 2, {197, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1146 "src/html/html_unescape.gperf" + {"nle", 3, {226, 137, 176}}, + {(char*)0}, +#line 1554 "src/html/html_unescape.gperf" + {"rHar", 3, {226, 165, 164}}, + {(char*)0}, +#line 938 "src/html/html_unescape.gperf" + {"lHar", 3, {226, 165, 162}}, +#line 1477 "src/html/html_unescape.gperf" + {"qprime", 3, {226, 129, 151}}, + {(char*)0}, +#line 829 "src/html/html_unescape.gperf" + {"lap", 3, {226, 170, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1087 "src/html/html_unescape.gperf" + {"nbsp", 2, {194, 160}}, +#line 1925 "src/html/html_unescape.gperf" + {"uHar", 3, {226, 165, 163}}, +#line 1868 "src/html/html_unescape.gperf" + {"top", 3, {226, 138, 164}}, + {(char*)0}, +#line 2004 "src/html/html_unescape.gperf" + {"Vbar", 3, {226, 171, 171}}, + {(char*)0}, {(char*)0}, +#line 947 "src/html/html_unescape.gperf" + {"Ll", 3, {226, 139, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1432 "src/html/html_unescape.gperf" + {"prap", 3, {226, 170, 183}}, + {(char*)0}, +#line 498 "src/html/html_unescape.gperf" + {"emsp", 3, {226, 128, 131}}, + {(char*)0}, {(char*)0}, +#line 1079 "src/html/html_unescape.gperf" + {"nap", 3, {226, 137, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 976 "src/html/html_unescape.gperf" + {"looparrowleft", 3, {226, 134, 171}}, + {(char*)0}, +#line 870 "src/html/html_unescape.gperf" + {"le", 3, {226, 137, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1670 "src/html/html_unescape.gperf" + {"sharp", 3, {226, 153, 175}}, + {(char*)0}, +#line 474 "src/html/html_unescape.gperf" + {"ee", 3, {226, 133, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 914 "src/html/html_unescape.gperf" + {"les", 3, {226, 169, 189}}, +#line 745 "src/html/html_unescape.gperf" + {"in", 3, {226, 136, 136}}, +#line 1461 "src/html/html_unescape.gperf" + {"prop", 3, {226, 136, 157}}, + {(char*)0}, +#line 1866 "src/html/html_unescape.gperf" + {"topbot", 3, {226, 140, 182}}, + {(char*)0}, {(char*)0}, +#line 750 "src/html/html_unescape.gperf" + {"int", 3, {226, 136, 171}}, + {(char*)0}, +#line 1105 "src/html/html_unescape.gperf" + {"ne", 3, {226, 137, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1237 "src/html/html_unescape.gperf" + {"nprcue", 3, {226, 139, 160}}, + {(char*)0}, +#line 1447 "src/html/html_unescape.gperf" + {"pre", 3, {226, 170, 175}}, +#line 509 "src/html/html_unescape.gperf" + {"epsi", 2, {206, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1960 "src/html/html_unescape.gperf" + {"upsi", 2, {207, 133}}, +#line 1839 "src/html/html_unescape.gperf" + {"there4", 3, {226, 136, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1523 "src/html/html_unescape.gperf" + {"rbrke", 3, {226, 166, 140}}, +#line 1658 "src/html/html_unescape.gperf" + {"searr", 3, {226, 134, 152}}, +#line 853 "src/html/html_unescape.gperf" + {"lbrke", 3, {226, 166, 139}}, + {(char*)0}, +#line 132 "src/html/html_unescape.gperf" + {"blacktriangle", 3, {226, 150, 180}}, + {(char*)0}, {(char*)0}, +#line 960 "src/html/html_unescape.gperf" + {"lneq", 3, {226, 170, 135}}, + {(char*)0}, {(char*)0}, +#line 961 "src/html/html_unescape.gperf" + {"lneqq", 3, {226, 137, 168}}, + {(char*)0}, +#line 1418 "src/html/html_unescape.gperf" + {"plus", 1, {43}}, +#line 1154 "src/html/html_unescape.gperf" + {"nles", 3, {226, 169, 189}}, +#line 1106 "src/html/html_unescape.gperf" + {"nedot", 3, {226, 137, 144}}, +#line 134 "src/html/html_unescape.gperf" + {"blacktriangleleft", 3, {226, 151, 130}}, +#line 135 "src/html/html_unescape.gperf" + {"blacktriangleright", 3, {226, 150, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1102 "src/html/html_unescape.gperf" + {"nearr", 3, {226, 134, 151}}, + {(char*)0}, {(char*)0}, +#line 133 "src/html/html_unescape.gperf" + {"blacktriangledown", 3, {226, 150, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1155 "src/html/html_unescape.gperf" + {"nless", 3, {226, 137, 174}}, +#line 490 "src/html/html_unescape.gperf" + {"emacr", 2, {196, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2034 "src/html/html_unescape.gperf" + {"vprop", 3, {226, 136, 157}}, +#line 1934 "src/html/html_unescape.gperf" + {"umacr", 2, {197, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1701 "src/html/html_unescape.gperf" + {"smeparsl", 3, {226, 167, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1033 "src/html/html_unescape.gperf" + {"Map", 3, {226, 164, 133}}, + {(char*)0}, {(char*)0}, +#line 1420 "src/html/html_unescape.gperf" + {"plusdu", 3, {226, 168, 165}}, +#line 1168 "src/html/html_unescape.gperf" + {"Not", 3, {226, 171, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2019 "src/html/html_unescape.gperf" + {"Verbar", 3, {226, 128, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1399 "src/html/html_unescape.gperf" + {"perp", 3, {226, 138, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 561 "src/html/html_unescape.gperf" + {"fltns", 3, {226, 150, 177}}, +#line 1423 "src/html/html_unescape.gperf" + {"plusmn", 2, {194, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1151 "src/html/html_unescape.gperf" + {"nleq", 3, {226, 137, 176}}, + {(char*)0}, {(char*)0}, +#line 1152 "src/html/html_unescape.gperf" + {"nleqq", 3, {226, 137, 166}}, + {(char*)0}, +#line 579 "src/html/html_unescape.gperf" + {"frac34", 2, {194, 190}}, +#line 573 "src/html/html_unescape.gperf" + {"frac14", 2, {194, 188}}, +#line 2018 "src/html/html_unescape.gperf" + {"verbar", 1, {124}}, +#line 571 "src/html/html_unescape.gperf" + {"frac12", 2, {194, 189}}, +#line 580 "src/html/html_unescape.gperf" + {"frac35", 3, {226, 133, 151}}, +#line 574 "src/html/html_unescape.gperf" + {"frac15", 3, {226, 133, 149}}, +#line 582 "src/html/html_unescape.gperf" + {"frac45", 3, {226, 133, 152}}, + {(char*)0}, {(char*)0}, +#line 578 "src/html/html_unescape.gperf" + {"frac25", 3, {226, 133, 150}}, + {(char*)0}, +#line 572 "src/html/html_unescape.gperf" + {"frac13", 3, {226, 133, 147}}, + {(char*)0}, +#line 575 "src/html/html_unescape.gperf" + {"frac16", 3, {226, 133, 153}}, +#line 1466 "src/html/html_unescape.gperf" + {"prurel", 3, {226, 138, 176}}, +#line 577 "src/html/html_unescape.gperf" + {"frac23", 3, {226, 133, 148}}, +#line 581 "src/html/html_unescape.gperf" + {"frac38", 3, {226, 133, 156}}, +#line 576 "src/html/html_unescape.gperf" + {"frac18", 3, {226, 133, 155}}, +#line 583 "src/html/html_unescape.gperf" + {"frac56", 3, {226, 133, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 584 "src/html/html_unescape.gperf" + {"frac58", 3, {226, 133, 157}}, + {(char*)0}, +#line 585 "src/html/html_unescape.gperf" + {"frac78", 3, {226, 133, 158}}, +#line 910 "src/html/html_unescape.gperf" + {"leq", 3, {226, 137, 164}}, +#line 344 "src/html/html_unescape.gperf" + {"darr", 3, {226, 134, 147}}, + {(char*)0}, {(char*)0}, +#line 1961 "src/html/html_unescape.gperf" + {"Upsi", 2, {207, 146}}, +#line 399 "src/html/html_unescape.gperf" + {"dot", 2, {203, 153}}, +#line 1407 "src/html/html_unescape.gperf" + {"phone", 3, {226, 152, 142}}, + {(char*)0}, {(char*)0}, +#line 219 "src/html/html_unescape.gperf" + {"Cap", 3, {226, 139, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 131 "src/html/html_unescape.gperf" + {"blacksquare", 3, {226, 150, 170}}, +#line 1600 "src/html/html_unescape.gperf" + {"rnmid", 3, {226, 171, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 911 "src/html/html_unescape.gperf" + {"leqq", 3, {226, 137, 166}}, + {(char*)0}, {(char*)0}, +#line 749 "src/html/html_unescape.gperf" + {"intcal", 3, {226, 138, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 372 "src/html/html_unescape.gperf" + {"dharr", 3, {226, 135, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1555 "src/html/html_unescape.gperf" + {"rhard", 3, {226, 135, 129}}, + {(char*)0}, +#line 939 "src/html/html_unescape.gperf" + {"lhard", 3, {226, 134, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1421 "src/html/html_unescape.gperf" + {"pluse", 3, {226, 169, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1933 "src/html/html_unescape.gperf" + {"Umacr", 2, {197, 170}}, +#line 2015 "src/html/html_unescape.gperf" + {"Vee", 3, {226, 139, 129}}, + {(char*)0}, {(char*)0}, +#line 1503 "src/html/html_unescape.gperf" + {"Rarr", 3, {226, 134, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 304 "src/html/html_unescape.gperf" + {"Cross", 3, {226, 168, 175}}, + {(char*)0}, +#line 1620 "src/html/html_unescape.gperf" + {"rsqb", 1, {93}}, + {(char*)0}, +#line 1006 "src/html/html_unescape.gperf" + {"lsqb", 1, {91}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1510 "src/html/html_unescape.gperf" + {"Rarrtl", 3, {226, 164, 150}}, + {(char*)0}, {(char*)0}, +#line 530 "src/html/html_unescape.gperf" + {"esdot", 3, {226, 137, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2014 "src/html/html_unescape.gperf" + {"vee", 3, {226, 136, 168}}, +#line 1089 "src/html/html_unescape.gperf" + {"nbumpe", 3, {226, 137, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 948 "src/html/html_unescape.gperf" + {"llcorner", 3, {226, 140, 158}}, +#line 570 "src/html/html_unescape.gperf" + {"fpartint", 3, {226, 168, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1740 "src/html/html_unescape.gperf" + {"squf", 3, {226, 150, 170}}, +#line 1414 "src/html/html_unescape.gperf" + {"plankv", 3, {226, 132, 143}}, + {(char*)0}, {(char*)0}, +#line 525 "src/html/html_unescape.gperf" + {"eqvparsl", 3, {226, 167, 165}}, + {(char*)0}, +#line 1930 "src/html/html_unescape.gperf" + {"ulcorner", 3, {226, 140, 156}}, + {(char*)0}, +#line 2055 "src/html/html_unescape.gperf" + {"wp", 3, {226, 132, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 989 "src/html/html_unescape.gperf" + {"lozf", 3, {226, 167, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 299 "src/html/html_unescape.gperf" + {"COPY", 2, {194, 169}}, + {(char*)0}, +#line 1929 "src/html/html_unescape.gperf" + {"ulcorn", 3, {226, 140, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2013 "src/html/html_unescape.gperf" + {"veebar", 3, {226, 138, 187}}, + {(char*)0}, +#line 1392 "src/html/html_unescape.gperf" + {"part", 3, {226, 136, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1730 "src/html/html_unescape.gperf" + {"square", 3, {226, 150, 161}}, + {(char*)0}, +#line 1088 "src/html/html_unescape.gperf" + {"nbump", 3, {226, 137, 142}}, +#line 108 "src/html/html_unescape.gperf" + {"bernou", 3, {226, 132, 172}}, +#line 2056 "src/html/html_unescape.gperf" + {"wr", 3, {226, 137, 128}}, +#line 1518 "src/html/html_unescape.gperf" + {"rBarr", 3, {226, 164, 143}}, +#line 993 "src/html/html_unescape.gperf" + {"lrcorner", 3, {226, 140, 159}}, +#line 849 "src/html/html_unescape.gperf" + {"lBarr", 3, {226, 164, 142}}, + {(char*)0}, {(char*)0}, +#line 144 "src/html/html_unescape.gperf" + {"bnot", 3, {226, 140, 144}}, + {(char*)0}, +#line 1662 "src/html/html_unescape.gperf" + {"semi", 1, {59}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1969 "src/html/html_unescape.gperf" + {"urcorner", 3, {226, 140, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1218 "src/html/html_unescape.gperf" + {"NotSubset", 3, {226, 138, 130}}, + {(char*)0}, +#line 1605 "src/html/html_unescape.gperf" + {"ropf", 4, {240, 157, 149, 163}}, +#line 1476 "src/html/html_unescape.gperf" + {"Qopf", 3, {226, 132, 154}}, +#line 980 "src/html/html_unescape.gperf" + {"lopf", 4, {240, 157, 149, 157}}, + {(char*)0}, +#line 1713 "src/html/html_unescape.gperf" + {"sopf", 4, {240, 157, 149, 164}}, +#line 1968 "src/html/html_unescape.gperf" + {"urcorn", 3, {226, 140, 157}}, +#line 1869 "src/html/html_unescape.gperf" + {"Topf", 4, {240, 157, 149, 139}}, +#line 2127 "src/html/html_unescape.gperf" + {"Zopf", 3, {226, 132, 164}}, +#line 505 "src/html/html_unescape.gperf" + {"eopf", 4, {240, 157, 149, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1604 "src/html/html_unescape.gperf" + {"ropar", 3, {226, 166, 134}}, +#line 1945 "src/html/html_unescape.gperf" + {"uopf", 4, {240, 157, 149, 166}}, +#line 978 "src/html/html_unescape.gperf" + {"lopar", 3, {226, 166, 133}}, +#line 1870 "src/html/html_unescape.gperf" + {"topf", 4, {240, 157, 149, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2075 "src/html/html_unescape.gperf" + {"Xopf", 4, {240, 157, 149, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1166 "src/html/html_unescape.gperf" + {"nopf", 4, {240, 157, 149, 159}}, + {(char*)0}, +#line 146 "src/html/html_unescape.gperf" + {"bopf", 4, {240, 157, 149, 147}}, +#line 512 "src/html/html_unescape.gperf" + {"epsiv", 2, {207, 181}}, +#line 562 "src/html/html_unescape.gperf" + {"fnof", 2, {198, 146}}, +#line 734 "src/html/html_unescape.gperf" + {"imacr", 2, {196, 171}}, + {(char*)0}, {(char*)0}, +#line 792 "src/html/html_unescape.gperf" + {"Jopf", 4, {240, 157, 149, 129}}, + {(char*)0}, +#line 1135 "src/html/html_unescape.gperf" + {"nhpar", 3, {226, 171, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2053 "src/html/html_unescape.gperf" + {"Wopf", 4, {240, 157, 149, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1721 "src/html/html_unescape.gperf" + {"Sqrt", 3, {226, 136, 154}}, +#line 1263 "src/html/html_unescape.gperf" + {"nsub", 3, {226, 138, 132}}, + {(char*)0}, +#line 1081 "src/html/html_unescape.gperf" + {"napid", 3, {226, 137, 139}}, + {(char*)0}, {(char*)0}, +#line 1224 "src/html/html_unescape.gperf" + {"NotSuperset", 3, {226, 138, 131}}, + {(char*)0}, {(char*)0}, +#line 197 "src/html/html_unescape.gperf" + {"brvbar", 2, {194, 166}}, + {(char*)0}, {(char*)0}, +#line 1711 "src/html/html_unescape.gperf" + {"sol", 1, {47}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 461 "src/html/html_unescape.gperf" + {"easter", 3, {226, 169, 174}}, + {(char*)0}, +#line 1429 "src/html/html_unescape.gperf" + {"popf", 4, {240, 157, 149, 161}}, + {(char*)0}, {(char*)0}, +#line 370 "src/html/html_unescape.gperf" + {"dHar", 3, {226, 165, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2032 "src/html/html_unescape.gperf" + {"Vopf", 4, {240, 157, 149, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1274 "src/html/html_unescape.gperf" + {"nsupset", 3, {226, 138, 131}}, +#line 1271 "src/html/html_unescape.gperf" + {"nsup", 3, {226, 138, 133}}, +#line 2003 "src/html/html_unescape.gperf" + {"vBar", 3, {226, 171, 168}}, + {(char*)0}, +#line 1266 "src/html/html_unescape.gperf" + {"nsubset", 3, {226, 138, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1851 "src/html/html_unescape.gperf" + {"thkap", 3, {226, 137, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1137 "src/html/html_unescape.gperf" + {"nis", 3, {226, 139, 188}}, +#line 1460 "src/html/html_unescape.gperf" + {"profsurf", 3, {226, 140, 147}}, +#line 1710 "src/html/html_unescape.gperf" + {"solb", 3, {226, 167, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 962 "src/html/html_unescape.gperf" + {"lnsim", 3, {226, 139, 166}}, + {(char*)0}, +#line 1709 "src/html/html_unescape.gperf" + {"solbar", 3, {226, 140, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1731 "src/html/html_unescape.gperf" + {"Square", 3, {226, 150, 161}}, + {(char*)0}, +#line 2033 "src/html/html_unescape.gperf" + {"vopf", 4, {240, 157, 149, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1926 "src/html/html_unescape.gperf" + {"uharl", 3, {226, 134, 191}}, + {(char*)0}, +#line 1931 "src/html/html_unescape.gperf" + {"ulcrop", 3, {226, 140, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 515 "src/html/html_unescape.gperf" + {"eqsim", 3, {226, 137, 130}}, +#line 523 "src/html/html_unescape.gperf" + {"equiv", 3, {226, 137, 161}}, + {(char*)0}, {(char*)0}, +#line 486 "src/html/html_unescape.gperf" + {"ell", 3, {226, 132, 147}}, +#line 1700 "src/html/html_unescape.gperf" + {"smashp", 3, {226, 168, 179}}, +#line 1067 "src/html/html_unescape.gperf" + {"mp", 3, {226, 136, 147}}, + {(char*)0}, {(char*)0}, +#line 814 "src/html/html_unescape.gperf" + {"Kopf", 4, {240, 157, 149, 130}}, + {(char*)0}, {(char*)0}, +#line 1696 "src/html/html_unescape.gperf" + {"simrarr", 3, {226, 165, 178}}, + {(char*)0}, +#line 559 "src/html/html_unescape.gperf" + {"flat", 3, {226, 153, 173}}, + {(char*)0}, +#line 1065 "src/html/html_unescape.gperf" + {"Mopf", 4, {240, 157, 149, 132}}, +#line 1712 "src/html/html_unescape.gperf" + {"Sopf", 4, {240, 157, 149, 138}}, +#line 1062 "src/html/html_unescape.gperf" + {"mldr", 3, {226, 128, 166}}, +#line 1597 "src/html/html_unescape.gperf" + {"rlm", 3, {226, 128, 143}}, +#line 768 "src/html/html_unescape.gperf" + {"iprod", 3, {226, 168, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 991 "src/html/html_unescape.gperf" + {"lparlt", 3, {226, 166, 147}}, + {(char*)0}, +#line 564 "src/html/html_unescape.gperf" + {"fopf", 4, {240, 157, 149, 151}}, +#line 1944 "src/html/html_unescape.gperf" + {"Uopf", 4, {240, 157, 149, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1996 "src/html/html_unescape.gperf" + {"varsubsetneq", 3, {226, 138, 138}}, +#line 1997 "src/html/html_unescape.gperf" + {"varsubsetneqq", 3, {226, 171, 139}}, + {(char*)0}, {(char*)0}, +#line 1970 "src/html/html_unescape.gperf" + {"urcrop", 3, {226, 140, 142}}, +#line 928 "src/html/html_unescape.gperf" + {"LessLess", 3, {226, 170, 161}}, + {(char*)0}, +#line 1543 "src/html/html_unescape.gperf" + {"Re", 3, {226, 132, 156}}, + {(char*)0}, {(char*)0}, +#line 1202 "src/html/html_unescape.gperf" + {"NotNestedLessLess", 3, {226, 170, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 396 "src/html/html_unescape.gperf" + {"Dopf", 4, {240, 157, 148, 187}}, + {(char*)0}, +#line 568 "src/html/html_unescape.gperf" + {"forkv", 3, {226, 171, 153}}, + {(char*)0}, +#line 1261 "src/html/html_unescape.gperf" + {"nsqsube", 3, {226, 139, 162}}, + {(char*)0}, +#line 1273 "src/html/html_unescape.gperf" + {"nsupe", 3, {226, 138, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1265 "src/html/html_unescape.gperf" + {"nsube", 3, {226, 138, 136}}, +#line 1475 "src/html/html_unescape.gperf" + {"qopf", 4, {240, 157, 149, 162}}, +#line 1596 "src/html/html_unescape.gperf" + {"rlhar", 3, {226, 135, 140}}, + {(char*)0}, {(char*)0}, +#line 996 "src/html/html_unescape.gperf" + {"lrm", 3, {226, 128, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1157 "src/html/html_unescape.gperf" + {"nlsim", 3, {226, 137, 180}}, + {(char*)0}, +#line 1431 "src/html/html_unescape.gperf" + {"pound", 2, {194, 163}}, +#line 1998 "src/html/html_unescape.gperf" + {"varsupsetneq", 3, {226, 138, 139}}, +#line 1999 "src/html/html_unescape.gperf" + {"varsupsetneqq", 3, {226, 171, 140}}, + {(char*)0}, +#line 142 "src/html/html_unescape.gperf" + {"bnequiv", 3, {226, 137, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 979 "src/html/html_unescape.gperf" + {"Lopf", 4, {240, 157, 149, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1262 "src/html/html_unescape.gperf" + {"nsqsupe", 3, {226, 139, 163}}, + {(char*)0}, {(char*)0}, +#line 1507 "src/html/html_unescape.gperf" + {"rarrlp", 3, {226, 134, 172}}, +#line 2046 "src/html/html_unescape.gperf" + {"wedbar", 3, {226, 169, 159}}, +#line 839 "src/html/html_unescape.gperf" + {"larrlp", 3, {226, 134, 171}}, + {(char*)0}, +#line 2101 "src/html/html_unescape.gperf" + {"Yopf", 4, {240, 157, 149, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1210 "src/html/html_unescape.gperf" + {"NotReverseElement", 3, {226, 136, 140}}, + {(char*)0}, {(char*)0}, +#line 295 "src/html/html_unescape.gperf" + {"Copf", 3, {226, 132, 130}}, +#line 994 "src/html/html_unescape.gperf" + {"lrhar", 3, {226, 135, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1391 "src/html/html_unescape.gperf" + {"parsl", 3, {226, 171, 189}}, +#line 1935 "src/html/html_unescape.gperf" + {"uml", 2, {194, 168}}, +#line 1039 "src/html/html_unescape.gperf" + {"marker", 3, {226, 150, 174}}, +#line 1275 "src/html/html_unescape.gperf" + {"nsupseteq", 3, {226, 138, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1267 "src/html/html_unescape.gperf" + {"nsubseteq", 3, {226, 138, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1738 "src/html/html_unescape.gperf" + {"squarf", 3, {226, 150, 170}}, +#line 2021 "src/html/html_unescape.gperf" + {"Vert", 3, {226, 128, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1736 "src/html/html_unescape.gperf" + {"SquareSupersetEqual", 3, {226, 138, 146}}, + {(char*)0}, +#line 1465 "src/html/html_unescape.gperf" + {"prsim", 3, {226, 137, 190}}, + {(char*)0}, {(char*)0}, +#line 1734 "src/html/html_unescape.gperf" + {"SquareSubsetEqual", 3, {226, 138, 145}}, + {(char*)0}, {(char*)0}, +#line 1735 "src/html/html_unescape.gperf" + {"SquareSuperset", 3, {226, 138, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1733 "src/html/html_unescape.gperf" + {"SquareSubset", 3, {226, 138, 143}}, +#line 1290 "src/html/html_unescape.gperf" + {"nvap", 3, {226, 137, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 765 "src/html/html_unescape.gperf" + {"iopf", 4, {240, 157, 149, 154}}, + {(char*)0}, +#line 1426 "src/html/html_unescape.gperf" + {"pm", 2, {194, 177}}, + {(char*)0}, +#line 2020 "src/html/html_unescape.gperf" + {"vert", 1, {124}}, + {(char*)0}, +#line 1845 "src/html/html_unescape.gperf" + {"thetav", 2, {207, 145}}, + {(char*)0}, {(char*)0}, +#line 987 "src/html/html_unescape.gperf" + {"loz", 3, {226, 151, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1034 "src/html/html_unescape.gperf" + {"map", 3, {226, 134, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 923 "src/html/html_unescape.gperf" + {"lesseqqgtr", 3, {226, 170, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1616 "src/html/html_unescape.gperf" + {"rscr", 4, {240, 157, 147, 135}}, +#line 1478 "src/html/html_unescape.gperf" + {"Qscr", 4, {240, 157, 146, 172}}, +#line 999 "src/html/html_unescape.gperf" + {"lscr", 4, {240, 157, 147, 129}}, + {(char*)0}, +#line 1743 "src/html/html_unescape.gperf" + {"sscr", 4, {240, 157, 147, 136}}, + {(char*)0}, +#line 1891 "src/html/html_unescape.gperf" + {"Tscr", 4, {240, 157, 146, 175}}, +#line 2128 "src/html/html_unescape.gperf" + {"Zscr", 4, {240, 157, 146, 181}}, +#line 528 "src/html/html_unescape.gperf" + {"escr", 3, {226, 132, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1975 "src/html/html_unescape.gperf" + {"uscr", 4, {240, 157, 147, 138}}, + {(char*)0}, +#line 1892 "src/html/html_unescape.gperf" + {"tscr", 4, {240, 157, 147, 137}}, + {(char*)0}, +#line 741 "src/html/html_unescape.gperf" + {"imof", 3, {226, 138, 183}}, +#line 297 "src/html/html_unescape.gperf" + {"Coproduct", 3, {226, 136, 144}}, + {(char*)0}, {(char*)0}, +#line 2081 "src/html/html_unescape.gperf" + {"Xscr", 4, {240, 157, 146, 179}}, +#line 2068 "src/html/html_unescape.gperf" + {"Xi", 2, {206, 158}}, + {(char*)0}, {(char*)0}, +#line 1253 "src/html/html_unescape.gperf" + {"nscr", 4, {240, 157, 147, 131}}, +#line 1136 "src/html/html_unescape.gperf" + {"ni", 3, {226, 136, 139}}, +#line 198 "src/html/html_unescape.gperf" + {"bscr", 4, {240, 157, 146, 183}}, +#line 1167 "src/html/html_unescape.gperf" + {"Nopf", 3, {226, 132, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 794 "src/html/html_unescape.gperf" + {"Jscr", 4, {240, 157, 146, 165}}, +#line 1443 "src/html/html_unescape.gperf" + {"preceq", 3, {226, 170, 175}}, + {(char*)0}, {(char*)0}, +#line 1303 "src/html/html_unescape.gperf" + {"nvrArr", 3, {226, 164, 131}}, +#line 88 "src/html/html_unescape.gperf" + {"backprime", 3, {226, 128, 181}}, +#line 2058 "src/html/html_unescape.gperf" + {"Wscr", 4, {240, 157, 146, 178}}, + {(char*)0}, +#line 1989 "src/html/html_unescape.gperf" + {"varphi", 2, {207, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1259 "src/html/html_unescape.gperf" + {"nsmid", 3, {226, 136, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 393 "src/html/html_unescape.gperf" + {"dlcorn", 3, {226, 140, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1468 "src/html/html_unescape.gperf" + {"pscr", 4, {240, 157, 147, 133}}, +#line 1409 "src/html/html_unescape.gperf" + {"pi", 2, {207, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2036 "src/html/html_unescape.gperf" + {"Vscr", 4, {240, 157, 146, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1113 "src/html/html_unescape.gperf" + {"nesim", 3, {226, 137, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1694 "src/html/html_unescape.gperf" + {"simne", 3, {226, 137, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1276 "src/html/html_unescape.gperf" + {"nsupseteqq", 3, {226, 171, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1268 "src/html/html_unescape.gperf" + {"nsubseteqq", 3, {226, 171, 133}}, +#line 441 "src/html/html_unescape.gperf" + {"drcorn", 3, {226, 140, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1521 "src/html/html_unescape.gperf" + {"rbrace", 1, {125}}, +#line 2037 "src/html/html_unescape.gperf" + {"vscr", 4, {240, 157, 147, 139}}, +#line 851 "src/html/html_unescape.gperf" + {"lbrace", 1, {123}}, +#line 397 "src/html/html_unescape.gperf" + {"dopf", 4, {240, 157, 149, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 586 "src/html/html_unescape.gperf" + {"frasl", 3, {226, 129, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 931 "src/html/html_unescape.gperf" + {"LessTilde", 3, {226, 137, 178}}, + {(char*)0}, {(char*)0}, +#line 816 "src/html/html_unescape.gperf" + {"Kscr", 4, {240, 157, 146, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1417 "src/html/html_unescape.gperf" + {"pluscir", 3, {226, 168, 162}}, +#line 1069 "src/html/html_unescape.gperf" + {"Mscr", 3, {226, 132, 179}}, +#line 1742 "src/html/html_unescape.gperf" + {"Sscr", 4, {240, 157, 146, 174}}, +#line 1524 "src/html/html_unescape.gperf" + {"rbrksld", 3, {226, 166, 142}}, + {(char*)0}, +#line 854 "src/html/html_unescape.gperf" + {"lbrksld", 3, {226, 166, 143}}, +#line 1519 "src/html/html_unescape.gperf" + {"RBarr", 3, {226, 164, 144}}, + {(char*)0}, {(char*)0}, +#line 1718 "src/html/html_unescape.gperf" + {"sqcaps", 3, {226, 138, 147}}, +#line 1504 "src/html/html_unescape.gperf" + {"rArr", 3, {226, 135, 146}}, +#line 143 "src/html/html_unescape.gperf" + {"bNot", 3, {226, 171, 173}}, +#line 836 "src/html/html_unescape.gperf" + {"lArr", 3, {226, 135, 144}}, + {(char*)0}, +#line 588 "src/html/html_unescape.gperf" + {"fscr", 4, {240, 157, 146, 187}}, +#line 1974 "src/html/html_unescape.gperf" + {"Uscr", 4, {240, 157, 146, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1906 "src/html/html_unescape.gperf" + {"uArr", 3, {226, 135, 145}}, + {(char*)0}, {(char*)0}, +#line 1606 "src/html/html_unescape.gperf" + {"Ropf", 3, {226, 132, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2054 "src/html/html_unescape.gperf" + {"wopf", 4, {240, 157, 149, 168}}, + {(char*)0}, {(char*)0}, +#line 443 "src/html/html_unescape.gperf" + {"Dscr", 4, {240, 157, 146, 159}}, +#line 1352 "src/html/html_unescape.gperf" + {"opar", 3, {226, 166, 183}}, +#line 1663 "src/html/html_unescape.gperf" + {"seswar", 3, {226, 164, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 363 "src/html/html_unescape.gperf" + {"Del", 3, {226, 136, 135}}, +#line 1486 "src/html/html_unescape.gperf" + {"rAarr", 3, {226, 135, 155}}, +#line 1559 "src/html/html_unescape.gperf" + {"rho", 2, {207, 129}}, +#line 818 "src/html/html_unescape.gperf" + {"lAarr", 3, {226, 135, 154}}, +#line 1438 "src/html/html_unescape.gperf" + {"preccurlyeq", 3, {226, 137, 188}}, +#line 1479 "src/html/html_unescape.gperf" + {"qscr", 4, {240, 157, 147, 134}}, + {(char*)0}, {(char*)0}, +#line 1029 "src/html/html_unescape.gperf" + {"macr", 2, {194, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1186 "src/html/html_unescape.gperf" + {"notin", 3, {226, 136, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 524 "src/html/html_unescape.gperf" + {"equivDD", 3, {226, 169, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1717 "src/html/html_unescape.gperf" + {"sqcap", 3, {226, 138, 147}}, + {(char*)0}, +#line 1260 "src/html/html_unescape.gperf" + {"nspar", 3, {226, 136, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1341 "src/html/html_unescape.gperf" + {"olt", 3, {226, 167, 128}}, +#line 1515 "src/html/html_unescape.gperf" + {"ratio", 3, {226, 136, 182}}, +#line 1000 "src/html/html_unescape.gperf" + {"Lscr", 3, {226, 132, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 371 "src/html/html_unescape.gperf" + {"dharl", 3, {226, 135, 131}}, + {(char*)0}, +#line 394 "src/html/html_unescape.gperf" + {"dlcrop", 3, {226, 140, 141}}, +#line 409 "src/html/html_unescape.gperf" + {"DoubleDot", 2, {194, 168}}, +#line 405 "src/html/html_unescape.gperf" + {"dotplus", 3, {226, 136, 148}}, +#line 1359 "src/html/html_unescape.gperf" + {"or", 3, {226, 136, 168}}, + {(char*)0}, +#line 2103 "src/html/html_unescape.gperf" + {"Yscr", 4, {240, 157, 146, 180}}, + {(char*)0}, {(char*)0}, +#line 563 "src/html/html_unescape.gperf" + {"Fopf", 4, {240, 157, 148, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 305 "src/html/html_unescape.gperf" + {"Cscr", 4, {240, 157, 146, 158}}, +#line 1337 "src/html/html_unescape.gperf" + {"olarr", 3, {226, 134, 186}}, +#line 1244 "src/html/html_unescape.gperf" + {"nrarrw", 3, {226, 134, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1027 "src/html/html_unescape.gperf" + {"lvertneqq", 3, {226, 137, 168}}, +#line 516 "src/html/html_unescape.gperf" + {"eqslantgtr", 3, {226, 170, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1854 "src/html/html_unescape.gperf" + {"thorn", 2, {195, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 517 "src/html/html_unescape.gperf" + {"eqslantless", 3, {226, 170, 149}}, + {(char*)0}, {(char*)0}, +#line 744 "src/html/html_unescape.gperf" + {"incare", 3, {226, 132, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1993 "src/html/html_unescape.gperf" + {"vArr", 3, {226, 135, 149}}, +#line 1612 "src/html/html_unescape.gperf" + {"rppolint", 3, {226, 168, 146}}, +#line 442 "src/html/html_unescape.gperf" + {"drcrop", 3, {226, 140, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1388 "src/html/html_unescape.gperf" + {"parallel", 3, {226, 136, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1357 "src/html/html_unescape.gperf" + {"orarr", 3, {226, 134, 187}}, +#line 1745 "src/html/html_unescape.gperf" + {"ssmile", 3, {226, 140, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 413 "src/html/html_unescape.gperf" + {"DoubleLeftTee", 3, {226, 171, 164}}, +#line 527 "src/html/html_unescape.gperf" + {"erDot", 3, {226, 137, 147}}, +#line 382 "src/html/html_unescape.gperf" + {"diams", 3, {226, 153, 166}}, +#line 1744 "src/html/html_unescape.gperf" + {"ssetmn", 3, {226, 136, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1369 "src/html/html_unescape.gperf" + {"oS", 3, {226, 147, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 770 "src/html/html_unescape.gperf" + {"iscr", 4, {240, 157, 146, 190}}, +#line 726 "src/html/html_unescape.gperf" + {"ii", 3, {226, 133, 136}}, +#line 1544 "src/html/html_unescape.gperf" + {"rect", 3, {226, 150, 173}}, + {(char*)0}, {(char*)0}, +#line 1250 "src/html/html_unescape.gperf" + {"nsccue", 3, {226, 139, 161}}, +#line 1661 "src/html/html_unescape.gperf" + {"sect", 2, {194, 167}}, + {(char*)0}, +#line 1061 "src/html/html_unescape.gperf" + {"mlcp", 3, {226, 171, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1366 "src/html/html_unescape.gperf" + {"oror", 3, {226, 169, 150}}, + {(char*)0}, +#line 408 "src/html/html_unescape.gperf" + {"DoubleContourIntegral", 3, {226, 136, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 519 "src/html/html_unescape.gperf" + {"equals", 1, {61}}, + {(char*)0}, +#line 680 "src/html/html_unescape.gperf" + {"Hat", 1, {94}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1746 "src/html/html_unescape.gperf" + {"sstarf", 3, {226, 139, 134}}, +#line 1070 "src/html/html_unescape.gperf" + {"mstpos", 3, {226, 136, 190}}, + {(char*)0}, +#line 383 "src/html/html_unescape.gperf" + {"die", 2, {194, 168}}, +#line 1045 "src/html/html_unescape.gperf" + {"measuredangle", 3, {226, 136, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 565 "src/html/html_unescape.gperf" + {"forall", 3, {226, 136, 128}}, + {(char*)0}, {(char*)0}, +#line 1190 "src/html/html_unescape.gperf" + {"notinvb", 3, {226, 139, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1066 "src/html/html_unescape.gperf" + {"mopf", 4, {240, 157, 149, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1139 "src/html/html_unescape.gperf" + {"niv", 3, {226, 136, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2005 "src/html/html_unescape.gperf" + {"vBarv", 3, {226, 171, 169}}, + {(char*)0}, +#line 1252 "src/html/html_unescape.gperf" + {"Nscr", 4, {240, 157, 146, 169}}, + {(char*)0}, +#line 1397 "src/html/html_unescape.gperf" + {"period", 1, {46}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 103 "src/html/html_unescape.gperf" + {"becaus", 3, {226, 136, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 113 "src/html/html_unescape.gperf" + {"between", 3, {226, 137, 172}}, +#line 751 "src/html/html_unescape.gperf" + {"Int", 3, {226, 136, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 104 "src/html/html_unescape.gperf" + {"because", 3, {226, 136, 181}}, +#line 1411 "src/html/html_unescape.gperf" + {"piv", 2, {207, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1552 "src/html/html_unescape.gperf" + {"rfr", 4, {240, 157, 148, 175}}, +#line 1472 "src/html/html_unescape.gperf" + {"Qfr", 4, {240, 157, 148, 148}}, +#line 935 "src/html/html_unescape.gperf" + {"lfr", 4, {240, 157, 148, 169}}, + {(char*)0}, +#line 1668 "src/html/html_unescape.gperf" + {"sfr", 4, {240, 157, 148, 176}}, +#line 1149 "src/html/html_unescape.gperf" + {"nleftrightarrow", 3, {226, 134, 174}}, +#line 1837 "src/html/html_unescape.gperf" + {"Tfr", 4, {240, 157, 148, 151}}, +#line 2122 "src/html/html_unescape.gperf" + {"Zfr", 3, {226, 132, 168}}, +#line 477 "src/html/html_unescape.gperf" + {"efr", 4, {240, 157, 148, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1686 "src/html/html_unescape.gperf" + {"sim", 3, {226, 136, 188}}, +#line 1922 "src/html/html_unescape.gperf" + {"ufr", 4, {240, 157, 148, 178}}, +#line 1607 "src/html/html_unescape.gperf" + {"roplus", 3, {226, 168, 174}}, +#line 1838 "src/html/html_unescape.gperf" + {"tfr", 4, {240, 157, 148, 177}}, +#line 981 "src/html/html_unescape.gperf" + {"loplus", 3, {226, 168, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2064 "src/html/html_unescape.gperf" + {"Xfr", 4, {240, 157, 148, 155}}, + {(char*)0}, {(char*)0}, +#line 1539 "src/html/html_unescape.gperf" + {"real", 3, {226, 132, 156}}, +#line 1120 "src/html/html_unescape.gperf" + {"nfr", 4, {240, 157, 148, 171}}, + {(char*)0}, +#line 115 "src/html/html_unescape.gperf" + {"bfr", 4, {240, 157, 148, 159}}, + {(char*)0}, +#line 1185 "src/html/html_unescape.gperf" + {"NotHumpEqual", 3, {226, 137, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 789 "src/html/html_unescape.gperf" + {"Jfr", 4, {240, 157, 148, 141}}, + {(char*)0}, +#line 444 "src/html/html_unescape.gperf" + {"dscr", 4, {240, 157, 146, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2051 "src/html/html_unescape.gperf" + {"Wfr", 4, {240, 157, 148, 154}}, + {(char*)0}, +#line 130 "src/html/html_unescape.gperf" + {"blacklozenge", 3, {226, 167, 171}}, + {(char*)0}, +#line 2126 "src/html/html_unescape.gperf" + {"zopf", 4, {240, 157, 149, 171}}, +#line 1542 "src/html/html_unescape.gperf" + {"reals", 3, {226, 132, 157}}, + {(char*)0}, +#line 1171 "src/html/html_unescape.gperf" + {"NotCupCap", 3, {226, 137, 173}}, + {(char*)0}, {(char*)0}, +#line 1695 "src/html/html_unescape.gperf" + {"simplus", 3, {226, 168, 164}}, + {(char*)0}, +#line 566 "src/html/html_unescape.gperf" + {"ForAll", 3, {226, 136, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1402 "src/html/html_unescape.gperf" + {"pfr", 4, {240, 157, 148, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1343 "src/html/html_unescape.gperf" + {"omacr", 2, {197, 141}}, + {(char*)0}, +#line 2027 "src/html/html_unescape.gperf" + {"Vfr", 4, {240, 157, 148, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 489 "src/html/html_unescape.gperf" + {"Emacr", 2, {196, 146}}, +#line 1617 "src/html/html_unescape.gperf" + {"Rscr", 3, {226, 132, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2059 "src/html/html_unescape.gperf" + {"wscr", 4, {240, 157, 147, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1680 "src/html/html_unescape.gperf" + {"ShortUpArrow", 3, {226, 134, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1665 "src/html/html_unescape.gperf" + {"setmn", 3, {226, 136, 150}}, + {(char*)0}, +#line 2028 "src/html/html_unescape.gperf" + {"vfr", 4, {240, 157, 148, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 807 "src/html/html_unescape.gperf" + {"Kfr", 4, {240, 157, 148, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1355 "src/html/html_unescape.gperf" + {"operp", 3, {226, 166, 185}}, + {(char*)0}, +#line 1048 "src/html/html_unescape.gperf" + {"Mfr", 4, {240, 157, 148, 144}}, +#line 1667 "src/html/html_unescape.gperf" + {"Sfr", 4, {240, 157, 148, 150}}, + {(char*)0}, {(char*)0}, +#line 1161 "src/html/html_unescape.gperf" + {"nltrie", 3, {226, 139, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 589 "src/html/html_unescape.gperf" + {"Fscr", 3, {226, 132, 177}}, + {(char*)0}, {(char*)0}, +#line 554 "src/html/html_unescape.gperf" + {"ffr", 4, {240, 157, 148, 163}}, +#line 1921 "src/html/html_unescape.gperf" + {"Ufr", 4, {240, 157, 148, 152}}, + {(char*)0}, +#line 1677 "src/html/html_unescape.gperf" + {"shortmid", 3, {226, 136, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1305 "src/html/html_unescape.gperf" + {"nvsim", 3, {226, 136, 188}}, +#line 368 "src/html/html_unescape.gperf" + {"Dfr", 4, {240, 157, 148, 135}}, +#line 921 "src/html/html_unescape.gperf" + {"lessdot", 3, {226, 139, 150}}, + {(char*)0}, {(char*)0}, +#line 1459 "src/html/html_unescape.gperf" + {"profline", 3, {226, 140, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1473 "src/html/html_unescape.gperf" + {"qfr", 4, {240, 157, 148, 174}}, +#line 346 "src/html/html_unescape.gperf" + {"dArr", 3, {226, 135, 147}}, + {(char*)0}, +#line 1248 "src/html/html_unescape.gperf" + {"nrtrie", 3, {226, 139, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1679 "src/html/html_unescape.gperf" + {"ShortRightArrow", 3, {226, 134, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1841 "src/html/html_unescape.gperf" + {"Therefore", 3, {226, 136, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 358 "src/html/html_unescape.gperf" + {"DD", 3, {226, 133, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1840 "src/html/html_unescape.gperf" + {"therefore", 3, {226, 136, 180}}, +#line 934 "src/html/html_unescape.gperf" + {"Lfr", 4, {240, 157, 148, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1825 "src/html/html_unescape.gperf" + {"target", 3, {226, 140, 150}}, + {(char*)0}, {(char*)0}, +#line 484 "src/html/html_unescape.gperf" + {"Element", 3, {226, 136, 136}}, +#line 2097 "src/html/html_unescape.gperf" + {"Yfr", 4, {240, 157, 148, 156}}, +#line 272 "src/html/html_unescape.gperf" + {"ClockwiseContourIntegral", 3, {226, 136, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1338 "src/html/html_unescape.gperf" + {"olcir", 3, {226, 166, 190}}, + {(char*)0}, +#line 246 "src/html/html_unescape.gperf" + {"Cfr", 3, {226, 132, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 549 "src/html/html_unescape.gperf" + {"female", 3, {226, 153, 128}}, +#line 1270 "src/html/html_unescape.gperf" + {"nsucceq", 3, {226, 170, 176}}, +#line 1313 "src/html/html_unescape.gperf" + {"oast", 3, {226, 138, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1396 "src/html/html_unescape.gperf" + {"percnt", 1, {37}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1363 "src/html/html_unescape.gperf" + {"ordf", 2, {194, 170}}, + {(char*)0}, +#line 1360 "src/html/html_unescape.gperf" + {"ord", 3, {226, 169, 157}}, +#line 1558 "src/html/html_unescape.gperf" + {"Rho", 2, {206, 161}}, + {(char*)0}, +#line 1068 "src/html/html_unescape.gperf" + {"mscr", 4, {240, 157, 147, 130}}, + {(char*)0}, +#line 1304 "src/html/html_unescape.gperf" + {"nvrtrie", 3, {226, 138, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 959 "src/html/html_unescape.gperf" + {"lnE", 3, {226, 137, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1134 "src/html/html_unescape.gperf" + {"nhArr", 3, {226, 135, 142}}, +#line 1358 "src/html/html_unescape.gperf" + {"Or", 3, {226, 169, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 388 "src/html/html_unescape.gperf" + {"divide", 2, {195, 183}}, + {(char*)0}, +#line 722 "src/html/html_unescape.gperf" + {"ifr", 4, {240, 157, 148, 166}}, +#line 485 "src/html/html_unescape.gperf" + {"elinters", 3, {226, 143, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 204 "src/html/html_unescape.gperf" + {"bsol", 1, {92}}, +#line 1299 "src/html/html_unescape.gperf" + {"nvlArr", 3, {226, 164, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 733 "src/html/html_unescape.gperf" + {"Imacr", 2, {196, 170}}, + {(char*)0}, +#line 90 "src/html/html_unescape.gperf" + {"backsimeq", 3, {226, 139, 141}}, +#line 1899 "src/html/html_unescape.gperf" + {"twixt", 3, {226, 137, 172}}, +#line 1339 "src/html/html_unescape.gperf" + {"olcross", 3, {226, 166, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1509 "src/html/html_unescape.gperf" + {"rarrsim", 3, {226, 165, 180}}, +#line 410 "src/html/html_unescape.gperf" + {"DoubleDownArrow", 3, {226, 135, 147}}, +#line 841 "src/html/html_unescape.gperf" + {"larrsim", 3, {226, 165, 179}}, +#line 492 "src/html/html_unescape.gperf" + {"emptyset", 3, {226, 136, 133}}, +#line 1351 "src/html/html_unescape.gperf" + {"oopf", 4, {240, 157, 149, 160}}, + {(char*)0}, +#line 541 "src/html/html_unescape.gperf" + {"exist", 3, {226, 136, 131}}, + {(char*)0}, {(char*)0}, +#line 950 "src/html/html_unescape.gperf" + {"llhard", 3, {226, 165, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 540 "src/html/html_unescape.gperf" + {"excl", 1, {33}}, +#line 504 "src/html/html_unescape.gperf" + {"Eopf", 4, {240, 157, 148, 188}}, +#line 1143 "src/html/html_unescape.gperf" + {"nlArr", 3, {226, 135, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1850 "src/html/html_unescape.gperf" + {"thinsp", 3, {226, 128, 137}}, +#line 1219 "src/html/html_unescape.gperf" + {"NotSubsetEqual", 3, {226, 138, 136}}, +#line 1404 "src/html/html_unescape.gperf" + {"phi", 2, {207, 134}}, +#line 411 "src/html/html_unescape.gperf" + {"DoubleLeftArrow", 3, {226, 135, 144}}, + {(char*)0}, +#line 1867 "src/html/html_unescape.gperf" + {"topcir", 3, {226, 171, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 387 "src/html/html_unescape.gperf" + {"div", 2, {195, 183}}, + {(char*)0}, +#line 1119 "src/html/html_unescape.gperf" + {"Nfr", 4, {240, 157, 148, 145}}, +#line 1145 "src/html/html_unescape.gperf" + {"nlE", 3, {226, 137, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2129 "src/html/html_unescape.gperf" + {"zscr", 4, {240, 157, 147, 143}}, +#line 995 "src/html/html_unescape.gperf" + {"lrhard", 3, {226, 165, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 951 "src/html/html_unescape.gperf" + {"lltri", 3, {226, 151, 186}}, + {(char*)0}, {(char*)0}, +#line 1243 "src/html/html_unescape.gperf" + {"nrArr", 3, {226, 135, 143}}, +#line 1225 "src/html/html_unescape.gperf" + {"NotSupersetEqual", 3, {226, 138, 137}}, + {(char*)0}, +#line 1820 "src/html/html_unescape.gperf" + {"swArr", 3, {226, 135, 153}}, +#line 1848 "src/html/html_unescape.gperf" + {"ThickSpace", 3, {226, 129, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1932 "src/html/html_unescape.gperf" + {"ultri", 3, {226, 151, 184}}, +#line 1205 "src/html/html_unescape.gperf" + {"notnivb", 3, {226, 139, 190}}, + {(char*)0}, +#line 1450 "src/html/html_unescape.gperf" + {"prime", 3, {226, 128, 178}}, + {(char*)0}, {(char*)0}, +#line 1452 "src/html/html_unescape.gperf" + {"primes", 3, {226, 132, 153}}, + {(char*)0}, +#line 1335 "src/html/html_unescape.gperf" + {"ohm", 2, {206, 169}}, + {(char*)0}, {(char*)0}, +#line 265 "src/html/html_unescape.gperf" + {"CircleTimes", 3, {226, 138, 151}}, +#line 1160 "src/html/html_unescape.gperf" + {"nltri", 3, {226, 139, 170}}, + {(char*)0}, {(char*)0}, +#line 1692 "src/html/html_unescape.gperf" + {"siml", 3, {226, 170, 157}}, +#line 1308 "src/html/html_unescape.gperf" + {"nwArr", 3, {226, 135, 150}}, + {(char*)0}, {(char*)0}, +#line 1990 "src/html/html_unescape.gperf" + {"varpi", 2, {207, 150}}, + {(char*)0}, {(char*)0}, +#line 1368 "src/html/html_unescape.gperf" + {"orv", 3, {226, 169, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1664 "src/html/html_unescape.gperf" + {"setminus", 3, {226, 136, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 997 "src/html/html_unescape.gperf" + {"lrtri", 3, {226, 138, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1398 "src/html/html_unescape.gperf" + {"permil", 3, {226, 128, 176}}, +#line 1054 "src/html/html_unescape.gperf" + {"mid", 3, {226, 136, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1973 "src/html/html_unescape.gperf" + {"urtri", 3, {226, 151, 185}}, + {(char*)0}, {(char*)0}, +#line 369 "src/html/html_unescape.gperf" + {"dfr", 4, {240, 157, 148, 161}}, +#line 1050 "src/html/html_unescape.gperf" + {"mho", 3, {226, 132, 167}}, +#line 1448 "src/html/html_unescape.gperf" + {"prE", 3, {226, 170, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2041 "src/html/html_unescape.gperf" + {"vsupne", 3, {226, 138, 139}}, + {(char*)0}, {(char*)0}, +#line 1247 "src/html/html_unescape.gperf" + {"nrtri", 3, {226, 139, 171}}, +#line 2039 "src/html/html_unescape.gperf" + {"vsubne", 3, {226, 138, 138}}, + {(char*)0}, +#line 473 "src/html/html_unescape.gperf" + {"eDot", 3, {226, 137, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 919 "src/html/html_unescape.gperf" + {"lesges", 3, {226, 170, 147}}, + {(char*)0}, {(char*)0}, +#line 87 "src/html/html_unescape.gperf" + {"backepsilon", 2, {207, 182}}, + {(char*)0}, +#line 1513 "src/html/html_unescape.gperf" + {"ratail", 3, {226, 164, 154}}, + {(char*)0}, +#line 843 "src/html/html_unescape.gperf" + {"latail", 3, {226, 164, 153}}, + {(char*)0}, {(char*)0}, +#line 1954 "src/html/html_unescape.gperf" + {"UpEquilibrium", 3, {226, 165, 174}}, + {(char*)0}, {(char*)0}, +#line 511 "src/html/html_unescape.gperf" + {"epsilon", 2, {206, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1964 "src/html/html_unescape.gperf" + {"upsilon", 2, {207, 133}}, + {(char*)0}, +#line 1052 "src/html/html_unescape.gperf" + {"midast", 1, {42}}, +#line 698 "src/html/html_unescape.gperf" + {"Hopf", 3, {226, 132, 141}}, +#line 2029 "src/html/html_unescape.gperf" + {"vltri", 3, {226, 138, 178}}, + {(char*)0}, +#line 1553 "src/html/html_unescape.gperf" + {"Rfr", 3, {226, 132, 156}}, + {(char*)0}, {(char*)0}, +#line 2048 "src/html/html_unescape.gperf" + {"Wedge", 3, {226, 139, 128}}, +#line 2052 "src/html/html_unescape.gperf" + {"wfr", 4, {240, 157, 148, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 94 "src/html/html_unescape.gperf" + {"barwed", 3, {226, 140, 133}}, + {(char*)0}, {(char*)0}, +#line 1031 "src/html/html_unescape.gperf" + {"malt", 3, {226, 156, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 251 "src/html/html_unescape.gperf" + {"Chi", 2, {206, 167}}, +#line 494 "src/html/html_unescape.gperf" + {"emptyv", 3, {226, 136, 133}}, +#line 1203 "src/html/html_unescape.gperf" + {"notni", 3, {226, 136, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 926 "src/html/html_unescape.gperf" + {"LessGreater", 3, {226, 137, 182}}, + {(char*)0}, +#line 378 "src/html/html_unescape.gperf" + {"diam", 3, {226, 139, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2035 "src/html/html_unescape.gperf" + {"vrtri", 3, {226, 138, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 263 "src/html/html_unescape.gperf" + {"CircleMinus", 3, {226, 138, 150}}, + {(char*)0}, +#line 1342 "src/html/html_unescape.gperf" + {"Omacr", 2, {197, 140}}, +#line 1659 "src/html/html_unescape.gperf" + {"seArr", 3, {226, 135, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 553 "src/html/html_unescape.gperf" + {"Ffr", 4, {240, 157, 148, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1445 "src/html/html_unescape.gperf" + {"precneqq", 3, {226, 170, 181}}, + {(char*)0}, +#line 380 "src/html/html_unescape.gperf" + {"Diamond", 3, {226, 139, 132}}, +#line 1364 "src/html/html_unescape.gperf" + {"ordm", 2, {194, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1103 "src/html/html_unescape.gperf" + {"neArr", 3, {226, 135, 151}}, +#line 764 "src/html/html_unescape.gperf" + {"Iopf", 4, {240, 157, 149, 128}}, +#line 260 "src/html/html_unescape.gperf" + {"CircleDot", 3, {226, 138, 153}}, + {(char*)0}, {(char*)0}, +#line 1453 "src/html/html_unescape.gperf" + {"prnap", 3, {226, 170, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 404 "src/html/html_unescape.gperf" + {"dotminus", 3, {226, 136, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1254 "src/html/html_unescape.gperf" + {"nshortmid", 3, {226, 136, 164}}, + {(char*)0}, +#line 148 "src/html/html_unescape.gperf" + {"bottom", 3, {226, 138, 165}}, + {(char*)0}, +#line 1428 "src/html/html_unescape.gperf" + {"pointint", 3, {226, 168, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1737 "src/html/html_unescape.gperf" + {"SquareUnion", 3, {226, 138, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 793 "src/html/html_unescape.gperf" + {"jopf", 4, {240, 157, 149, 155}}, + {(char*)0}, {(char*)0}, +#line 1963 "src/html/html_unescape.gperf" + {"Upsilon", 2, {206, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 279 "src/html/html_unescape.gperf" + {"Colone", 3, {226, 169, 180}}, + {(char*)0}, +#line 1301 "src/html/html_unescape.gperf" + {"nvlt", 1, {60}}, + {(char*)0}, {(char*)0}, +#line 1115 "src/html/html_unescape.gperf" + {"NestedLessLess", 3, {226, 137, 170}}, +#line 278 "src/html/html_unescape.gperf" + {"Colon", 3, {226, 136, 183}}, + {(char*)0}, {(char*)0}, +#line 205 "src/html/html_unescape.gperf" + {"bsolhsub", 3, {226, 159, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 412 "src/html/html_unescape.gperf" + {"DoubleLeftRightArrow", 3, {226, 135, 148}}, +#line 1424 "src/html/html_unescape.gperf" + {"plussim", 3, {226, 168, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 735 "src/html/html_unescape.gperf" + {"image", 3, {226, 132, 145}}, +#line 481 "src/html/html_unescape.gperf" + {"egs", 3, {226, 170, 150}}, + {(char*)0}, {(char*)0}, +#line 1371 "src/html/html_unescape.gperf" + {"oscr", 3, {226, 132, 180}}, +#line 1822 "src/html/html_unescape.gperf" + {"swnwar", 3, {226, 164, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2117 "src/html/html_unescape.gperf" + {"zeetrf", 3, {226, 132, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1032 "src/html/html_unescape.gperf" + {"maltese", 3, {226, 156, 160}}, + {(char*)0}, +#line 1049 "src/html/html_unescape.gperf" + {"mfr", 4, {240, 157, 148, 170}}, +#line 1505 "src/html/html_unescape.gperf" + {"rarrfs", 3, {226, 164, 158}}, +#line 529 "src/html/html_unescape.gperf" + {"Escr", 3, {226, 132, 176}}, +#line 837 "src/html/html_unescape.gperf" + {"larrfs", 3, {226, 164, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1063 "src/html/html_unescape.gperf" + {"mnplus", 3, {226, 136, 147}}, +#line 1130 "src/html/html_unescape.gperf" + {"ngt", 3, {226, 137, 175}}, +#line 1131 "src/html/html_unescape.gperf" + {"ngtr", 3, {226, 137, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 628 "src/html/html_unescape.gperf" + {"gl", 3, {226, 137, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 381 "src/html/html_unescape.gperf" + {"diamondsuit", 3, {226, 153, 166}}, +#line 656 "src/html/html_unescape.gperf" + {"GT", 1, {62}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 929 "src/html/html_unescape.gperf" + {"lesssim", 3, {226, 137, 178}}, +#line 447 "src/html/html_unescape.gperf" + {"dsol", 3, {226, 167, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1955 "src/html/html_unescape.gperf" + {"upharpoonleft", 3, {226, 134, 191}}, +#line 1732 "src/html/html_unescape.gperf" + {"SquareIntersection", 3, {226, 138, 147}}, +#line 1004 "src/html/html_unescape.gperf" + {"lsime", 3, {226, 170, 141}}, + {(char*)0}, +#line 1158 "src/html/html_unescape.gperf" + {"nLt", 3, {226, 137, 170}}, + {(char*)0}, +#line 1195 "src/html/html_unescape.gperf" + {"NotLess", 3, {226, 137, 174}}, + {(char*)0}, +#line 631 "src/html/html_unescape.gperf" + {"gnap", 3, {226, 170, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1635 "src/html/html_unescape.gperf" + {"scap", 3, {226, 170, 184}}, + {(char*)0}, {(char*)0}, +#line 1037 "src/html/html_unescape.gperf" + {"mapstoleft", 3, {226, 134, 164}}, +#line 1198 "src/html/html_unescape.gperf" + {"NotLessLess", 3, {226, 137, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1551 "src/html/html_unescape.gperf" + {"rfloor", 3, {226, 140, 139}}, + {(char*)0}, +#line 933 "src/html/html_unescape.gperf" + {"lfloor", 3, {226, 140, 138}}, + {(char*)0}, {(char*)0}, +#line 1257 "src/html/html_unescape.gperf" + {"nsime", 3, {226, 137, 132}}, + {(char*)0}, +#line 202 "src/html/html_unescape.gperf" + {"bsime", 3, {226, 139, 141}}, +#line 1196 "src/html/html_unescape.gperf" + {"NotLessEqual", 3, {226, 137, 176}}, +#line 1200 "src/html/html_unescape.gperf" + {"NotLessTilde", 3, {226, 137, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1090 "src/html/html_unescape.gperf" + {"ncap", 3, {226, 169, 131}}, + {(char*)0}, {(char*)0}, +#line 1197 "src/html/html_unescape.gperf" + {"NotLessGreater", 3, {226, 137, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1449 "src/html/html_unescape.gperf" + {"precsim", 3, {226, 137, 190}}, + {(char*)0}, +#line 977 "src/html/html_unescape.gperf" + {"looparrowright", 3, {226, 134, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1433 "src/html/html_unescape.gperf" + {"Pr", 3, {226, 170, 187}}, +#line 1531 "src/html/html_unescape.gperf" + {"rcub", 1, {125}}, +#line 1038 "src/html/html_unescape.gperf" + {"mapstoup", 3, {226, 134, 165}}, +#line 861 "src/html/html_unescape.gperf" + {"lcub", 1, {123}}, + {(char*)0}, +#line 2121 "src/html/html_unescape.gperf" + {"zfr", 4, {240, 157, 148, 183}}, + {(char*)0}, {(char*)0}, +#line 1947 "src/html/html_unescape.gperf" + {"uparrow", 3, {226, 134, 145}}, + {(char*)0}, +#line 633 "src/html/html_unescape.gperf" + {"gne", 3, {226, 170, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1641 "src/html/html_unescape.gperf" + {"sce", 3, {226, 170, 176}}, +#line 740 "src/html/html_unescape.gperf" + {"Im", 3, {226, 132, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1527 "src/html/html_unescape.gperf" + {"rcaron", 2, {197, 153}}, + {(char*)0}, +#line 857 "src/html/html_unescape.gperf" + {"lcaron", 2, {196, 190}}, +#line 1350 "src/html/html_unescape.gperf" + {"Oopf", 4, {240, 157, 149, 134}}, +#line 1637 "src/html/html_unescape.gperf" + {"scaron", 2, {197, 161}}, +#line 89 "src/html/html_unescape.gperf" + {"backsim", 3, {226, 136, 189}}, +#line 1829 "src/html/html_unescape.gperf" + {"Tcaron", 2, {197, 164}}, +#line 2111 "src/html/html_unescape.gperf" + {"Zcaron", 2, {197, 189}}, +#line 463 "src/html/html_unescape.gperf" + {"ecaron", 2, {196, 155}}, + {(char*)0}, +#line 109 "src/html/html_unescape.gperf" + {"Bernoullis", 3, {226, 132, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1122 "src/html/html_unescape.gperf" + {"nge", 3, {226, 137, 177}}, +#line 1830 "src/html/html_unescape.gperf" + {"tcaron", 2, {197, 165}}, + {(char*)0}, +#line 567 "src/html/html_unescape.gperf" + {"fork", 3, {226, 139, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 702 "src/html/html_unescape.gperf" + {"Hscr", 3, {226, 132, 139}}, + {(char*)0}, +#line 1092 "src/html/html_unescape.gperf" + {"ncaron", 2, {197, 136}}, +#line 488 "src/html/html_unescape.gperf" + {"elsdot", 3, {226, 170, 151}}, + {(char*)0}, +#line 1828 "src/html/html_unescape.gperf" + {"tbrk", 3, {226, 142, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1887 "src/html/html_unescape.gperf" + {"triplus", 3, {226, 168, 185}}, + {(char*)0}, {(char*)0}, +#line 379 "src/html/html_unescape.gperf" + {"diamond", 3, {226, 139, 132}}, + {(char*)0}, {(char*)0}, +#line 1097 "src/html/html_unescape.gperf" + {"ncup", 3, {226, 169, 130}}, + {(char*)0}, +#line 97 "src/html/html_unescape.gperf" + {"bbrk", 3, {226, 142, 181}}, + {(char*)0}, +#line 587 "src/html/html_unescape.gperf" + {"frown", 3, {226, 140, 162}}, +#line 129 "src/html/html_unescape.gperf" + {"bkarow", 3, {226, 164, 141}}, + {(char*)0}, +#line 1714 "src/html/html_unescape.gperf" + {"spades", 3, {226, 153, 160}}, + {(char*)0}, +#line 1470 "src/html/html_unescape.gperf" + {"psi", 2, {207, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 145 "src/html/html_unescape.gperf" + {"Bopf", 4, {240, 157, 148, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 395 "src/html/html_unescape.gperf" + {"dollar", 1, {36}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 386 "src/html/html_unescape.gperf" + {"disin", 3, {226, 139, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1715 "src/html/html_unescape.gperf" + {"spadesuit", 3, {226, 153, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1226 "src/html/html_unescape.gperf" + {"NotTilde", 3, {226, 137, 129}}, +#line 407 "src/html/html_unescape.gperf" + {"doublebarwedge", 3, {226, 140, 134}}, + {(char*)0}, +#line 595 "src/html/html_unescape.gperf" + {"gap", 3, {226, 170, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 98 "src/html/html_unescape.gperf" + {"bbrktbrk", 3, {226, 142, 182}}, + {(char*)0}, {(char*)0}, +#line 1821 "src/html/html_unescape.gperf" + {"swarrow", 3, {226, 134, 153}}, +#line 107 "src/html/html_unescape.gperf" + {"bepsi", 2, {207, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 771 "src/html/html_unescape.gperf" + {"Iscr", 3, {226, 132, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1228 "src/html/html_unescape.gperf" + {"NotTildeFullEqual", 3, {226, 137, 135}}, +#line 514 "src/html/html_unescape.gperf" + {"eqcolon", 3, {226, 137, 149}}, + {(char*)0}, {(char*)0}, +#line 1864 "src/html/html_unescape.gperf" + {"tint", 3, {226, 136, 173}}, + {(char*)0}, {(char*)0}, +#line 757 "src/html/html_unescape.gperf" + {"intprod", 3, {226, 168, 188}}, + {(char*)0}, +#line 1272 "src/html/html_unescape.gperf" + {"nsupE", 3, {226, 171, 134}}, + {(char*)0}, {(char*)0}, +#line 1309 "src/html/html_unescape.gperf" + {"nwarrow", 3, {226, 134, 150}}, +#line 1264 "src/html/html_unescape.gperf" + {"nsubE", 3, {226, 171, 133}}, + {(char*)0}, {(char*)0}, +#line 1126 "src/html/html_unescape.gperf" + {"nges", 3, {226, 169, 190}}, + {(char*)0}, +#line 1949 "src/html/html_unescape.gperf" + {"Uparrow", 3, {226, 135, 145}}, +#line 605 "src/html/html_unescape.gperf" + {"ge", 3, {226, 137, 165}}, +#line 1353 "src/html/html_unescape.gperf" + {"OpenCurlyDoubleQuote", 3, {226, 128, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1699 "src/html/html_unescape.gperf" + {"smallsetminus", 3, {226, 136, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1636 "src/html/html_unescape.gperf" + {"Scaron", 2, {197, 160}}, + {(char*)0}, +#line 1302 "src/html/html_unescape.gperf" + {"nvltrie", 3, {226, 138, 180}}, +#line 613 "src/html/html_unescape.gperf" + {"ges", 3, {226, 169, 190}}, +#line 136 "src/html/html_unescape.gperf" + {"blank", 3, {226, 144, 163}}, +#line 1485 "src/html/html_unescape.gperf" + {"QUOT", 1, {34}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 140 "src/html/html_unescape.gperf" + {"block", 3, {226, 150, 136}}, +#line 1874 "src/html/html_unescape.gperf" + {"trade", 3, {226, 132, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 795 "src/html/html_unescape.gperf" + {"jscr", 4, {240, 157, 146, 191}}, +#line 2047 "src/html/html_unescape.gperf" + {"wedge", 3, {226, 136, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 30 "src/html/html_unescape.gperf" + {"Amacr", 2, {196, 128}}, + {(char*)0}, +#line 518 "src/html/html_unescape.gperf" + {"Equal", 3, {226, 169, 181}}, + {(char*)0}, {(char*)0}, +#line 352 "src/html/html_unescape.gperf" + {"Dcaron", 2, {196, 142}}, + {(char*)0}, {(char*)0}, +#line 400 "src/html/html_unescape.gperf" + {"DotDot", 3, {226, 131, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 635 "src/html/html_unescape.gperf" + {"gneq", 3, {226, 170, 136}}, +#line 1991 "src/html/html_unescape.gperf" + {"varpropto", 3, {226, 136, 157}}, + {(char*)0}, +#line 636 "src/html/html_unescape.gperf" + {"gneqq", 3, {226, 137, 169}}, +#line 1462 "src/html/html_unescape.gperf" + {"Proportional", 3, {226, 136, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 775 "src/html/html_unescape.gperf" + {"isins", 3, {226, 139, 180}}, + {(char*)0}, +#line 470 "src/html/html_unescape.gperf" + {"eDDot", 3, {226, 169, 183}}, +#line 772 "src/html/html_unescape.gperf" + {"isin", 3, {226, 136, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1886 "src/html/html_unescape.gperf" + {"TripleDot", 3, {226, 131, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 569 "src/html/html_unescape.gperf" + {"Fouriertrf", 3, {226, 132, 177}}, +#line 1463 "src/html/html_unescape.gperf" + {"Proportion", 3, {226, 136, 183}}, + {(char*)0}, {(char*)0}, +#line 1123 "src/html/html_unescape.gperf" + {"ngeq", 3, {226, 137, 177}}, +#line 856 "src/html/html_unescape.gperf" + {"Lcaron", 2, {196, 189}}, + {(char*)0}, +#line 1124 "src/html/html_unescape.gperf" + {"ngeqq", 3, {226, 137, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 871 "src/html/html_unescape.gperf" + {"lE", 3, {226, 137, 166}}, +#line 228 "src/html/html_unescape.gperf" + {"Ccaron", 2, {196, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 200 "src/html/html_unescape.gperf" + {"bsemi", 3, {226, 129, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1464 "src/html/html_unescape.gperf" + {"propto", 3, {226, 136, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 915 "src/html/html_unescape.gperf" + {"lesdot", 3, {226, 169, 191}}, +#line 292 "src/html/html_unescape.gperf" + {"Conint", 3, {226, 136, 175}}, + {(char*)0}, +#line 36 "src/html/html_unescape.gperf" + {"And", 3, {226, 169, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1660 "src/html/html_unescape.gperf" + {"searrow", 3, {226, 134, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1367 "src/html/html_unescape.gperf" + {"orslope", 3, {226, 169, 151}}, +#line 677 "src/html/html_unescape.gperf" + {"harr", 3, {226, 134, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 846 "src/html/html_unescape.gperf" + {"late", 3, {226, 170, 173}}, + {(char*)0}, +#line 244 "src/html/html_unescape.gperf" + {"CenterDot", 2, {194, 183}}, + {(char*)0}, {(char*)0}, +#line 1329 "src/html/html_unescape.gperf" + {"ofr", 4, {240, 157, 148, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1104 "src/html/html_unescape.gperf" + {"nearrow", 3, {226, 134, 151}}, + {(char*)0}, +#line 1474 "src/html/html_unescape.gperf" + {"qint", 3, {226, 168, 140}}, + {(char*)0}, {(char*)0}, +#line 847 "src/html/html_unescape.gperf" + {"lates", 3, {226, 170, 173}}, +#line 802 "src/html/html_unescape.gperf" + {"kappav", 2, {207, 176}}, + {(char*)0}, {(char*)0}, +#line 699 "src/html/html_unescape.gperf" + {"horbar", 3, {226, 128, 149}}, +#line 476 "src/html/html_unescape.gperf" + {"Efr", 4, {240, 157, 148, 136}}, +#line 693 "src/html/html_unescape.gperf" + {"hoarr", 3, {226, 135, 191}}, +#line 1240 "src/html/html_unescape.gperf" + {"npre", 3, {226, 170, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 748 "src/html/html_unescape.gperf" + {"inodot", 2, {196, 177}}, + {(char*)0}, +#line 1916 "src/html/html_unescape.gperf" + {"udarr", 3, {226, 135, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 609 "src/html/html_unescape.gperf" + {"geq", 3, {226, 137, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1258 "src/html/html_unescape.gperf" + {"nsimeq", 3, {226, 137, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 610 "src/html/html_unescape.gperf" + {"geqq", 3, {226, 137, 167}}, + {(char*)0}, {(char*)0}, +#line 475 "src/html/html_unescape.gperf" + {"efDot", 3, {226, 137, 146}}, + {(char*)0}, {(char*)0}, +#line 1611 "src/html/html_unescape.gperf" + {"rpargt", 3, {226, 166, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1370 "src/html/html_unescape.gperf" + {"Oscr", 4, {240, 157, 146, 170}}, + {(char*)0}, {(char*)0}, +#line 1419 "src/html/html_unescape.gperf" + {"plusdo", 3, {226, 136, 148}}, + {(char*)0}, {(char*)0}, +#line 822 "src/html/html_unescape.gperf" + {"lagran", 3, {226, 132, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1847 "src/html/html_unescape.gperf" + {"thicksim", 3, {226, 136, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1446 "src/html/html_unescape.gperf" + {"precnsim", 3, {226, 139, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1091 "src/html/html_unescape.gperf" + {"Ncaron", 2, {197, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1080 "src/html/html_unescape.gperf" + {"napE", 3, {226, 169, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 728 "src/html/html_unescape.gperf" + {"iiint", 3, {226, 136, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 199 "src/html/html_unescape.gperf" + {"Bscr", 3, {226, 132, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1036 "src/html/html_unescape.gperf" + {"mapstodown", 3, {226, 134, 167}}, + {(char*)0}, {(char*)0}, +#line 1994 "src/html/html_unescape.gperf" + {"varrho", 2, {207, 177}}, + {(char*)0}, +#line 776 "src/html/html_unescape.gperf" + {"isinsv", 3, {226, 139, 179}}, + {(char*)0}, {(char*)0}, +#line 1297 "src/html/html_unescape.gperf" + {"nvHarr", 3, {226, 164, 132}}, + {(char*)0}, {(char*)0}, +#line 1192 "src/html/html_unescape.gperf" + {"NotLeftTriangleBar", 3, {226, 167, 143}}, + {(char*)0}, +#line 521 "src/html/html_unescape.gperf" + {"equest", 3, {226, 137, 159}}, + {(char*)0}, +#line 1194 "src/html/html_unescape.gperf" + {"NotLeftTriangleEqual", 3, {226, 139, 172}}, +#line 1193 "src/html/html_unescape.gperf" + {"NotLeftTriangle", 3, {226, 139, 170}}, + {(char*)0}, {(char*)0}, +#line 61 "src/html/html_unescape.gperf" + {"Aopf", 4, {240, 157, 148, 184}}, +#line 681 "src/html/html_unescape.gperf" + {"hbar", 3, {226, 132, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1985 "src/html/html_unescape.gperf" + {"vangrt", 3, {226, 166, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 689 "src/html/html_unescape.gperf" + {"Hfr", 3, {226, 132, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1495 "src/html/html_unescape.gperf" + {"range", 3, {226, 166, 165}}, +#line 1705 "src/html/html_unescape.gperf" + {"smte", 3, {226, 170, 172}}, +#line 1003 "src/html/html_unescape.gperf" + {"lsim", 3, {226, 137, 178}}, + {(char*)0}, +#line 1235 "src/html/html_unescape.gperf" + {"npolint", 3, {226, 168, 148}}, + {(char*)0}, +#line 353 "src/html/html_unescape.gperf" + {"dcaron", 2, {196, 143}}, + {(char*)0}, +#line 532 "src/html/html_unescape.gperf" + {"esim", 3, {226, 137, 130}}, + {(char*)0}, +#line 1940 "src/html/html_unescape.gperf" + {"Union", 3, {226, 139, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1706 "src/html/html_unescape.gperf" + {"smtes", 3, {226, 170, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 815 "src/html/html_unescape.gperf" + {"kopf", 4, {240, 157, 149, 156}}, +#line 639 "src/html/html_unescape.gperf" + {"gopf", 4, {240, 157, 149, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1256 "src/html/html_unescape.gperf" + {"nsim", 3, {226, 137, 129}}, + {(char*)0}, +#line 201 "src/html/html_unescape.gperf" + {"bsim", 3, {226, 136, 189}}, + {(char*)0}, +#line 1698 "src/html/html_unescape.gperf" + {"SmallCircle", 3, {226, 136, 152}}, + {(char*)0}, +#line 1172 "src/html/html_unescape.gperf" + {"NotDoubleVerticalBar", 3, {226, 136, 166}}, +#line 1201 "src/html/html_unescape.gperf" + {"NotNestedGreaterGreater", 3, {226, 170, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 520 "src/html/html_unescape.gperf" + {"EqualTilde", 3, {226, 137, 130}}, + {(char*)0}, {(char*)0}, +#line 1187 "src/html/html_unescape.gperf" + {"notindot", 3, {226, 139, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1526 "src/html/html_unescape.gperf" + {"Rcaron", 2, {197, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1430 "src/html/html_unescape.gperf" + {"Popf", 3, {226, 132, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 638 "src/html/html_unescape.gperf" + {"Gopf", 4, {240, 157, 148, 190}}, + {(char*)0}, {(char*)0}, +#line 723 "src/html/html_unescape.gperf" + {"Ifr", 3, {226, 132, 145}}, + {(char*)0}, {(char*)0}, +#line 2049 "src/html/html_unescape.gperf" + {"wedgeq", 3, {226, 137, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1456 "src/html/html_unescape.gperf" + {"prod", 3, {226, 136, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1374 "src/html/html_unescape.gperf" + {"osol", 3, {226, 138, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 419 "src/html/html_unescape.gperf" + {"DoubleUpArrow", 3, {226, 135, 145}}, + {(char*)0}, {(char*)0}, +#line 290 "src/html/html_unescape.gperf" + {"Congruent", 3, {226, 137, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 637 "src/html/html_unescape.gperf" + {"gnsim", 3, {226, 139, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1651 "src/html/html_unescape.gperf" + {"scsim", 3, {226, 137, 191}}, + {(char*)0}, +#line 790 "src/html/html_unescape.gperf" + {"jfr", 4, {240, 157, 148, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1962 "src/html/html_unescape.gperf" + {"upsih", 2, {207, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1156 "src/html/html_unescape.gperf" + {"nLl", 3, {226, 139, 152}}, + {(char*)0}, {(char*)0}, +#line 420 "src/html/html_unescape.gperf" + {"DoubleUpDownArrow", 3, {226, 135, 149}}, + {(char*)0}, +#line 1128 "src/html/html_unescape.gperf" + {"ngsim", 3, {226, 137, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 684 "src/html/html_unescape.gperf" + {"hearts", 3, {226, 153, 165}}, + {(char*)0}, +#line 922 "src/html/html_unescape.gperf" + {"lesseqgtr", 3, {226, 139, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1112 "src/html/html_unescape.gperf" + {"nesear", 3, {226, 164, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 542 "src/html/html_unescape.gperf" + {"Exists", 3, {226, 136, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1703 "src/html/html_unescape.gperf" + {"smile", 3, {226, 140, 163}}, + {(char*)0}, +#line 1984 "src/html/html_unescape.gperf" + {"uwangle", 3, {226, 166, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 685 "src/html/html_unescape.gperf" + {"heartsuit", 3, {226, 153, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 700 "src/html/html_unescape.gperf" + {"HorizontalLine", 3, {226, 148, 128}}, + {(char*)0}, {(char*)0}, +#line 645 "src/html/html_unescape.gperf" + {"GreaterLess", 3, {226, 137, 183}}, + {(char*)0}, +#line 1615 "src/html/html_unescape.gperf" + {"rsaquo", 3, {226, 128, 186}}, + {(char*)0}, +#line 998 "src/html/html_unescape.gperf" + {"lsaquo", 3, {226, 128, 185}}, + {(char*)0}, +#line 1540 "src/html/html_unescape.gperf" + {"realine", 3, {226, 132, 155}}, +#line 348 "src/html/html_unescape.gperf" + {"Dashv", 3, {226, 171, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1687 "src/html/html_unescape.gperf" + {"simdot", 3, {226, 169, 170}}, +#line 641 "src/html/html_unescape.gperf" + {"GreaterEqual", 3, {226, 137, 165}}, +#line 647 "src/html/html_unescape.gperf" + {"GreaterTilde", 3, {226, 137, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 642 "src/html/html_unescape.gperf" + {"GreaterEqualLess", 3, {226, 139, 155}}, + {(char*)0}, +#line 644 "src/html/html_unescape.gperf" + {"GreaterGreater", 3, {226, 170, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1530 "src/html/html_unescape.gperf" + {"rceil", 3, {226, 140, 137}}, + {(char*)0}, +#line 860 "src/html/html_unescape.gperf" + {"lceil", 3, {226, 140, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 927 "src/html/html_unescape.gperf" + {"lessgtr", 3, {226, 137, 182}}, + {(char*)0}, {(char*)0}, +#line 1340 "src/html/html_unescape.gperf" + {"oline", 3, {226, 128, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1852 "src/html/html_unescape.gperf" + {"thksim", 3, {226, 136, 188}}, + {(char*)0}, +#line 759 "src/html/html_unescape.gperf" + {"InvisibleTimes", 3, {226, 129, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1487 "src/html/html_unescape.gperf" + {"race", 3, {226, 136, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 769 "src/html/html_unescape.gperf" + {"iquest", 2, {194, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 737 "src/html/html_unescape.gperf" + {"imagline", 3, {226, 132, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1966 "src/html/html_unescape.gperf" + {"UpTee", 3, {226, 138, 165}}, + {(char*)0}, +#line 1053 "src/html/html_unescape.gperf" + {"midcir", 3, {226, 171, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1327 "src/html/html_unescape.gperf" + {"ofcir", 3, {226, 166, 191}}, + {(char*)0}, {(char*)0}, +#line 357 "src/html/html_unescape.gperf" + {"ddarr", 3, {226, 135, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1494 "src/html/html_unescape.gperf" + {"rangd", 3, {226, 166, 146}}, + {(char*)0}, +#line 827 "src/html/html_unescape.gperf" + {"langd", 3, {226, 166, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 522 "src/html/html_unescape.gperf" + {"Equilibrium", 3, {226, 135, 140}}, +#line 1390 "src/html/html_unescape.gperf" + {"parsim", 3, {226, 171, 179}}, +#line 2012 "src/html/html_unescape.gperf" + {"Vdashl", 3, {226, 171, 166}}, +#line 1328 "src/html/html_unescape.gperf" + {"Ofr", 4, {240, 157, 148, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 105 "src/html/html_unescape.gperf" + {"Because", 3, {226, 136, 181}}, + {(char*)0}, +#line 1514 "src/html/html_unescape.gperf" + {"rAtail", 3, {226, 164, 156}}, + {(char*)0}, +#line 844 "src/html/html_unescape.gperf" + {"lAtail", 3, {226, 164, 155}}, +#line 1349 "src/html/html_unescape.gperf" + {"ominus", 3, {226, 138, 150}}, +#line 74 "src/html/html_unescape.gperf" + {"Ascr", 4, {240, 157, 146, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 510 "src/html/html_unescape.gperf" + {"Epsilon", 2, {206, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1676 "src/html/html_unescape.gperf" + {"ShortLeftArrow", 3, {226, 134, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 777 "src/html/html_unescape.gperf" + {"isinv", 3, {226, 136, 136}}, + {(char*)0}, +#line 1051 "src/html/html_unescape.gperf" + {"micro", 2, {194, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2112 "src/html/html_unescape.gperf" + {"zcaron", 2, {197, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 817 "src/html/html_unescape.gperf" + {"kscr", 4, {240, 157, 147, 128}}, +#line 649 "src/html/html_unescape.gperf" + {"gscr", 3, {226, 132, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 114 "src/html/html_unescape.gperf" + {"Bfr", 4, {240, 157, 148, 133}}, +#line 608 "src/html/html_unescape.gperf" + {"gel", 3, {226, 139, 155}}, +#line 687 "src/html/html_unescape.gperf" + {"hercon", 3, {226, 138, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1885 "src/html/html_unescape.gperf" + {"triminus", 3, {226, 168, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 480 "src/html/html_unescape.gperf" + {"egrave", 2, {195, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1655 "src/html/html_unescape.gperf" + {"sdot", 3, {226, 139, 133}}, +#line 1924 "src/html/html_unescape.gperf" + {"ugrave", 2, {195, 185}}, + {(char*)0}, +#line 2115 "src/html/html_unescape.gperf" + {"Zdot", 2, {197, 187}}, +#line 472 "src/html/html_unescape.gperf" + {"edot", 2, {196, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1229 "src/html/html_unescape.gperf" + {"NotTildeTilde", 3, {226, 137, 137}}, + {(char*)0}, +#line 1835 "src/html/html_unescape.gperf" + {"tdot", 3, {226, 131, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1467 "src/html/html_unescape.gperf" + {"Pscr", 4, {240, 157, 146, 171}}, +#line 1408 "src/html/html_unescape.gperf" + {"Pi", 2, {206, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 648 "src/html/html_unescape.gperf" + {"Gscr", 4, {240, 157, 146, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1425 "src/html/html_unescape.gperf" + {"plustwo", 3, {226, 168, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1173 "src/html/html_unescape.gperf" + {"NotElement", 3, {226, 136, 137}}, + {(char*)0}, +#line 1422 "src/html/html_unescape.gperf" + {"PlusMinus", 2, {194, 177}}, + {(char*)0}, {(char*)0}, +#line 697 "src/html/html_unescape.gperf" + {"hopf", 4, {240, 157, 149, 153}}, +#line 594 "src/html/html_unescape.gperf" + {"gammad", 2, {207, 157}}, + {(char*)0}, +#line 1044 "src/html/html_unescape.gperf" + {"mDDot", 3, {226, 136, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 389 "src/html/html_unescape.gperf" + {"divideontimes", 3, {226, 139, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 401 "src/html/html_unescape.gperf" + {"doteq", 3, {226, 137, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1986 "src/html/html_unescape.gperf" + {"varepsilon", 2, {207, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1439 "src/html/html_unescape.gperf" + {"Precedes", 3, {226, 137, 186}}, + {(char*)0}, {(char*)0}, +#line 593 "src/html/html_unescape.gperf" + {"Gammad", 2, {207, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 349 "src/html/html_unescape.gperf" + {"dashv", 3, {226, 138, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1170 "src/html/html_unescape.gperf" + {"NotCongruent", 3, {226, 137, 162}}, + {(char*)0}, {(char*)0}, +#line 1911 "src/html/html_unescape.gperf" + {"ubreve", 2, {197, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1333 "src/html/html_unescape.gperf" + {"ogt", 3, {226, 167, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1609 "src/html/html_unescape.gperf" + {"RoundImplies", 3, {226, 165, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1441 "src/html/html_unescape.gperf" + {"PrecedesSlantEqual", 3, {226, 137, 188}}, + {(char*)0}, {(char*)0}, +#line 1688 "src/html/html_unescape.gperf" + {"sime", 3, {226, 137, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1923 "src/html/html_unescape.gperf" + {"Ugrave", 2, {195, 153}}, + {(char*)0}, +#line 350 "src/html/html_unescape.gperf" + {"dbkarow", 3, {226, 164, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1656 "src/html/html_unescape.gperf" + {"sdote", 3, {226, 169, 166}}, + {(char*)0}, +#line 2016 "src/html/html_unescape.gperf" + {"veeeq", 3, {226, 137, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1035 "src/html/html_unescape.gperf" + {"mapsto", 3, {226, 134, 166}}, + {(char*)0}, {(char*)0}, +#line 1862 "src/html/html_unescape.gperf" + {"times", 2, {195, 151}}, + {(char*)0}, {(char*)0}, +#line 1496 "src/html/html_unescape.gperf" + {"rangle", 3, {226, 159, 169}}, + {(char*)0}, +#line 828 "src/html/html_unescape.gperf" + {"langle", 3, {226, 159, 168}}, + {(char*)0}, {(char*)0}, +#line 878 "src/html/html_unescape.gperf" + {"leftarrowtail", 3, {226, 134, 162}}, +#line 673 "src/html/html_unescape.gperf" + {"hamilt", 3, {226, 132, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1919 "src/html/html_unescape.gperf" + {"udhar", 3, {226, 165, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1138 "src/html/html_unescape.gperf" + {"nisd", 3, {226, 139, 186}}, + {(char*)0}, +#line 1550 "src/html/html_unescape.gperf" + {"rfisht", 3, {226, 165, 189}}, + {(char*)0}, +#line 932 "src/html/html_unescape.gperf" + {"lfisht", 3, {226, 165, 188}}, +#line 676 "src/html/html_unescape.gperf" + {"harrcir", 3, {226, 165, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1354 "src/html/html_unescape.gperf" + {"OpenCurlyQuote", 3, {226, 128, 152}}, + {(char*)0}, +#line 1920 "src/html/html_unescape.gperf" + {"ufisht", 3, {226, 165, 190}}, +#line 1184 "src/html/html_unescape.gperf" + {"NotHumpDownHump", 3, {226, 137, 142}}, + {(char*)0}, {(char*)0}, +#line 896 "src/html/html_unescape.gperf" + {"LeftTee", 3, {226, 138, 163}}, + {(char*)0}, +#line 1618 "src/html/html_unescape.gperf" + {"rsh", 3, {226, 134, 177}}, + {(char*)0}, +#line 1001 "src/html/html_unescape.gperf" + {"lsh", 3, {226, 134, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 668 "src/html/html_unescape.gperf" + {"gvertneqq", 3, {226, 137, 169}}, + {(char*)0}, {(char*)0}, +#line 1861 "src/html/html_unescape.gperf" + {"timesb", 3, {226, 138, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1650 "src/html/html_unescape.gperf" + {"scpolint", 3, {226, 168, 147}}, + {(char*)0}, {(char*)0}, +#line 237 "src/html/html_unescape.gperf" + {"Cdot", 2, {196, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 455 "src/html/html_unescape.gperf" + {"dwangle", 3, {226, 166, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1910 "src/html/html_unescape.gperf" + {"Ubreve", 2, {197, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 905 "src/html/html_unescape.gperf" + {"LeftUpVector", 3, {226, 134, 191}}, + {(char*)0}, {(char*)0}, +#line 904 "src/html/html_unescape.gperf" + {"LeftUpVectorBar", 3, {226, 165, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 462 "src/html/html_unescape.gperf" + {"Ecaron", 2, {196, 154}}, + {(char*)0}, {(char*)0}, +#line 694 "src/html/html_unescape.gperf" + {"homtht", 3, {226, 136, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 725 "src/html/html_unescape.gperf" + {"igrave", 2, {195, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1239 "src/html/html_unescape.gperf" + {"npreceq", 3, {226, 170, 175}}, +#line 467 "src/html/html_unescape.gperf" + {"ecolon", 3, {226, 137, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 359 "src/html/html_unescape.gperf" + {"dd", 3, {226, 133, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1689 "src/html/html_unescape.gperf" + {"simeq", 3, {226, 137, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1188 "src/html/html_unescape.gperf" + {"notinE", 3, {226, 139, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 120 "src/html/html_unescape.gperf" + {"bigoplus", 3, {226, 168, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 22 "src/html/html_unescape.gperf" + {"Afr", 4, {240, 157, 148, 132}}, +#line 874 "src/html/html_unescape.gperf" + {"leftarrow", 3, {226, 134, 144}}, +#line 1336 "src/html/html_unescape.gperf" + {"oint", 3, {226, 136, 174}}, + {(char*)0}, +#line 1824 "src/html/html_unescape.gperf" + {"Tab", 1, {9}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1330 "src/html/html_unescape.gperf" + {"ogon", 2, {203, 155}}, + {(char*)0}, {(char*)0}, +#line 1013 "src/html/html_unescape.gperf" + {"lt", 1, {60}}, +#line 1150 "src/html/html_unescape.gperf" + {"nLeftrightarrow", 3, {226, 135, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1499 "src/html/html_unescape.gperf" + {"rarrb", 3, {226, 135, 165}}, + {(char*)0}, +#line 832 "src/html/html_unescape.gperf" + {"larrb", 3, {226, 135, 164}}, + {(char*)0}, +#line 701 "src/html/html_unescape.gperf" + {"hscr", 4, {240, 157, 146, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 902 "src/html/html_unescape.gperf" + {"LeftUpDownVector", 3, {226, 165, 145}}, + {(char*)0}, +#line 808 "src/html/html_unescape.gperf" + {"kfr", 4, {240, 157, 148, 168}}, +#line 620 "src/html/html_unescape.gperf" + {"gfr", 4, {240, 157, 148, 164}}, +#line 1946 "src/html/html_unescape.gperf" + {"UpArrowBar", 3, {226, 164, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1251 "src/html/html_unescape.gperf" + {"nsce", 3, {226, 170, 176}}, +#line 1016 "src/html/html_unescape.gperf" + {"ltdot", 3, {226, 139, 150}}, +#line 617 "src/html/html_unescape.gperf" + {"gesl", 3, {226, 139, 155}}, +#line 2074 "src/html/html_unescape.gperf" + {"xodot", 3, {226, 168, 128}}, +#line 1748 "src/html/html_unescape.gperf" + {"star", 3, {226, 152, 134}}, + {(char*)0}, {(char*)0}, +#line 984 "src/html/html_unescape.gperf" + {"lowbar", 1, {95}}, + {(char*)0}, +#line 2066 "src/html/html_unescape.gperf" + {"xharr", 3, {226, 159, 183}}, +#line 466 "src/html/html_unescape.gperf" + {"ecir", 3, {226, 137, 150}}, + {(char*)0}, +#line 1976 "src/html/html_unescape.gperf" + {"utdot", 3, {226, 139, 176}}, +#line 1086 "src/html/html_unescape.gperf" + {"natur", 3, {226, 153, 174}}, +#line 1002 "src/html/html_unescape.gperf" + {"Lsh", 3, {226, 134, 176}}, +#line 746 "src/html/html_unescape.gperf" + {"infin", 3, {226, 136, 158}}, + {(char*)0}, +#line 284 "src/html/html_unescape.gperf" + {"comp", 3, {226, 136, 129}}, + {(char*)0}, +#line 1685 "src/html/html_unescape.gperf" + {"sigmav", 2, {207, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2078 "src/html/html_unescape.gperf" + {"xotime", 3, {226, 168, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1401 "src/html/html_unescape.gperf" + {"Pfr", 4, {240, 157, 148, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 619 "src/html/html_unescape.gperf" + {"Gfr", 4, {240, 157, 148, 138}}, + {(char*)0}, {(char*)0}, +#line 116 "src/html/html_unescape.gperf" + {"bigcap", 3, {226, 139, 130}}, + {(char*)0}, +#line 1693 "src/html/html_unescape.gperf" + {"simlE", 3, {226, 170, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 727 "src/html/html_unescape.gperf" + {"iiiint", 3, {226, 168, 140}}, +#line 96 "src/html/html_unescape.gperf" + {"barwedge", 3, {226, 140, 133}}, +#line 95 "src/html/html_unescape.gperf" + {"Barwed", 3, {226, 140, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2070 "src/html/html_unescape.gperf" + {"xlarr", 3, {226, 159, 181}}, +#line 924 "src/html/html_unescape.gperf" + {"LessEqualGreater", 3, {226, 139, 154}}, + {(char*)0}, +#line 302 "src/html/html_unescape.gperf" + {"crarr", 3, {226, 134, 181}}, +#line 773 "src/html/html_unescape.gperf" + {"isindot", 3, {226, 139, 181}}, + {(char*)0}, +#line 283 "src/html/html_unescape.gperf" + {"commat", 1, {64}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1055 "src/html/html_unescape.gperf" + {"middot", 2, {194, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 917 "src/html/html_unescape.gperf" + {"lesdotor", 3, {226, 170, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1684 "src/html/html_unescape.gperf" + {"sigmaf", 2, {207, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1500 "src/html/html_unescape.gperf" + {"rarrbfs", 3, {226, 164, 160}}, + {(char*)0}, +#line 833 "src/html/html_unescape.gperf" + {"larrbfs", 3, {226, 164, 159}}, + {(char*)0}, {(char*)0}, +#line 2079 "src/html/html_unescape.gperf" + {"xrarr", 3, {226, 159, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 118 "src/html/html_unescape.gperf" + {"bigcup", 3, {226, 139, 131}}, + {(char*)0}, +#line 275 "src/html/html_unescape.gperf" + {"clubs", 3, {226, 153, 163}}, +#line 678 "src/html/html_unescape.gperf" + {"hArr", 3, {226, 135, 148}}, +#line 1626 "src/html/html_unescape.gperf" + {"rtrie", 3, {226, 138, 181}}, + {(char*)0}, +#line 1022 "src/html/html_unescape.gperf" + {"ltrie", 3, {226, 138, 180}}, +#line 742 "src/html/html_unescape.gperf" + {"imped", 2, {198, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 503 "src/html/html_unescape.gperf" + {"eogon", 2, {196, 153}}, +#line 1631 "src/html/html_unescape.gperf" + {"rx", 3, {226, 132, 158}}, +#line 1024 "src/html/html_unescape.gperf" + {"ltrPar", 3, {226, 166, 150}}, +#line 1747 "src/html/html_unescape.gperf" + {"Star", 3, {226, 139, 134}}, + {(char*)0}, +#line 1943 "src/html/html_unescape.gperf" + {"uogon", 2, {197, 179}}, + {(char*)0}, {(char*)0}, +#line 1856 "src/html/html_unescape.gperf" + {"Tilde", 3, {226, 136, 188}}, + {(char*)0}, +#line 672 "src/html/html_unescape.gperf" + {"half", 2, {194, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1855 "src/html/html_unescape.gperf" + {"tilde", 2, {203, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 876 "src/html/html_unescape.gperf" + {"Leftarrow", 3, {226, 135, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 618 "src/html/html_unescape.gperf" + {"gesles", 3, {226, 170, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 218 "src/html/html_unescape.gperf" + {"cap", 3, {226, 136, 169}}, +#line 1752 "src/html/html_unescape.gperf" + {"strns", 2, {194, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1015 "src/html/html_unescape.gperf" + {"Lt", 3, {226, 137, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1454 "src/html/html_unescape.gperf" + {"prnE", 3, {226, 170, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1727 "src/html/html_unescape.gperf" + {"sqsupe", 3, {226, 138, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1728 "src/html/html_unescape.gperf" + {"sqsupset", 3, {226, 138, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1883 "src/html/html_unescape.gperf" + {"tridot", 3, {226, 151, 172}}, +#line 1361 "src/html/html_unescape.gperf" + {"order", 3, {226, 132, 180}}, + {(char*)0}, {(char*)0}, +#line 223 "src/html/html_unescape.gperf" + {"caps", 3, {226, 136, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 303 "src/html/html_unescape.gperf" + {"cross", 3, {226, 156, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 367 "src/html/html_unescape.gperf" + {"dfisht", 3, {226, 165, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2072 "src/html/html_unescape.gperf" + {"xmap", 3, {226, 159, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1726 "src/html/html_unescape.gperf" + {"sqsup", 3, {226, 138, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1625 "src/html/html_unescape.gperf" + {"rtri", 3, {226, 150, 185}}, + {(char*)0}, +#line 1021 "src/html/html_unescape.gperf" + {"ltri", 3, {226, 151, 131}}, +#line 778 "src/html/html_unescape.gperf" + {"it", 3, {226, 129, 162}}, +#line 1599 "src/html/html_unescape.gperf" + {"rmoust", 3, {226, 142, 177}}, + {(char*)0}, +#line 955 "src/html/html_unescape.gperf" + {"lmoust", 3, {226, 142, 176}}, +#line 634 "src/html/html_unescape.gperf" + {"gnE", 3, {226, 137, 169}}, +#line 937 "src/html/html_unescape.gperf" + {"lgE", 3, {226, 170, 145}}, + {(char*)0}, {(char*)0}, +#line 1642 "src/html/html_unescape.gperf" + {"scE", 3, {226, 170, 180}}, + {(char*)0}, +#line 1979 "src/html/html_unescape.gperf" + {"utri", 3, {226, 150, 181}}, + {(char*)0}, +#line 2017 "src/html/html_unescape.gperf" + {"vellip", 3, {226, 139, 174}}, + {(char*)0}, +#line 535 "src/html/html_unescape.gperf" + {"ETH", 2, {195, 144}}, + {(char*)0}, {(char*)0}, +#line 953 "src/html/html_unescape.gperf" + {"lmidot", 2, {197, 128}}, + {(char*)0}, +#line 1942 "src/html/html_unescape.gperf" + {"Uogon", 2, {197, 178}}, +#line 301 "src/html/html_unescape.gperf" + {"CounterClockwiseContourIntegral", 3, {226, 136, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1121 "src/html/html_unescape.gperf" + {"ngE", 3, {226, 137, 167}}, +#line 1310 "src/html/html_unescape.gperf" + {"nwnear", 3, {226, 164, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 918 "src/html/html_unescape.gperf" + {"lesg", 3, {226, 139, 154}}, + {(char*)0}, {(char*)0}, +#line 1416 "src/html/html_unescape.gperf" + {"plusb", 3, {226, 138, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1619 "src/html/html_unescape.gperf" + {"Rsh", 3, {226, 134, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 300 "src/html/html_unescape.gperf" + {"copysr", 3, {226, 132, 151}}, + {(char*)0}, +#line 747 "src/html/html_unescape.gperf" + {"infintie", 3, {226, 167, 157}}, + {(char*)0}, +#line 739 "src/html/html_unescape.gperf" + {"imath", 2, {196, 177}}, +#line 531 "src/html/html_unescape.gperf" + {"Esim", 3, {226, 169, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1403 "src/html/html_unescape.gperf" + {"Phi", 2, {206, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 629 "src/html/html_unescape.gperf" + {"glE", 3, {226, 170, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2031 "src/html/html_unescape.gperf" + {"vnsup", 3, {226, 138, 131}}, + {(char*)0}, {(char*)0}, +#line 1691 "src/html/html_unescape.gperf" + {"simgE", 3, {226, 170, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 414 "src/html/html_unescape.gperf" + {"DoubleLongLeftArrow", 3, {226, 159, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 415 "src/html/html_unescape.gperf" + {"DoubleLongLeftRightArrow", 3, {226, 159, 186}}, + {(char*)0}, {(char*)0}, +#line 1296 "src/html/html_unescape.gperf" + {"nvgt", 1, {62}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1047 "src/html/html_unescape.gperf" + {"Mellintrf", 3, {226, 132, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1451 "src/html/html_unescape.gperf" + {"Prime", 3, {226, 128, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 729 "src/html/html_unescape.gperf" + {"iinfin", 3, {226, 167, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1547 "src/html/html_unescape.gperf" + {"ReverseElement", 3, {226, 136, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 493 "src/html/html_unescape.gperf" + {"EmptySmallSquare", 3, {226, 151, 187}}, +#line 1490 "src/html/html_unescape.gperf" + {"radic", 3, {226, 136, 154}}, + {(char*)0}, {(char*)0}, +#line 688 "src/html/html_unescape.gperf" + {"hfr", 4, {240, 157, 148, 165}}, +#line 2116 "src/html/html_unescape.gperf" + {"zdot", 2, {197, 188}}, +#line 1030 "src/html/html_unescape.gperf" + {"male", 3, {226, 153, 130}}, + {(char*)0}, +#line 1501 "src/html/html_unescape.gperf" + {"rarrc", 3, {226, 164, 179}}, +#line 1437 "src/html/html_unescape.gperf" + {"prec", 3, {226, 137, 186}}, +#line 1647 "src/html/html_unescape.gperf" + {"scnap", 3, {226, 170, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 384 "src/html/html_unescape.gperf" + {"DifferentialD", 3, {226, 133, 134}}, + {(char*)0}, +#line 1064 "src/html/html_unescape.gperf" + {"models", 3, {226, 138, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1012 "src/html/html_unescape.gperf" + {"ltcir", 3, {226, 169, 185}}, +#line 763 "src/html/html_unescape.gperf" + {"iogon", 2, {196, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 217 "src/html/html_unescape.gperf" + {"capcap", 3, {226, 169, 139}}, + {(char*)0}, +#line 721 "src/html/html_unescape.gperf" + {"iff", 3, {226, 135, 148}}, + {(char*)0}, +#line 361 "src/html/html_unescape.gperf" + {"ddotseq", 3, {226, 169, 183}}, + {(char*)0}, +#line 264 "src/html/html_unescape.gperf" + {"CirclePlus", 3, {226, 138, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1623 "src/html/html_unescape.gperf" + {"rthree", 3, {226, 139, 140}}, + {(char*)0}, +#line 1017 "src/html/html_unescape.gperf" + {"lthree", 3, {226, 139, 139}}, + {(char*)0}, {(char*)0}, +#line 1442 "src/html/html_unescape.gperf" + {"PrecedesTilde", 3, {226, 137, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 450 "src/html/html_unescape.gperf" + {"dtdot", 3, {226, 139, 177}}, + {(char*)0}, +#line 276 "src/html/html_unescape.gperf" + {"clubsuit", 3, {226, 153, 163}}, + {(char*)0}, +#line 1489 "src/html/html_unescape.gperf" + {"racute", 2, {197, 149}}, + {(char*)0}, +#line 820 "src/html/html_unescape.gperf" + {"lacute", 2, {196, 186}}, +#line 1890 "src/html/html_unescape.gperf" + {"trpezium", 3, {226, 143, 162}}, +#line 1633 "src/html/html_unescape.gperf" + {"sacute", 2, {197, 155}}, + {(char*)0}, {(char*)0}, +#line 2109 "src/html/html_unescape.gperf" + {"Zacute", 2, {197, 185}}, +#line 460 "src/html/html_unescape.gperf" + {"eacute", 2, {195, 169}}, + {(char*)0}, +#line 1859 "src/html/html_unescape.gperf" + {"TildeTilde", 3, {226, 137, 136}}, + {(char*)0}, +#line 1907 "src/html/html_unescape.gperf" + {"Uarrocir", 3, {226, 165, 137}}, +#line 1903 "src/html/html_unescape.gperf" + {"uacute", 2, {195, 186}}, +#line 983 "src/html/html_unescape.gperf" + {"lowast", 3, {226, 136, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1077 "src/html/html_unescape.gperf" + {"nacute", 2, {197, 132}}, + {(char*)0}, +#line 1207 "src/html/html_unescape.gperf" + {"NotPrecedes", 3, {226, 138, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 952 "src/html/html_unescape.gperf" + {"Lmidot", 2, {196, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1948 "src/html/html_unescape.gperf" + {"UpArrow", 3, {226, 134, 145}}, + {(char*)0}, +#line 1512 "src/html/html_unescape.gperf" + {"rarrw", 3, {226, 134, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 439 "src/html/html_unescape.gperf" + {"DownTee", 3, {226, 138, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 556 "src/html/html_unescape.gperf" + {"FilledSmallSquare", 3, {226, 151, 188}}, +#line 220 "src/html/html_unescape.gperf" + {"capcup", 3, {226, 169, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 643 "src/html/html_unescape.gperf" + {"GreaterFullEqual", 3, {226, 137, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1300 "src/html/html_unescape.gperf" + {"nvle", 3, {226, 137, 164}}, + {(char*)0}, +#line 1884 "src/html/html_unescape.gperf" + {"trie", 3, {226, 137, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1347 "src/html/html_unescape.gperf" + {"omicron", 2, {206, 191}}, + {(char*)0}, +#line 418 "src/html/html_unescape.gperf" + {"DoubleRightTee", 3, {226, 138, 168}}, +#line 234 "src/html/html_unescape.gperf" + {"Cconint", 3, {226, 136, 176}}, +#line 1622 "src/html/html_unescape.gperf" + {"rsquor", 3, {226, 128, 153}}, + {(char*)0}, +#line 1008 "src/html/html_unescape.gperf" + {"lsquor", 3, {226, 128, 154}}, + {(char*)0}, +#line 2125 "src/html/html_unescape.gperf" + {"zigrarr", 3, {226, 135, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 294 "src/html/html_unescape.gperf" + {"copf", 4, {240, 157, 149, 148}}, + {(char*)0}, +#line 293 "src/html/html_unescape.gperf" + {"ContourIntegral", 3, {226, 136, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 671 "src/html/html_unescape.gperf" + {"hairsp", 3, {226, 128, 138}}, +#line 1729 "src/html/html_unescape.gperf" + {"sqsupseteq", 3, {226, 138, 146}}, +#line 307 "src/html/html_unescape.gperf" + {"csub", 3, {226, 171, 143}}, +#line 1956 "src/html/html_unescape.gperf" + {"upharpoonright", 3, {226, 134, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 427 "src/html/html_unescape.gperf" + {"DownBreve", 2, {204, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1675 "src/html/html_unescape.gperf" + {"ShortDownArrow", 3, {226, 134, 147}}, + {(char*)0}, +#line 2076 "src/html/html_unescape.gperf" + {"xopf", 4, {240, 157, 149, 169}}, + {(char*)0}, +#line 1632 "src/html/html_unescape.gperf" + {"Sacute", 2, {197, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2040 "src/html/html_unescape.gperf" + {"vsupnE", 3, {226, 171, 140}}, +#line 266 "src/html/html_unescape.gperf" + {"cir", 3, {226, 151, 139}}, +#line 1415 "src/html/html_unescape.gperf" + {"plusacir", 3, {226, 168, 163}}, +#line 309 "src/html/html_unescape.gperf" + {"csup", 3, {226, 171, 144}}, +#line 2038 "src/html/html_unescape.gperf" + {"vsubnE", 3, {226, 171, 139}}, +#line 1902 "src/html/html_unescape.gperf" + {"Uacute", 2, {195, 154}}, + {(char*)0}, +#line 774 "src/html/html_unescape.gperf" + {"isinE", 3, {226, 139, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 607 "src/html/html_unescape.gperf" + {"gEl", 3, {226, 170, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1720 "src/html/html_unescape.gperf" + {"sqcups", 3, {226, 138, 148}}, + {(char*)0}, +#line 1702 "src/html/html_unescape.gperf" + {"smid", 3, {226, 136, 163}}, + {(char*)0}, +#line 936 "src/html/html_unescape.gperf" + {"lg", 3, {226, 137, 182}}, + {(char*)0}, +#line 416 "src/html/html_unescape.gperf" + {"DoubleLongRightArrow", 3, {226, 159, 185}}, +#line 1209 "src/html/html_unescape.gperf" + {"NotPrecedesSlantEqual", 3, {226, 139, 160}}, + {(char*)0}, {(char*)0}, +#line 478 "src/html/html_unescape.gperf" + {"eg", 3, {226, 170, 154}}, + {(char*)0}, {(char*)0}, +#line 34 "src/html/html_unescape.gperf" + {"AMP", 1, {38}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1163 "src/html/html_unescape.gperf" + {"nmid", 3, {226, 136, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1863 "src/html/html_unescape.gperf" + {"timesd", 3, {226, 168, 176}}, + {(char*)0}, {(char*)0}, +#line 434 "src/html/html_unescape.gperf" + {"DownLeftVector", 3, {226, 134, 189}}, +#line 2131 "src/html/html_unescape.gperf" + {"zwnj", 3, {226, 128, 140}}, +#line 819 "src/html/html_unescape.gperf" + {"Lacute", 2, {196, 185}}, +#line 433 "src/html/html_unescape.gperf" + {"DownLeftVectorBar", 3, {226, 165, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1332 "src/html/html_unescape.gperf" + {"ograve", 2, {195, 178}}, +#line 2088 "src/html/html_unescape.gperf" + {"Yacute", 2, {195, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1719 "src/html/html_unescape.gperf" + {"sqcup", 3, {226, 138, 148}}, + {(char*)0}, {(char*)0}, +#line 1323 "src/html/html_unescape.gperf" + {"odot", 3, {226, 138, 153}}, +#line 213 "src/html/html_unescape.gperf" + {"Cacute", 2, {196, 134}}, + {(char*)0}, +#line 1286 "src/html/html_unescape.gperf" + {"nu", 2, {206, 189}}, +#line 1889 "src/html/html_unescape.gperf" + {"tritime", 3, {226, 168, 187}}, + {(char*)0}, +#line 479 "src/html/html_unescape.gperf" + {"Egrave", 2, {195, 136}}, +#line 508 "src/html/html_unescape.gperf" + {"eplus", 3, {226, 169, 177}}, + {(char*)0}, +#line 86 "src/html/html_unescape.gperf" + {"backcong", 3, {226, 137, 140}}, + {(char*)0}, {(char*)0}, +#line 1957 "src/html/html_unescape.gperf" + {"uplus", 3, {226, 138, 142}}, + {(char*)0}, +#line 471 "src/html/html_unescape.gperf" + {"Edot", 2, {196, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 310 "src/html/html_unescape.gperf" + {"csupe", 3, {226, 171, 146}}, + {(char*)0}, +#line 1690 "src/html/html_unescape.gperf" + {"simg", 3, {226, 170, 158}}, +#line 1959 "src/html/html_unescape.gperf" + {"UpperRightArrow", 3, {226, 134, 151}}, +#line 308 "src/html/html_unescape.gperf" + {"csube", 3, {226, 171, 145}}, + {(char*)0}, +#line 451 "src/html/html_unescape.gperf" + {"dtri", 3, {226, 150, 191}}, +#line 1455 "src/html/html_unescape.gperf" + {"prnsim", 3, {226, 139, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 178 "src/html/html_unescape.gperf" + {"boxUr", 3, {226, 149, 153}}, +#line 1981 "src/html/html_unescape.gperf" + {"uuarr", 3, {226, 135, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 432 "src/html/html_unescape.gperf" + {"DownLeftTeeVector", 3, {226, 165, 158}}, +#line 651 "src/html/html_unescape.gperf" + {"gsime", 3, {226, 170, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 121 "src/html/html_unescape.gperf" + {"bigotimes", 3, {226, 168, 130}}, +#line 342 "src/html/html_unescape.gperf" + {"Dagger", 3, {226, 128, 161}}, + {(char*)0}, {(char*)0}, +#line 755 "src/html/html_unescape.gperf" + {"Intersection", 3, {226, 139, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 711 "src/html/html_unescape.gperf" + {"iacute", 2, {195, 173}}, + {(char*)0}, +#line 1435 "src/html/html_unescape.gperf" + {"prcue", 3, {226, 137, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 482 "src/html/html_unescape.gperf" + {"egsdot", 3, {226, 170, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 743 "src/html/html_unescape.gperf" + {"Implies", 3, {226, 135, 146}}, +#line 2011 "src/html/html_unescape.gperf" + {"VDash", 3, {226, 138, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 208 "src/html/html_unescape.gperf" + {"bump", 3, {226, 137, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1071 "src/html/html_unescape.gperf" + {"Mu", 2, {206, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2009 "src/html/html_unescape.gperf" + {"vDash", 3, {226, 138, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1028 "src/html/html_unescape.gperf" + {"lvnE", 3, {226, 137, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 895 "src/html/html_unescape.gperf" + {"LeftTeeArrow", 3, {226, 134, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1076 "src/html/html_unescape.gperf" + {"Nacute", 2, {197, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1937 "src/html/html_unescape.gperf" + {"UnderBrace", 3, {226, 143, 159}}, +#line 1469 "src/html/html_unescape.gperf" + {"Psi", 2, {206, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1560 "src/html/html_unescape.gperf" + {"rhov", 2, {207, 177}}, + {(char*)0}, +#line 913 "src/html/html_unescape.gperf" + {"lescc", 3, {226, 170, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1790 "src/html/html_unescape.gperf" + {"sup1", 2, {194, 185}}, + {(char*)0}, {(char*)0}, +#line 1791 "src/html/html_unescape.gperf" + {"sup2", 2, {194, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1792 "src/html/html_unescape.gperf" + {"sup3", 2, {194, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 119 "src/html/html_unescape.gperf" + {"bigodot", 3, {226, 168, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 425 "src/html/html_unescape.gperf" + {"Downarrow", 3, {226, 135, 147}}, + {(char*)0}, +#line 2083 "src/html/html_unescape.gperf" + {"xsqcup", 3, {226, 168, 134}}, + {(char*)0}, +#line 93 "src/html/html_unescape.gperf" + {"barvee", 3, {226, 138, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1107 "src/html/html_unescape.gperf" + {"NegativeMediumSpace", 3, {226, 128, 139}}, +#line 210 "src/html/html_unescape.gperf" + {"bumpe", 3, {226, 137, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 306 "src/html/html_unescape.gperf" + {"cscr", 4, {240, 157, 146, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1249 "src/html/html_unescape.gperf" + {"nsc", 3, {226, 138, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1793 "src/html/html_unescape.gperf" + {"sup", 3, {226, 138, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 239 "src/html/html_unescape.gperf" + {"cedil", 2, {194, 184}}, + {(char*)0}, {(char*)0}, +#line 192 "src/html/html_unescape.gperf" + {"boxVr", 3, {226, 149, 159}}, + {(char*)0}, +#line 1365 "src/html/html_unescape.gperf" + {"origof", 3, {226, 138, 182}}, +#line 2130 "src/html/html_unescape.gperf" + {"zwj", 3, {226, 128, 141}}, +#line 724 "src/html/html_unescape.gperf" + {"Igrave", 2, {195, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 717 "src/html/html_unescape.gperf" + {"Idot", 2, {196, 176}}, + {(char*)0}, +#line 2082 "src/html/html_unescape.gperf" + {"xscr", 4, {240, 157, 147, 141}}, +#line 2069 "src/html/html_unescape.gperf" + {"xi", 2, {206, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1132 "src/html/html_unescape.gperf" + {"nGtv", 3, {226, 137, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 166 "src/html/html_unescape.gperf" + {"boxHu", 3, {226, 149, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1853 "src/html/html_unescape.gperf" + {"THORN", 2, {195, 158}}, + {(char*)0}, +#line 1488 "src/html/html_unescape.gperf" + {"Racute", 2, {197, 148}}, + {(char*)0}, +#line 1506 "src/html/html_unescape.gperf" + {"rarrhk", 3, {226, 134, 170}}, + {(char*)0}, +#line 838 "src/html/html_unescape.gperf" + {"larrhk", 3, {226, 134, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1628 "src/html/html_unescape.gperf" + {"rtriltri", 3, {226, 167, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 181 "src/html/html_unescape.gperf" + {"boxV", 3, {226, 149, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 341 "src/html/html_unescape.gperf" + {"dagger", 3, {226, 128, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1346 "src/html/html_unescape.gperf" + {"Omicron", 2, {206, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 421 "src/html/html_unescape.gperf" + {"DoubleVerticalBar", 3, {226, 136, 165}}, + {(char*)0}, {(char*)0}, +#line 1118 "src/html/html_unescape.gperf" + {"nexists", 3, {226, 136, 132}}, + {(char*)0}, {(char*)0}, +#line 1285 "src/html/html_unescape.gperf" + {"Nu", 2, {206, 157}}, +#line 1117 "src/html/html_unescape.gperf" + {"nexist", 3, {226, 136, 132}}, +#line 606 "src/html/html_unescape.gperf" + {"gE", 3, {226, 137, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 64 "src/html/html_unescape.gperf" + {"ap", 3, {226, 137, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1794 "src/html/html_unescape.gperf" + {"Sup", 3, {226, 139, 145}}, +#line 402 "src/html/html_unescape.gperf" + {"doteqdot", 3, {226, 137, 145}}, + {(char*)0}, {(char*)0}, +#line 500 "src/html/html_unescape.gperf" + {"eng", 2, {197, 139}}, + {(char*)0}, +#line 225 "src/html/html_unescape.gperf" + {"caron", 2, {203, 135}}, + {(char*)0}, +#line 168 "src/html/html_unescape.gperf" + {"boxHU", 3, {226, 149, 169}}, +#line 614 "src/html/html_unescape.gperf" + {"gesdot", 3, {226, 170, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1548 "src/html/html_unescape.gperf" + {"ReverseEquilibrium", 3, {226, 135, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 175 "src/html/html_unescape.gperf" + {"boxUL", 3, {226, 149, 157}}, + {(char*)0}, +#line 1805 "src/html/html_unescape.gperf" + {"supmult", 3, {226, 171, 130}}, + {(char*)0}, {(char*)0}, +#line 1410 "src/html/html_unescape.gperf" + {"pitchfork", 3, {226, 139, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1289 "src/html/html_unescape.gperf" + {"numsp", 3, {226, 128, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1492 "src/html/html_unescape.gperf" + {"rang", 3, {226, 159, 169}}, + {(char*)0}, +#line 825 "src/html/html_unescape.gperf" + {"lang", 3, {226, 159, 168}}, + {(char*)0}, {(char*)0}, +#line 1316 "src/html/html_unescape.gperf" + {"ocir", 3, {226, 138, 154}}, + {(char*)0}, +#line 1516 "src/html/html_unescape.gperf" + {"rationals", 3, {226, 132, 154}}, + {(char*)0}, +#line 296 "src/html/html_unescape.gperf" + {"coprod", 3, {226, 136, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1019 "src/html/html_unescape.gperf" + {"ltlarr", 3, {226, 165, 182}}, +#line 195 "src/html/html_unescape.gperf" + {"breve", 2, {203, 152}}, + {(char*)0}, +#line 1078 "src/html/html_unescape.gperf" + {"nang", 3, {226, 136, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1818 "src/html/html_unescape.gperf" + {"swarhk", 3, {226, 164, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1497 "src/html/html_unescape.gperf" + {"raquo", 2, {194, 187}}, + {(char*)0}, +#line 831 "src/html/html_unescape.gperf" + {"laquo", 2, {194, 171}}, +#line 1816 "src/html/html_unescape.gperf" + {"supsub", 3, {226, 171, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 322 "src/html/html_unescape.gperf" + {"Cup", 3, {226, 139, 147}}, +#line 66 "src/html/html_unescape.gperf" + {"ape", 3, {226, 137, 138}}, +#line 1482 "src/html/html_unescape.gperf" + {"quest", 1, {63}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1306 "src/html/html_unescape.gperf" + {"nwarhk", 3, {226, 164, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1809 "src/html/html_unescape.gperf" + {"supset", 3, {226, 138, 131}}, + {(char*)0}, +#line 423 "src/html/html_unescape.gperf" + {"downarrow", 3, {226, 134, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 453 "src/html/html_unescape.gperf" + {"duarr", 3, {226, 135, 181}}, + {(char*)0}, +#line 68 "src/html/html_unescape.gperf" + {"apos", 1, {39}}, +#line 1331 "src/html/html_unescape.gperf" + {"Ograve", 2, {195, 146}}, +#line 1678 "src/html/html_unescape.gperf" + {"shortparallel", 3, {226, 136, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1269 "src/html/html_unescape.gperf" + {"nsucc", 3, {226, 138, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 967 "src/html/html_unescape.gperf" + {"LongLeftArrow", 3, {226, 159, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 916 "src/html/html_unescape.gperf" + {"lesdoto", 3, {226, 170, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1807 "src/html/html_unescape.gperf" + {"supne", 3, {226, 138, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1127 "src/html/html_unescape.gperf" + {"nGg", 3, {226, 139, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1491 "src/html/html_unescape.gperf" + {"raemptyv", 3, {226, 166, 179}}, +#line 1817 "src/html/html_unescape.gperf" + {"supsup", 3, {226, 171, 150}}, +#line 821 "src/html/html_unescape.gperf" + {"laemptyv", 3, {226, 166, 180}}, + {(char*)0}, {(char*)0}, +#line 1871 "src/html/html_unescape.gperf" + {"topfork", 3, {226, 171, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 502 "src/html/html_unescape.gperf" + {"Eogon", 2, {196, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1594 "src/html/html_unescape.gperf" + {"risingdotseq", 3, {226, 137, 147}}, + {(char*)0}, +#line 212 "src/html/html_unescape.gperf" + {"bumpeq", 3, {226, 137, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1010 "src/html/html_unescape.gperf" + {"lstrok", 2, {197, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1897 "src/html/html_unescape.gperf" + {"Tstrok", 2, {197, 166}}, +#line 650 "src/html/html_unescape.gperf" + {"gsim", 3, {226, 137, 179}}, + {(char*)0}, {(char*)0}, +#line 106 "src/html/html_unescape.gperf" + {"bemptyv", 3, {226, 166, 176}}, +#line 2110 "src/html/html_unescape.gperf" + {"zacute", 2, {197, 186}}, +#line 652 "src/html/html_unescape.gperf" + {"gsiml", 3, {226, 170, 144}}, + {(char*)0}, {(char*)0}, +#line 1898 "src/html/html_unescape.gperf" + {"tstrok", 2, {197, 167}}, + {(char*)0}, +#line 1601 "src/html/html_unescape.gperf" + {"roang", 3, {226, 159, 173}}, +#line 189 "src/html/html_unescape.gperf" + {"boxVL", 3, {226, 149, 163}}, +#line 963 "src/html/html_unescape.gperf" + {"loang", 3, {226, 159, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1153 "src/html/html_unescape.gperf" + {"nleqslant", 3, {226, 169, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1634 "src/html/html_unescape.gperf" + {"sbquo", 3, {226, 128, 154}}, + {(char*)0}, +#line 1657 "src/html/html_unescape.gperf" + {"searhk", 3, {226, 164, 165}}, +#line 957 "src/html/html_unescape.gperf" + {"lnapprox", 3, {226, 170, 137}}, + {(char*)0}, {(char*)0}, +#line 1810 "src/html/html_unescape.gperf" + {"Supset", 3, {226, 139, 145}}, + {(char*)0}, +#line 162 "src/html/html_unescape.gperf" + {"boxHd", 3, {226, 149, 164}}, +#line 1987 "src/html/html_unescape.gperf" + {"varkappa", 2, {207, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 254 "src/html/html_unescape.gperf" + {"circeq", 3, {226, 137, 151}}, + {(char*)0}, +#line 2102 "src/html/html_unescape.gperf" + {"yopf", 4, {240, 157, 149, 170}}, + {(char*)0}, +#line 1941 "src/html/html_unescape.gperf" + {"UnionPlus", 3, {226, 138, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 826 "src/html/html_unescape.gperf" + {"Lang", 3, {226, 159, 170}}, +#line 1101 "src/html/html_unescape.gperf" + {"nearhk", 3, {226, 164, 164}}, +#line 1674 "src/html/html_unescape.gperf" + {"shcy", 2, {209, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 245 "src/html/html_unescape.gperf" + {"cfr", 4, {240, 157, 148, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 800 "src/html/html_unescape.gperf" + {"Kappa", 2, {206, 154}}, +#line 944 "src/html/html_unescape.gperf" + {"ljcy", 2, {209, 153}}, +#line 1046 "src/html/html_unescape.gperf" + {"MediumSpace", 3, {226, 129, 159}}, + {(char*)0}, {(char*)0}, +#line 1811 "src/html/html_unescape.gperf" + {"supseteq", 3, {226, 138, 135}}, +#line 1812 "src/html/html_unescape.gperf" + {"supseteqq", 3, {226, 171, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1545 "src/html/html_unescape.gperf" + {"reg", 2, {194, 174}}, +#line 31 "src/html/html_unescape.gperf" + {"amacr", 2, {196, 129}}, +#line 909 "src/html/html_unescape.gperf" + {"leg", 3, {226, 139, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2050 "src/html/html_unescape.gperf" + {"weierp", 3, {226, 132, 152}}, +#line 1893 "src/html/html_unescape.gperf" + {"TScy", 2, {208, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1813 "src/html/html_unescape.gperf" + {"supsetneq", 3, {226, 138, 139}}, +#line 1141 "src/html/html_unescape.gperf" + {"njcy", 2, {209, 154}}, +#line 2065 "src/html/html_unescape.gperf" + {"xfr", 4, {240, 157, 148, 181}}, + {(char*)0}, +#line 1072 "src/html/html_unescape.gperf" + {"mu", 2, {206, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1298 "src/html/html_unescape.gperf" + {"nvinfin", 3, {226, 167, 158}}, +#line 179 "src/html/html_unescape.gperf" + {"boxUR", 3, {226, 149, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2077 "src/html/html_unescape.gperf" + {"xoplus", 3, {226, 168, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 887 "src/html/html_unescape.gperf" + {"leftleftarrows", 3, {226, 135, 135}}, +#line 1787 "src/html/html_unescape.gperf" + {"sum", 3, {226, 136, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 112 "src/html/html_unescape.gperf" + {"beth", 3, {226, 132, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 286 "src/html/html_unescape.gperf" + {"complement", 3, {226, 136, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1287 "src/html/html_unescape.gperf" + {"num", 1, {35}}, +#line 33 "src/html/html_unescape.gperf" + {"amp", 1, {38}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 174 "src/html/html_unescape.gperf" + {"boxUl", 3, {226, 149, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1177 "src/html/html_unescape.gperf" + {"NotGreater", 3, {226, 137, 175}}, +#line 170 "src/html/html_unescape.gperf" + {"boxplus", 3, {226, 138, 158}}, +#line 791 "src/html/html_unescape.gperf" + {"jmath", 2, {200, 183}}, + {(char*)0}, +#line 1669 "src/html/html_unescape.gperf" + {"sfrown", 3, {226, 140, 162}}, + {(char*)0}, +#line 448 "src/html/html_unescape.gperf" + {"Dstrok", 2, {196, 144}}, + {(char*)0}, +#line 37 "src/html/html_unescape.gperf" + {"and", 3, {226, 136, 167}}, +#line 1180 "src/html/html_unescape.gperf" + {"NotGreaterGreater", 3, {226, 137, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1182 "src/html/html_unescape.gperf" + {"NotGreaterSlantEqual", 3, {226, 169, 190}}, + {(char*)0}, +#line 1181 "src/html/html_unescape.gperf" + {"NotGreaterLess", 3, {226, 137, 185}}, +#line 1484 "src/html/html_unescape.gperf" + {"quot", 1, {34}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1179 "src/html/html_unescape.gperf" + {"NotGreaterFullEqual", 3, {226, 137, 167}}, +#line 709 "src/html/html_unescape.gperf" + {"hyphen", 3, {226, 128, 144}}, +#line 1412 "src/html/html_unescape.gperf" + {"planck", 3, {226, 132, 143}}, + {(char*)0}, +#line 1857 "src/html/html_unescape.gperf" + {"TildeEqual", 3, {226, 137, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1872 "src/html/html_unescape.gperf" + {"tosa", 3, {226, 164, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1009 "src/html/html_unescape.gperf" + {"Lstrok", 2, {197, 129}}, + {(char*)0}, {(char*)0}, +#line 1681 "src/html/html_unescape.gperf" + {"shy", 2, {194, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2073 "src/html/html_unescape.gperf" + {"xnis", 3, {226, 139, 187}}, +#line 762 "src/html/html_unescape.gperf" + {"Iogon", 2, {196, 174}}, + {(char*)0}, {(char*)0}, +#line 456 "src/html/html_unescape.gperf" + {"DZcy", 2, {208, 143}}, + {(char*)0}, +#line 1334 "src/html/html_unescape.gperf" + {"ohbar", 3, {226, 166, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 271 "src/html/html_unescape.gperf" + {"cirscir", 3, {226, 167, 130}}, + {(char*)0}, +#line 1666 "src/html/html_unescape.gperf" + {"sext", 3, {226, 156, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1387 "src/html/html_unescape.gperf" + {"para", 2, {194, 182}}, + {(char*)0}, {(char*)0}, +#line 77 "src/html/html_unescape.gperf" + {"ast", 1, {42}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1483 "src/html/html_unescape.gperf" + {"questeq", 3, {226, 137, 159}}, + {(char*)0}, +#line 1788 "src/html/html_unescape.gperf" + {"Sum", 3, {226, 136, 145}}, + {(char*)0}, +#line 445 "src/html/html_unescape.gperf" + {"DScy", 2, {208, 133}}, + {(char*)0}, +#line 499 "src/html/html_unescape.gperf" + {"ENG", 2, {197, 138}}, + {(char*)0}, +#line 2123 "src/html/html_unescape.gperf" + {"ZHcy", 2, {208, 150}}, + {(char*)0}, {(char*)0}, +#line 966 "src/html/html_unescape.gperf" + {"longleftarrow", 3, {226, 159, 181}}, + {(char*)0}, +#line 347 "src/html/html_unescape.gperf" + {"dash", 3, {226, 128, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 438 "src/html/html_unescape.gperf" + {"DownTeeArrow", 3, {226, 134, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1814 "src/html/html_unescape.gperf" + {"supsetneqq", 3, {226, 171, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1458 "src/html/html_unescape.gperf" + {"profalar", 3, {226, 140, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1312 "src/html/html_unescape.gperf" + {"oacute", 2, {195, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 193 "src/html/html_unescape.gperf" + {"boxVR", 3, {226, 149, 160}}, + {(char*)0}, {(char*)0}, +#line 459 "src/html/html_unescape.gperf" + {"Eacute", 2, {195, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1808 "src/html/html_unescape.gperf" + {"supplus", 3, {226, 171, 128}}, + {(char*)0}, +#line 695 "src/html/html_unescape.gperf" + {"hookleftarrow", 3, {226, 134, 169}}, + {(char*)0}, {(char*)0}, +#line 274 "src/html/html_unescape.gperf" + {"CloseCurlyQuote", 3, {226, 128, 153}}, + {(char*)0}, {(char*)0}, +#line 1888 "src/html/html_unescape.gperf" + {"trisb", 3, {226, 167, 141}}, +#line 406 "src/html/html_unescape.gperf" + {"dotsquare", 3, {226, 138, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1624 "src/html/html_unescape.gperf" + {"rtimes", 3, {226, 139, 138}}, + {(char*)0}, +#line 1018 "src/html/html_unescape.gperf" + {"ltimes", 3, {226, 139, 137}}, + {(char*)0}, {(char*)0}, +#line 1865 "src/html/html_unescape.gperf" + {"toea", 3, {226, 164, 168}}, +#line 24 "src/html/html_unescape.gperf" + {"Agrave", 2, {195, 128}}, + {(char*)0}, {(char*)0}, +#line 76 "src/html/html_unescape.gperf" + {"Assign", 3, {226, 137, 148}}, +#line 1493 "src/html/html_unescape.gperf" + {"Rang", 3, {226, 159, 171}}, +#line 761 "src/html/html_unescape.gperf" + {"iocy", 2, {209, 145}}, + {(char*)0}, +#line 1208 "src/html/html_unescape.gperf" + {"NotPrecedesEqual", 3, {226, 170, 175}}, + {(char*)0}, +#line 62 "src/html/html_unescape.gperf" + {"aopf", 4, {240, 157, 149, 146}}, + {(char*)0}, +#line 252 "src/html/html_unescape.gperf" + {"chi", 2, {207, 135}}, + {(char*)0}, {(char*)0}, +#line 1480 "src/html/html_unescape.gperf" + {"quaternions", 3, {226, 132, 141}}, +#line 188 "src/html/html_unescape.gperf" + {"boxVl", 3, {226, 149, 162}}, +#line 1178 "src/html/html_unescape.gperf" + {"NotGreaterEqual", 3, {226, 137, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2067 "src/html/html_unescape.gperf" + {"xhArr", 3, {226, 159, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1362 "src/html/html_unescape.gperf" + {"orderof", 3, {226, 132, 180}}, + {(char*)0}, {(char*)0}, +#line 1621 "src/html/html_unescape.gperf" + {"rsquo", 3, {226, 128, 153}}, + {(char*)0}, +#line 1007 "src/html/html_unescape.gperf" + {"lsquo", 3, {226, 128, 152}}, +#line 2104 "src/html/html_unescape.gperf" + {"yscr", 4, {240, 157, 147, 142}}, + {(char*)0}, {(char*)0}, +#line 604 "src/html/html_unescape.gperf" + {"gdot", 2, {196, 161}}, + {(char*)0}, +#line 1215 "src/html/html_unescape.gperf" + {"NotSquareSubsetEqual", 3, {226, 139, 162}}, +#line 810 "src/html/html_unescape.gperf" + {"KHcy", 2, {208, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 203 "src/html/html_unescape.gperf" + {"bsolb", 3, {226, 167, 133}}, +#line 1214 "src/html/html_unescape.gperf" + {"NotSquareSubset", 3, {226, 138, 143}}, +#line 1673 "src/html/html_unescape.gperf" + {"SHcy", 2, {208, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2099 "src/html/html_unescape.gperf" + {"YIcy", 2, {208, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 339 "src/html/html_unescape.gperf" + {"cwint", 3, {226, 136, 177}}, + {(char*)0}, {(char*)0}, +#line 1842 "src/html/html_unescape.gperf" + {"Theta", 2, {206, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1843 "src/html/html_unescape.gperf" + {"theta", 2, {206, 184}}, +#line 2071 "src/html/html_unescape.gperf" + {"xlArr", 3, {226, 159, 184}}, + {(char*)0}, +#line 1217 "src/html/html_unescape.gperf" + {"NotSquareSupersetEqual", 3, {226, 139, 163}}, + {(char*)0}, {(char*)0}, +#line 366 "src/html/html_unescape.gperf" + {"demptyv", 3, {226, 166, 177}}, +#line 1876 "src/html/html_unescape.gperf" + {"triangle", 3, {226, 150, 181}}, + {(char*)0}, +#line 603 "src/html/html_unescape.gperf" + {"Gdot", 2, {196, 160}}, + {(char*)0}, +#line 1216 "src/html/html_unescape.gperf" + {"NotSquareSuperset", 3, {226, 138, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 9 "src/html/html_unescape.gperf" + {"Abreve", 2, {196, 130}}, + {(char*)0}, {(char*)0}, +#line 449 "src/html/html_unescape.gperf" + {"dstrok", 2, {196, 145}}, +#line 1400 "src/html/html_unescape.gperf" + {"pertenk", 3, {226, 128, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1522 "src/html/html_unescape.gperf" + {"rbrack", 1, {93}}, + {(char*)0}, +#line 852 "src/html/html_unescape.gperf" + {"lbrack", 1, {91}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1324 "src/html/html_unescape.gperf" + {"odsold", 3, {226, 166, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1348 "src/html/html_unescape.gperf" + {"omid", 3, {226, 166, 182}}, + {(char*)0}, +#line 2080 "src/html/html_unescape.gperf" + {"xrArr", 3, {226, 159, 185}}, + {(char*)0}, +#line 1878 "src/html/html_unescape.gperf" + {"triangleleft", 3, {226, 151, 131}}, +#line 1183 "src/html/html_unescape.gperf" + {"NotGreaterTilde", 3, {226, 137, 181}}, +#line 280 "src/html/html_unescape.gperf" + {"colone", 3, {226, 137, 148}}, + {(char*)0}, +#line 968 "src/html/html_unescape.gperf" + {"Longleftarrow", 3, {226, 159, 184}}, + {(char*)0}, +#line 767 "src/html/html_unescape.gperf" + {"iota", 2, {206, 185}}, + {(char*)0}, +#line 277 "src/html/html_unescape.gperf" + {"colon", 1, {58}}, +#line 2119 "src/html/html_unescape.gperf" + {"Zeta", 2, {206, 150}}, +#line 597 "src/html/html_unescape.gperf" + {"gbreve", 2, {196, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 247 "src/html/html_unescape.gperf" + {"CHcy", 2, {208, 167}}, + {(char*)0}, {(char*)0}, +#line 2105 "src/html/html_unescape.gperf" + {"YUcy", 2, {208, 174}}, +#line 1546 "src/html/html_unescape.gperf" + {"REG", 2, {194, 174}}, +#line 1823 "src/html/html_unescape.gperf" + {"szlig", 2, {195, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 457 "src/html/html_unescape.gperf" + {"dzcy", 2, {209, 159}}, + {(char*)0}, +#line 111 "src/html/html_unescape.gperf" + {"beta", 2, {206, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 539 "src/html/html_unescape.gperf" + {"euro", 3, {226, 130, 172}}, + {(char*)0}, {(char*)0}, +#line 875 "src/html/html_unescape.gperf" + {"LeftArrow", 3, {226, 134, 144}}, + {(char*)0}, {(char*)0}, +#line 222 "src/html/html_unescape.gperf" + {"CapitalDifferentialD", 3, {226, 133, 133}}, + {(char*)0}, +#line 1593 "src/html/html_unescape.gperf" + {"ring", 2, {203, 154}}, +#line 830 "src/html/html_unescape.gperf" + {"Laplacetrf", 3, {226, 132, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 392 "src/html/html_unescape.gperf" + {"djcy", 2, {209, 146}}, + {(char*)0}, +#line 1356 "src/html/html_unescape.gperf" + {"oplus", 3, {226, 138, 149}}, + {(char*)0}, {(char*)0}, +#line 752 "src/html/html_unescape.gperf" + {"integers", 3, {226, 132, 164}}, +#line 596 "src/html/html_unescape.gperf" + {"Gbreve", 2, {196, 158}}, + {(char*)0}, +#line 1909 "src/html/html_unescape.gperf" + {"ubrcy", 2, {209, 158}}, +#line 538 "src/html/html_unescape.gperf" + {"euml", 2, {195, 171}}, + {(char*)0}, {(char*)0}, +#line 362 "src/html/html_unescape.gperf" + {"deg", 2, {194, 176}}, + {(char*)0}, +#line 1983 "src/html/html_unescape.gperf" + {"uuml", 2, {195, 188}}, + {(char*)0}, {(char*)0}, +#line 710 "src/html/html_unescape.gperf" + {"Iacute", 2, {195, 141}}, +#line 1781 "src/html/html_unescape.gperf" + {"succeq", 3, {226, 170, 176}}, + {(char*)0}, +#line 812 "src/html/html_unescape.gperf" + {"KJcy", 2, {208, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 320 "src/html/html_unescape.gperf" + {"CupCap", 3, {226, 137, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1894 "src/html/html_unescape.gperf" + {"tscy", 2, {209, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 242 "src/html/html_unescape.gperf" + {"cent", 2, {194, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 391 "src/html/html_unescape.gperf" + {"DJcy", 2, {208, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1858 "src/html/html_unescape.gperf" + {"TildeFullEqual", 3, {226, 137, 133}}, + {(char*)0}, +#line 1880 "src/html/html_unescape.gperf" + {"triangleq", 3, {226, 137, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 454 "src/html/html_unescape.gperf" + {"duhar", 3, {226, 165, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 880 "src/html/html_unescape.gperf" + {"LeftDoubleBracket", 3, {226, 159, 166}}, + {(char*)0}, +#line 943 "src/html/html_unescape.gperf" + {"LJcy", 2, {208, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 719 "src/html/html_unescape.gperf" + {"iecy", 2, {208, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1879 "src/html/html_unescape.gperf" + {"trianglelefteq", 3, {226, 138, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1111 "src/html/html_unescape.gperf" + {"nequiv", 3, {226, 137, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1255 "src/html/html_unescape.gperf" + {"nshortparallel", 3, {226, 136, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1100 "src/html/html_unescape.gperf" + {"ndash", 3, {226, 128, 147}}, +#line 149 "src/html/html_unescape.gperf" + {"bowtie", 3, {226, 139, 136}}, + {(char*)0}, +#line 558 "src/html/html_unescape.gperf" + {"fjlig", 1, {102}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1908 "src/html/html_unescape.gperf" + {"Ubrcy", 2, {208, 142}}, + {(char*)0}, +#line 2000 "src/html/html_unescape.gperf" + {"vartheta", 2, {207, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1982 "src/html/html_unescape.gperf" + {"Uuml", 2, {195, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2002 "src/html/html_unescape.gperf" + {"vartriangleright", 3, {226, 138, 179}}, +#line 2001 "src/html/html_unescape.gperf" + {"vartriangleleft", 3, {226, 138, 178}}, +#line 75 "src/html/html_unescape.gperf" + {"ascr", 4, {240, 157, 146, 182}}, + {(char*)0}, {(char*)0}, +#line 1776 "src/html/html_unescape.gperf" + {"succcurlyeq", 3, {226, 137, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 338 "src/html/html_unescape.gperf" + {"cwconint", 3, {226, 136, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1639 "src/html/html_unescape.gperf" + {"sc", 3, {226, 137, 187}}, + {(char*)0}, +#line 560 "src/html/html_unescape.gperf" + {"fllig", 3, {239, 172, 130}}, + {(char*)0}, +#line 257 "src/html/html_unescape.gperf" + {"circledast", 3, {226, 138, 155}}, + {(char*)0}, {(char*)0}, +#line 2010 "src/html/html_unescape.gperf" + {"Vdash", 3, {226, 138, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1293 "src/html/html_unescape.gperf" + {"nVdash", 3, {226, 138, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1804 "src/html/html_unescape.gperf" + {"suplarr", 3, {226, 165, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1603 "src/html/html_unescape.gperf" + {"robrk", 3, {226, 159, 167}}, + {(char*)0}, +#line 965 "src/html/html_unescape.gperf" + {"lobrk", 3, {226, 159, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2008 "src/html/html_unescape.gperf" + {"vdash", 3, {226, 138, 162}}, +#line 2108 "src/html/html_unescape.gperf" + {"Yuml", 2, {197, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 655 "src/html/html_unescape.gperf" + {"gt", 1, {62}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 227 "src/html/html_unescape.gperf" + {"ccaps", 3, {226, 169, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1777 "src/html/html_unescape.gperf" + {"Succeeds", 3, {226, 137, 187}}, +#line 1311 "src/html/html_unescape.gperf" + {"Oacute", 2, {195, 147}}, +#line 1875 "src/html/html_unescape.gperf" + {"TRADE", 3, {226, 132, 162}}, +#line 1140 "src/html/html_unescape.gperf" + {"NJcy", 2, {208, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 658 "src/html/html_unescape.gperf" + {"gtdot", 3, {226, 139, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2098 "src/html/html_unescape.gperf" + {"yfr", 4, {240, 157, 148, 182}}, + {(char*)0}, {(char*)0}, +#line 285 "src/html/html_unescape.gperf" + {"compfn", 3, {226, 136, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 657 "src/html/html_unescape.gperf" + {"Gt", 3, {226, 137, 171}}, +#line 1648 "src/html/html_unescape.gperf" + {"scnE", 3, {226, 170, 182}}, +#line 732 "src/html/html_unescape.gperf" + {"ijlig", 2, {196, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 262 "src/html/html_unescape.gperf" + {"circledS", 3, {226, 147, 136}}, + {(char*)0}, {(char*)0}, +#line 2096 "src/html/html_unescape.gperf" + {"yen", 2, {194, 165}}, + {(char*)0}, +#line 1844 "src/html/html_unescape.gperf" + {"thetasym", 2, {207, 145}}, + {(char*)0}, {(char*)0}, +#line 784 "src/html/html_unescape.gperf" + {"iuml", 2, {195, 175}}, +#line 1779 "src/html/html_unescape.gperf" + {"SucceedsSlantEqual", 3, {226, 137, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 160 "src/html/html_unescape.gperf" + {"boxH", 3, {226, 149, 144}}, +#line 1074 "src/html/html_unescape.gperf" + {"mumap", 3, {226, 138, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1578 "src/html/html_unescape.gperf" + {"rightrightarrows", 3, {226, 135, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 281 "src/html/html_unescape.gperf" + {"coloneq", 3, {226, 137, 148}}, + {(char*)0}, +#line 1638 "src/html/html_unescape.gperf" + {"Sc", 3, {226, 170, 188}}, +#line 630 "src/html/html_unescape.gperf" + {"glj", 3, {226, 170, 164}}, +#line 720 "src/html/html_unescape.gperf" + {"iexcl", 2, {194, 161}}, + {(char*)0}, {(char*)0}, +#line 235 "src/html/html_unescape.gperf" + {"ccups", 3, {226, 169, 140}}, + {(char*)0}, +#line 2060 "src/html/html_unescape.gperf" + {"xcap", 3, {226, 139, 130}}, +#line 2124 "src/html/html_unescape.gperf" + {"zhcy", 2, {208, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 164 "src/html/html_unescape.gperf" + {"boxHD", 3, {226, 149, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 912 "src/html/html_unescape.gperf" + {"leqslant", 3, {226, 169, 189}}, + {(char*)0}, +#line 1958 "src/html/html_unescape.gperf" + {"UpperLeftArrow", 3, {226, 134, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 351 "src/html/html_unescape.gperf" + {"dblac", 2, {203, 157}}, + {(char*)0}, {(char*)0}, +#line 1471 "src/html/html_unescape.gperf" + {"puncsp", 3, {226, 128, 136}}, + {(char*)0}, +#line 229 "src/html/html_unescape.gperf" + {"ccaron", 2, {196, 141}}, + {(char*)0}, +#line 1520 "src/html/html_unescape.gperf" + {"rbbrk", 3, {226, 157, 179}}, + {(char*)0}, +#line 850 "src/html/html_unescape.gperf" + {"lbbrk", 3, {226, 157, 178}}, + {(char*)0}, +#line 59 "src/html/html_unescape.gperf" + {"Aogon", 2, {196, 132}}, +#line 899 "src/html/html_unescape.gperf" + {"LeftTriangleBar", 3, {226, 167, 143}}, + {(char*)0}, {(char*)0}, +#line 616 "src/html/html_unescape.gperf" + {"gesdotol", 3, {226, 170, 132}}, +#line 901 "src/html/html_unescape.gperf" + {"LeftTriangleEqual", 3, {226, 138, 180}}, +#line 900 "src/html/html_unescape.gperf" + {"LeftTriangle", 3, {226, 138, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 291 "src/html/html_unescape.gperf" + {"conint", 3, {226, 136, 174}}, + {(char*)0}, {(char*)0}, +#line 440 "src/html/html_unescape.gperf" + {"drbkarow", 3, {226, 164, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1627 "src/html/html_unescape.gperf" + {"rtrif", 3, {226, 150, 184}}, + {(char*)0}, +#line 1023 "src/html/html_unescape.gperf" + {"ltrif", 3, {226, 151, 130}}, + {(char*)0}, {(char*)0}, +#line 1549 "src/html/html_unescape.gperf" + {"ReverseUpEquilibrium", 3, {226, 165, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 879 "src/html/html_unescape.gperf" + {"LeftCeiling", 3, {226, 140, 136}}, + {(char*)0}, +#line 1980 "src/html/html_unescape.gperf" + {"utrif", 3, {226, 150, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2062 "src/html/html_unescape.gperf" + {"xcup", 3, {226, 139, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 546 "src/html/html_unescape.gperf" + {"fallingdotseq", 3, {226, 137, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1529 "src/html/html_unescape.gperf" + {"rcedil", 2, {197, 151}}, + {(char*)0}, +#line 859 "src/html/html_unescape.gperf" + {"lcedil", 2, {196, 188}}, + {(char*)0}, +#line 1644 "src/html/html_unescape.gperf" + {"scedil", 2, {197, 159}}, + {(char*)0}, +#line 1831 "src/html/html_unescape.gperf" + {"Tcedil", 2, {197, 162}}, + {(char*)0}, +#line 1749 "src/html/html_unescape.gperf" + {"starf", 3, {226, 152, 133}}, +#line 169 "src/html/html_unescape.gperf" + {"boxminus", 3, {226, 138, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1832 "src/html/html_unescape.gperf" + {"tcedil", 2, {197, 163}}, +#line 2118 "src/html/html_unescape.gperf" + {"ZeroWidthSpace", 3, {226, 128, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1094 "src/html/html_unescape.gperf" + {"ncedil", 2, {197, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1405 "src/html/html_unescape.gperf" + {"phiv", 2, {207, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 712 "src/html/html_unescape.gperf" + {"ic", 3, {226, 129, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 221 "src/html/html_unescape.gperf" + {"capdot", 3, {226, 169, 128}}, + {(char*)0}, {(char*)0}, +#line 446 "src/html/html_unescape.gperf" + {"dscy", 2, {209, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 249 "src/html/html_unescape.gperf" + {"check", 3, {226, 156, 147}}, +#line 1382 "src/html/html_unescape.gperf" + {"ovbar", 3, {226, 140, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1281 "src/html/html_unescape.gperf" + {"ntriangleleft", 3, {226, 139, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1581 "src/html/html_unescape.gperf" + {"RightTee", 3, {226, 138, 162}}, +#line 1295 "src/html/html_unescape.gperf" + {"nvge", 3, {226, 137, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 893 "src/html/html_unescape.gperf" + {"leftrightsquigarrow", 3, {226, 134, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 988 "src/html/html_unescape.gperf" + {"lozenge", 3, {226, 151, 138}}, + {(char*)0}, {(char*)0}, +#line 1584 "src/html/html_unescape.gperf" + {"RightTriangleBar", 3, {226, 167, 144}}, + {(char*)0}, +#line 1582 "src/html/html_unescape.gperf" + {"RightTeeVector", 3, {226, 165, 155}}, + {(char*)0}, +#line 1586 "src/html/html_unescape.gperf" + {"RightTriangleEqual", 3, {226, 138, 181}}, +#line 1585 "src/html/html_unescape.gperf" + {"RightTriangle", 3, {226, 138, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 803 "src/html/html_unescape.gperf" + {"Kcedil", 2, {196, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1643 "src/html/html_unescape.gperf" + {"Scedil", 2, {197, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 269 "src/html/html_unescape.gperf" + {"cirfnint", 3, {226, 168, 144}}, + {(char*)0}, {(char*)0}, +#line 491 "src/html/html_unescape.gperf" + {"empty", 3, {226, 136, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 23 "src/html/html_unescape.gperf" + {"afr", 4, {240, 157, 148, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 377 "src/html/html_unescape.gperf" + {"DiacriticalTilde", 2, {203, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 883 "src/html/html_unescape.gperf" + {"LeftDownVector", 3, {226, 135, 131}}, + {(char*)0}, {(char*)0}, +#line 882 "src/html/html_unescape.gperf" + {"LeftDownVectorBar", 3, {226, 165, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 908 "src/html/html_unescape.gperf" + {"lEg", 3, {226, 170, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 69 "src/html/html_unescape.gperf" + {"ApplyFunction", 3, {226, 129, 161}}, + {(char*)0}, {(char*)0}, +#line 209 "src/html/html_unescape.gperf" + {"bumpE", 3, {226, 170, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 858 "src/html/html_unescape.gperf" + {"Lcedil", 2, {196, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 224 "src/html/html_unescape.gperf" + {"caret", 3, {226, 129, 129}}, + {(char*)0}, +#line 92 "src/html/html_unescape.gperf" + {"Barv", 3, {226, 171, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 230 "src/html/html_unescape.gperf" + {"Ccedil", 2, {195, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 261 "src/html/html_unescape.gperf" + {"circledR", 2, {194, 174}}, +#line 881 "src/html/html_unescape.gperf" + {"LeftDownTeeVector", 3, {226, 165, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1896 "src/html/html_unescape.gperf" + {"tshcy", 2, {209, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 403 "src/html/html_unescape.gperf" + {"DotEqual", 3, {226, 137, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 243 "src/html/html_unescape.gperf" + {"centerdot", 2, {194, 183}}, + {(char*)0}, +#line 1282 "src/html/html_unescape.gperf" + {"ntrianglelefteq", 3, {226, 139, 172}}, + {(char*)0}, +#line 1057 "src/html/html_unescape.gperf" + {"minus", 3, {226, 136, 146}}, + {(char*)0}, +#line 624 "src/html/html_unescape.gperf" + {"gimel", 3, {226, 132, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 7 "src/html/html_unescape.gperf" + {"Aacute", 2, {195, 129}}, +#line 654 "src/html/html_unescape.gperf" + {"gtcir", 3, {226, 169, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 662 "src/html/html_unescape.gperf" + {"gtrarr", 3, {226, 165, 184}}, +#line 206 "src/html/html_unescape.gperf" + {"bull", 3, {226, 128, 162}}, + {(char*)0}, {(char*)0}, +#line 424 "src/html/html_unescape.gperf" + {"DownArrow", 3, {226, 134, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1537 "src/html/html_unescape.gperf" + {"rdquor", 3, {226, 128, 157}}, + {(char*)0}, +#line 866 "src/html/html_unescape.gperf" + {"ldquor", 3, {226, 128, 158}}, + {(char*)0}, {(char*)0}, +#line 756 "src/html/html_unescape.gperf" + {"intlarhk", 3, {226, 168, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1978 "src/html/html_unescape.gperf" + {"utilde", 2, {197, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 590 "src/html/html_unescape.gperf" + {"gacute", 2, {199, 181}}, + {(char*)0}, +#line 1279 "src/html/html_unescape.gperf" + {"ntilde", 2, {195, 177}}, +#line 21 "src/html/html_unescape.gperf" + {"af", 3, {226, 129, 161}}, + {(char*)0}, {(char*)0}, +#line 704 "src/html/html_unescape.gperf" + {"Hstrok", 2, {196, 166}}, + {(char*)0}, +#line 544 "src/html/html_unescape.gperf" + {"exponentiale", 3, {226, 133, 135}}, +#line 1056 "src/html/html_unescape.gperf" + {"minusb", 3, {226, 138, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1588 "src/html/html_unescape.gperf" + {"RightUpTeeVector", 3, {226, 165, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1965 "src/html/html_unescape.gperf" + {"UpTeeArrow", 3, {226, 134, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2120 "src/html/html_unescape.gperf" + {"zeta", 2, {206, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 374 "src/html/html_unescape.gperf" + {"DiacriticalDot", 2, {203, 153}}, +#line 375 "src/html/html_unescape.gperf" + {"DiacriticalDoubleAcute", 2, {203, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1147 "src/html/html_unescape.gperf" + {"nleftarrow", 3, {226, 134, 154}}, +#line 692 "src/html/html_unescape.gperf" + {"hkswarow", 3, {226, 164, 166}}, + {(char*)0}, +#line 730 "src/html/html_unescape.gperf" + {"iiota", 3, {226, 132, 169}}, + {(char*)0}, {(char*)0}, +#line 63 "src/html/html_unescape.gperf" + {"apacir", 3, {226, 169, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1093 "src/html/html_unescape.gperf" + {"Ncedil", 2, {197, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 215 "src/html/html_unescape.gperf" + {"capand", 3, {226, 169, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1043 "src/html/html_unescape.gperf" + {"mdash", 3, {226, 128, 148}}, + {(char*)0}, {(char*)0}, +#line 555 "src/html/html_unescape.gperf" + {"filig", 3, {239, 172, 129}}, +#line 1649 "src/html/html_unescape.gperf" + {"scnsim", 3, {226, 139, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1541 "src/html/html_unescape.gperf" + {"realpart", 3, {226, 132, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 898 "src/html/html_unescape.gperf" + {"leftthreetimes", 3, {226, 139, 139}}, +#line 78 "src/html/html_unescape.gperf" + {"asymp", 3, {226, 137, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 686 "src/html/html_unescape.gperf" + {"hellip", 3, {226, 128, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 452 "src/html/html_unescape.gperf" + {"dtrif", 3, {226, 150, 190}}, + {(char*)0}, +#line 1176 "src/html/html_unescape.gperf" + {"NotExists", 3, {226, 136, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1640 "src/html/html_unescape.gperf" + {"sccue", 3, {226, 137, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2090 "src/html/html_unescape.gperf" + {"YAcy", 2, {208, 175}}, +#line 1977 "src/html/html_unescape.gperf" + {"Utilde", 2, {197, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1174 "src/html/html_unescape.gperf" + {"NotEqual", 3, {226, 137, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1849 "src/html/html_unescape.gperf" + {"ThinSpace", 3, {226, 128, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 65 "src/html/html_unescape.gperf" + {"apE", 3, {226, 169, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 207 "src/html/html_unescape.gperf" + {"bullet", 3, {226, 128, 162}}, + {(char*)0}, {(char*)0}, +#line 273 "src/html/html_unescape.gperf" + {"CloseCurlyDoubleQuote", 3, {226, 128, 157}}, +#line 364 "src/html/html_unescape.gperf" + {"Delta", 2, {206, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 621 "src/html/html_unescape.gperf" + {"gg", 3, {226, 137, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1379 "src/html/html_unescape.gperf" + {"otimes", 3, {226, 138, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2057 "src/html/html_unescape.gperf" + {"wreath", 3, {226, 137, 128}}, + {(char*)0}, +#line 1528 "src/html/html_unescape.gperf" + {"Rcedil", 2, {197, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 536 "src/html/html_unescape.gperf" + {"eth", 2, {195, 176}}, +#line 1806 "src/html/html_unescape.gperf" + {"supnE", 3, {226, 171, 140}}, + {(char*)0}, {(char*)0}, +#line 85 "src/html/html_unescape.gperf" + {"awint", 3, {226, 168, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 196 "src/html/html_unescape.gperf" + {"Breve", 2, {203, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 622 "src/html/html_unescape.gperf" + {"Gg", 3, {226, 139, 153}}, + {(char*)0}, +#line 707 "src/html/html_unescape.gperf" + {"HumpEqual", 3, {226, 137, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 949 "src/html/html_unescape.gperf" + {"Lleftarrow", 3, {226, 135, 154}}, +#line 155 "src/html/html_unescape.gperf" + {"boxdr", 3, {226, 148, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1783 "src/html/html_unescape.gperf" + {"succneqq", 3, {226, 170, 182}}, +#line 1972 "src/html/html_unescape.gperf" + {"uring", 2, {197, 175}}, +#line 930 "src/html/html_unescape.gperf" + {"LessSlantEqual", 3, {226, 169, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1291 "src/html/html_unescape.gperf" + {"nvdash", 3, {226, 138, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 670 "src/html/html_unescape.gperf" + {"Hacek", 2, {203, 135}}, +#line 780 "src/html/html_unescape.gperf" + {"itilde", 2, {196, 169}}, + {(char*)0}, {(char*)0}, +#line 766 "src/html/html_unescape.gperf" + {"Iota", 2, {206, 153}}, + {(char*)0}, +#line 760 "src/html/html_unescape.gperf" + {"IOcy", 2, {208, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 157 "src/html/html_unescape.gperf" + {"boxDr", 3, {226, 149, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1780 "src/html/html_unescape.gperf" + {"SucceedsTilde", 3, {226, 137, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 884 "src/html/html_unescape.gperf" + {"LeftFloor", 3, {226, 140, 138}}, +#line 2042 "src/html/html_unescape.gperf" + {"Vvdash", 3, {226, 138, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1877 "src/html/html_unescape.gperf" + {"triangledown", 3, {226, 150, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 970 "src/html/html_unescape.gperf" + {"LongLeftRightArrow", 3, {226, 159, 183}}, +#line 1573 "src/html/html_unescape.gperf" + {"RightFloor", 3, {226, 140, 139}}, + {(char*)0}, {(char*)0}, +#line 435 "src/html/html_unescape.gperf" + {"DownRightTeeVector", 3, {226, 165, 159}}, + {(char*)0}, +#line 1481 "src/html/html_unescape.gperf" + {"quatint", 3, {226, 168, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1278 "src/html/html_unescape.gperf" + {"Ntilde", 2, {195, 145}}, + {(char*)0}, {(char*)0}, +#line 211 "src/html/html_unescape.gperf" + {"Bumpeq", 3, {226, 137, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 669 "src/html/html_unescape.gperf" + {"gvnE", 3, {226, 137, 169}}, + {(char*)0}, +#line 165 "src/html/html_unescape.gperf" + {"boxhu", 3, {226, 148, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 659 "src/html/html_unescape.gperf" + {"gtlPar", 3, {226, 166, 149}}, + {(char*)0}, {(char*)0}, +#line 1238 "src/html/html_unescape.gperf" + {"nprec", 3, {226, 138, 128}}, + {(char*)0}, {(char*)0}, +#line 1381 "src/html/html_unescape.gperf" + {"ouml", 2, {195, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 612 "src/html/html_unescape.gperf" + {"gescc", 3, {226, 170, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 537 "src/html/html_unescape.gperf" + {"Euml", 2, {195, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1971 "src/html/html_unescape.gperf" + {"Uring", 2, {197, 174}}, + {(char*)0}, +#line 1938 "src/html/html_unescape.gperf" + {"UnderBracket", 3, {226, 142, 181}}, +#line 1162 "src/html/html_unescape.gperf" + {"nLtv", 3, {226, 137, 170}}, +#line 873 "src/html/html_unescape.gperf" + {"LeftArrowBar", 3, {226, 135, 164}}, +#line 1096 "src/html/html_unescape.gperf" + {"ncongdot", 3, {226, 169, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 79 "src/html/html_unescape.gperf" + {"asympeq", 3, {226, 137, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1059 "src/html/html_unescape.gperf" + {"minusdu", 3, {226, 168, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 365 "src/html/html_unescape.gperf" + {"delta", 2, {206, 180}}, + {(char*)0}, +#line 679 "src/html/html_unescape.gperf" + {"harrw", 3, {226, 134, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 39 "src/html/html_unescape.gperf" + {"andslope", 3, {226, 169, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 238 "src/html/html_unescape.gperf" + {"cdot", 2, {196, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 226 "src/html/html_unescape.gperf" + {"Cayleys", 3, {226, 132, 173}}, +#line 167 "src/html/html_unescape.gperf" + {"boxhU", 3, {226, 149, 168}}, + {(char*)0}, {(char*)0}, +#line 1785 "src/html/html_unescape.gperf" + {"succsim", 3, {226, 137, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 267 "src/html/html_unescape.gperf" + {"cirE", 3, {226, 167, 131}}, +#line 1654 "src/html/html_unescape.gperf" + {"sdotb", 3, {226, 138, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1319 "src/html/html_unescape.gperf" + {"odash", 3, {226, 138, 157}}, +#line 270 "src/html/html_unescape.gperf" + {"cirmid", 3, {226, 171, 175}}, +#line 1803 "src/html/html_unescape.gperf" + {"suphsub", 3, {226, 171, 151}}, +#line 1796 "src/html/html_unescape.gperf" + {"supdsub", 3, {226, 171, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1795 "src/html/html_unescape.gperf" + {"supdot", 3, {226, 170, 190}}, + {(char*)0}, +#line 84 "src/html/html_unescape.gperf" + {"awconint", 3, {226, 136, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1895 "src/html/html_unescape.gperf" + {"TSHcy", 2, {208, 139}}, + {(char*)0}, {(char*)0}, +#line 640 "src/html/html_unescape.gperf" + {"grave", 1, {96}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1005 "src/html/html_unescape.gperf" + {"lsimg", 3, {226, 170, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1950 "src/html/html_unescape.gperf" + {"UpArrowDownArrow", 3, {226, 135, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 907 "src/html/html_unescape.gperf" + {"LeftVector", 3, {226, 134, 188}}, +#line 417 "src/html/html_unescape.gperf" + {"DoubleRightArrow", 3, {226, 135, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1109 "src/html/html_unescape.gperf" + {"NegativeThinSpace", 3, {226, 128, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 942 "src/html/html_unescape.gperf" + {"lhblk", 3, {226, 150, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 268 "src/html/html_unescape.gperf" + {"cire", 3, {226, 137, 151}}, +#line 1294 "src/html/html_unescape.gperf" + {"nVDash", 3, {226, 138, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1928 "src/html/html_unescape.gperf" + {"uhblk", 3, {226, 150, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 738 "src/html/html_unescape.gperf" + {"imagpart", 3, {226, 132, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1587 "src/html/html_unescape.gperf" + {"RightUpDownVector", 3, {226, 165, 143}}, + {(char*)0}, {(char*)0}, +#line 152 "src/html/html_unescape.gperf" + {"boxdL", 3, {226, 149, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 627 "src/html/html_unescape.gperf" + {"gla", 3, {226, 170, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 783 "src/html/html_unescape.gperf" + {"Iuml", 2, {195, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1326 "src/html/html_unescape.gperf" + {"oelig", 2, {197, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1199 "src/html/html_unescape.gperf" + {"NotLessSlantEqual", 3, {226, 169, 189}}, + {(char*)0}, +#line 154 "src/html/html_unescape.gperf" + {"boxDL", 3, {226, 149, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 592 "src/html/html_unescape.gperf" + {"gamma", 2, {206, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1378 "src/html/html_unescape.gperf" + {"Otimes", 3, {226, 168, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 969 "src/html/html_unescape.gperf" + {"longleftrightarrow", 3, {226, 159, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 591 "src/html/html_unescape.gperf" + {"Gamma", 2, {206, 147}}, +#line 128 "src/html/html_unescape.gperf" + {"bigwedge", 3, {226, 139, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 161 "src/html/html_unescape.gperf" + {"boxhd", 3, {226, 148, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1797 "src/html/html_unescape.gperf" + {"supE", 3, {226, 171, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 903 "src/html/html_unescape.gperf" + {"LeftUpTeeVector", 3, {226, 165, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 615 "src/html/html_unescape.gperf" + {"gesdoto", 3, {226, 170, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 801 "src/html/html_unescape.gperf" + {"kappa", 2, {206, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1125 "src/html/html_unescape.gperf" + {"ngeqslant", 3, {226, 169, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 666 "src/html/html_unescape.gperf" + {"gtrless", 3, {226, 137, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 551 "src/html/html_unescape.gperf" + {"fflig", 3, {239, 172, 128}}, +#line 122 "src/html/html_unescape.gperf" + {"bigsqcup", 3, {226, 168, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 809 "src/html/html_unescape.gperf" + {"kgreen", 2, {196, 184}}, +#line 1798 "src/html/html_unescape.gperf" + {"supe", 3, {226, 138, 135}}, + {(char*)0}, +#line 171 "src/html/html_unescape.gperf" + {"boxtimes", 3, {226, 138, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 632 "src/html/html_unescape.gperf" + {"gnapprox", 3, {226, 170, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 428 "src/html/html_unescape.gperf" + {"downdownarrows", 3, {226, 135, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 126 "src/html/html_unescape.gperf" + {"biguplus", 3, {226, 168, 132}}, +#line 811 "src/html/html_unescape.gperf" + {"khcy", 2, {209, 133}}, + {(char*)0}, +#line 356 "src/html/html_unescape.gperf" + {"ddagger", 3, {226, 128, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1380 "src/html/html_unescape.gperf" + {"Ouml", 2, {195, 150}}, + {(char*)0}, +#line 110 "src/html/html_unescape.gperf" + {"Beta", 2, {206, 146}}, +#line 1058 "src/html/html_unescape.gperf" + {"minusd", 3, {226, 136, 184}}, +#line 1784 "src/html/html_unescape.gperf" + {"succnsim", 3, {226, 139, 169}}, + {(char*)0}, +#line 311 "src/html/html_unescape.gperf" + {"ctdot", 3, {226, 139, 175}}, + {(char*)0}, {(char*)0}, +#line 813 "src/html/html_unescape.gperf" + {"kjcy", 2, {209, 156}}, +#line 626 "src/html/html_unescape.gperf" + {"gjcy", 2, {209, 147}}, + {(char*)0}, +#line 1095 "src/html/html_unescape.gperf" + {"ncong", 3, {226, 137, 135}}, +#line 2086 "src/html/html_unescape.gperf" + {"xvee", 3, {226, 139, 129}}, +#line 99 "src/html/html_unescape.gperf" + {"bcong", 3, {226, 137, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1723 "src/html/html_unescape.gperf" + {"sqsube", 3, {226, 138, 145}}, + {(char*)0}, {(char*)0}, +#line 156 "src/html/html_unescape.gperf" + {"boxdR", 3, {226, 149, 146}}, + {(char*)0}, {(char*)0}, +#line 971 "src/html/html_unescape.gperf" + {"Longleftrightarrow", 3, {226, 159, 186}}, + {(char*)0}, +#line 1722 "src/html/html_unescape.gperf" + {"sqsub", 3, {226, 138, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 431 "src/html/html_unescape.gperf" + {"DownLeftRightVector", 3, {226, 165, 144}}, + {(char*)0}, {(char*)0}, +#line 1724 "src/html/html_unescape.gperf" + {"sqsubset", 3, {226, 138, 143}}, + {(char*)0}, +#line 1230 "src/html/html_unescape.gperf" + {"NotVerticalBar", 3, {226, 136, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1175 "src/html/html_unescape.gperf" + {"NotEqualTilde", 3, {226, 137, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 151 "src/html/html_unescape.gperf" + {"boxdl", 3, {226, 148, 144}}, + {(char*)0}, {(char*)0}, +#line 158 "src/html/html_unescape.gperf" + {"boxDR", 3, {226, 149, 148}}, + {(char*)0}, +#line 35 "src/html/html_unescape.gperf" + {"andand", 3, {226, 169, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1592 "src/html/html_unescape.gperf" + {"RightVector", 3, {226, 135, 128}}, + {(char*)0}, +#line 731 "src/html/html_unescape.gperf" + {"IJlig", 2, {196, 178}}, +#line 1227 "src/html/html_unescape.gperf" + {"NotTildeEqual", 3, {226, 137, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 58 "src/html/html_unescape.gperf" + {"angzarr", 3, {226, 141, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 53 "src/html/html_unescape.gperf" + {"angrt", 3, {226, 136, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 12 "src/html/html_unescape.gperf" + {"acd", 3, {226, 136, 191}}, + {(char*)0}, {(char*)0}, +#line 38 "src/html/html_unescape.gperf" + {"andd", 3, {226, 169, 156}}, + {(char*)0}, +#line 1241 "src/html/html_unescape.gperf" + {"nrarrc", 3, {226, 164, 179}}, +#line 2026 "src/html/html_unescape.gperf" + {"VeryThinSpace", 3, {226, 128, 138}}, + {(char*)0}, +#line 1800 "src/html/html_unescape.gperf" + {"Superset", 3, {226, 138, 131}}, + {(char*)0}, +#line 153 "src/html/html_unescape.gperf" + {"boxDl", 3, {226, 149, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2030 "src/html/html_unescape.gperf" + {"vnsub", 3, {226, 138, 130}}, + {(char*)0}, {(char*)0}, +#line 236 "src/html/html_unescape.gperf" + {"ccupssm", 3, {226, 169, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1988 "src/html/html_unescape.gperf" + {"varnothing", 3, {226, 136, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1533 "src/html/html_unescape.gperf" + {"rcy", 2, {209, 128}}, + {(char*)0}, +#line 863 "src/html/html_unescape.gperf" + {"lcy", 2, {208, 187}}, + {(char*)0}, +#line 1653 "src/html/html_unescape.gperf" + {"scy", 2, {209, 129}}, + {(char*)0}, +#line 1833 "src/html/html_unescape.gperf" + {"Tcy", 2, {208, 162}}, +#line 2113 "src/html/html_unescape.gperf" + {"Zcy", 2, {208, 151}}, +#line 469 "src/html/html_unescape.gperf" + {"ecy", 2, {209, 141}}, +#line 1538 "src/html/html_unescape.gperf" + {"rdsh", 3, {226, 134, 179}}, + {(char*)0}, +#line 869 "src/html/html_unescape.gperf" + {"ldsh", 3, {226, 134, 178}}, + {(char*)0}, +#line 1915 "src/html/html_unescape.gperf" + {"ucy", 2, {209, 131}}, +#line 185 "src/html/html_unescape.gperf" + {"boxVH", 3, {226, 149, 172}}, +#line 1834 "src/html/html_unescape.gperf" + {"tcy", 2, {209, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1099 "src/html/html_unescape.gperf" + {"ncy", 2, {208, 189}}, + {(char*)0}, +#line 101 "src/html/html_unescape.gperf" + {"bcy", 2, {208, 177}}, +#line 1277 "src/html/html_unescape.gperf" + {"ntgl", 3, {226, 137, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 787 "src/html/html_unescape.gperf" + {"Jcy", 2, {208, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 289 "src/html/html_unescape.gperf" + {"congdot", 3, {226, 169, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 57 "src/html/html_unescape.gperf" + {"angst", 2, {195, 133}}, + {(char*)0}, +#line 1570 "src/html/html_unescape.gperf" + {"RightDownTeeVector", 3, {226, 165, 157}}, + {(char*)0}, {(char*)0}, +#line 1386 "src/html/html_unescape.gperf" + {"OverParenthesis", 3, {226, 143, 156}}, +#line 1020 "src/html/html_unescape.gperf" + {"ltquest", 3, {226, 169, 187}}, + {(char*)0}, +#line 1395 "src/html/html_unescape.gperf" + {"pcy", 2, {208, 191}}, + {(char*)0}, {(char*)0}, +#line 1376 "src/html/html_unescape.gperf" + {"otilde", 2, {195, 181}}, +#line 1536 "src/html/html_unescape.gperf" + {"rdquo", 3, {226, 128, 157}}, + {(char*)0}, +#line 865 "src/html/html_unescape.gperf" + {"ldquo", 3, {226, 128, 156}}, + {(char*)0}, +#line 2006 "src/html/html_unescape.gperf" + {"Vcy", 2, {208, 146}}, + {(char*)0}, {(char*)0}, +#line 216 "src/html/html_unescape.gperf" + {"capbrcup", 3, {226, 169, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 102 "src/html/html_unescape.gperf" + {"bdquo", 3, {226, 128, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 422 "src/html/html_unescape.gperf" + {"DownArrowBar", 3, {226, 164, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2007 "src/html/html_unescape.gperf" + {"vcy", 2, {208, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 54 "src/html/html_unescape.gperf" + {"angrtvb", 3, {226, 138, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 805 "src/html/html_unescape.gperf" + {"Kcy", 2, {208, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1041 "src/html/html_unescape.gperf" + {"Mcy", 2, {208, 156}}, +#line 1652 "src/html/html_unescape.gperf" + {"Scy", 2, {208, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1116 "src/html/html_unescape.gperf" + {"NewLine", 1, {10}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 548 "src/html/html_unescape.gperf" + {"fcy", 2, {209, 132}}, +#line 1914 "src/html/html_unescape.gperf" + {"Ucy", 2, {208, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 184 "src/html/html_unescape.gperf" + {"boxVh", 3, {226, 149, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 354 "src/html/html_unescape.gperf" + {"Dcy", 2, {208, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 705 "src/html/html_unescape.gperf" + {"hstrok", 2, {196, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 862 "src/html/html_unescape.gperf" + {"Lcy", 2, {208, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2094 "src/html/html_unescape.gperf" + {"Ycy", 2, {208, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1815 "src/html/html_unescape.gperf" + {"supsim", 3, {226, 171, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1165 "src/html/html_unescape.gperf" + {"NonBreakingSpace", 2, {194, 160}}, +#line 1383 "src/html/html_unescape.gperf" + {"OverBar", 3, {226, 128, 190}}, +#line 1725 "src/html/html_unescape.gperf" + {"sqsubseteq", 3, {226, 138, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 625 "src/html/html_unescape.gperf" + {"GJcy", 2, {208, 131}}, + {(char*)0}, {(char*)0}, +#line 1384 "src/html/html_unescape.gperf" + {"OverBrace", 3, {226, 143, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 513 "src/html/html_unescape.gperf" + {"eqcirc", 3, {226, 137, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1385 "src/html/html_unescape.gperf" + {"OverBracket", 3, {226, 142, 180}}, + {(char*)0}, +#line 82 "src/html/html_unescape.gperf" + {"Auml", 2, {195, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 16 "src/html/html_unescape.gperf" + {"acute", 2, {194, 180}}, +#line 716 "src/html/html_unescape.gperf" + {"icy", 2, {208, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 779 "src/html/html_unescape.gperf" + {"Itilde", 2, {196, 168}}, +#line 690 "src/html/html_unescape.gperf" + {"HilbertSpace", 3, {226, 132, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1345 "src/html/html_unescape.gperf" + {"omega", 2, {207, 137}}, +#line 214 "src/html/html_unescape.gperf" + {"cacute", 2, {196, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1646 "src/html/html_unescape.gperf" + {"scirc", 2, {197, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 465 "src/html/html_unescape.gperf" + {"ecirc", 2, {195, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1913 "src/html/html_unescape.gperf" + {"ucirc", 2, {195, 187}}, + {(char*)0}, +#line 646 "src/html/html_unescape.gperf" + {"GreaterSlantEqual", 3, {226, 169, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 785 "src/html/html_unescape.gperf" + {"Jcirc", 2, {196, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1292 "src/html/html_unescape.gperf" + {"nvDash", 3, {226, 138, 173}}, +#line 2044 "src/html/html_unescape.gperf" + {"Wcirc", 2, {197, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1098 "src/html/html_unescape.gperf" + {"Ncy", 2, {208, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1580 "src/html/html_unescape.gperf" + {"RightTeeArrow", 3, {226, 134, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 925 "src/html/html_unescape.gperf" + {"LessFullEqual", 3, {226, 137, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1011 "src/html/html_unescape.gperf" + {"ltcc", 3, {226, 170, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 27 "src/html/html_unescape.gperf" + {"aleph", 3, {226, 132, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 355 "src/html/html_unescape.gperf" + {"dcy", 2, {208, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1645 "src/html/html_unescape.gperf" + {"Scirc", 2, {197, 156}}, + {(char*)0}, +#line 920 "src/html/html_unescape.gperf" + {"lessapprox", 3, {226, 170, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 718 "src/html/html_unescape.gperf" + {"IEcy", 2, {208, 149}}, +#line 986 "src/html/html_unescape.gperf" + {"LowerRightArrow", 3, {226, 134, 152}}, +#line 1912 "src/html/html_unescape.gperf" + {"Ucirc", 2, {195, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 25 "src/html/html_unescape.gperf" + {"agrave", 2, {195, 160}}, + {(char*)0}, +#line 1060 "src/html/html_unescape.gperf" + {"MinusPlus", 3, {226, 136, 147}}, +#line 127 "src/html/html_unescape.gperf" + {"bigvee", 3, {226, 139, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1532 "src/html/html_unescape.gperf" + {"Rcy", 2, {208, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1802 "src/html/html_unescape.gperf" + {"suphsol", 3, {226, 159, 137}}, + {(char*)0}, {(char*)0}, +#line 495 "src/html/html_unescape.gperf" + {"EmptyVerySmallSquare", 3, {226, 150, 171}}, + {(char*)0}, +#line 163 "src/html/html_unescape.gperf" + {"boxhD", 3, {226, 149, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1436 "src/html/html_unescape.gperf" + {"precapprox", 3, {226, 170, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 55 "src/html/html_unescape.gperf" + {"angrtvbd", 3, {226, 166, 157}}, +#line 2092 "src/html/html_unescape.gperf" + {"Ycirc", 2, {197, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1753 "src/html/html_unescape.gperf" + {"sub", 3, {226, 138, 130}}, + {(char*)0}, {(char*)0}, +#line 1375 "src/html/html_unescape.gperf" + {"Otilde", 2, {195, 149}}, +#line 232 "src/html/html_unescape.gperf" + {"Ccirc", 2, {196, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 547 "src/html/html_unescape.gperf" + {"Fcy", 2, {208, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 287 "src/html/html_unescape.gperf" + {"complexes", 3, {226, 132, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1763 "src/html/html_unescape.gperf" + {"subrarr", 3, {226, 165, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 758 "src/html/html_unescape.gperf" + {"InvisibleComma", 3, {226, 129, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 176 "src/html/html_unescape.gperf" + {"boxur", 3, {226, 148, 148}}, +#line 10 "src/html/html_unescape.gperf" + {"abreve", 2, {196, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1280 "src/html/html_unescape.gperf" + {"ntlg", 3, {226, 137, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 714 "src/html/html_unescape.gperf" + {"icirc", 2, {195, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2063 "src/html/html_unescape.gperf" + {"xdtri", 3, {226, 150, 189}}, +#line 253 "src/html/html_unescape.gperf" + {"circ", 2, {203, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 663 "src/html/html_unescape.gperf" + {"gtrdot", 3, {226, 139, 151}}, + {(char*)0}, {(char*)0}, +#line 611 "src/html/html_unescape.gperf" + {"geqslant", 3, {226, 169, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1283 "src/html/html_unescape.gperf" + {"ntriangleright", 3, {226, 139, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 314 "src/html/html_unescape.gperf" + {"cuepr", 3, {226, 139, 158}}, +#line 1754 "src/html/html_unescape.gperf" + {"Sub", 3, {226, 139, 144}}, + {(char*)0}, +#line 1042 "src/html/html_unescape.gperf" + {"mcy", 2, {208, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1860 "src/html/html_unescape.gperf" + {"timesbar", 3, {226, 168, 177}}, + {(char*)0}, +#line 691 "src/html/html_unescape.gperf" + {"hksearow", 3, {226, 164, 165}}, + {(char*)0}, {(char*)0}, +#line 1683 "src/html/html_unescape.gperf" + {"sigma", 2, {207, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 325 "src/html/html_unescape.gperf" + {"cupor", 3, {226, 169, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1373 "src/html/html_unescape.gperf" + {"oslash", 2, {195, 184}}, +#line 458 "src/html/html_unescape.gperf" + {"dzigrarr", 3, {226, 159, 191}}, + {(char*)0}, {(char*)0}, +#line 892 "src/html/html_unescape.gperf" + {"leftrightharpoons", 3, {226, 135, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1577 "src/html/html_unescape.gperf" + {"rightleftharpoons", 3, {226, 135, 140}}, + {(char*)0}, +#line 804 "src/html/html_unescape.gperf" + {"kcedil", 2, {196, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1759 "src/html/html_unescape.gperf" + {"submult", 3, {226, 171, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 333 "src/html/html_unescape.gperf" + {"curren", 2, {194, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 897 "src/html/html_unescape.gperf" + {"LeftTeeVector", 3, {226, 165, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 123 "src/html/html_unescape.gperf" + {"bigstar", 3, {226, 152, 133}}, + {(char*)0}, {(char*)0}, +#line 321 "src/html/html_unescape.gperf" + {"cup", 3, {226, 136, 170}}, +#line 974 "src/html/html_unescape.gperf" + {"LongRightArrow", 3, {226, 159, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 598 "src/html/html_unescape.gperf" + {"Gcedil", 2, {196, 162}}, + {(char*)0}, +#line 1440 "src/html/html_unescape.gperf" + {"PrecedesEqual", 3, {226, 170, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 2114 "src/html/html_unescape.gperf" + {"zcy", 2, {208, 183}}, + {(char*)0}, +#line 1413 "src/html/html_unescape.gperf" + {"planckh", 3, {226, 132, 142}}, +#line 1344 "src/html/html_unescape.gperf" + {"Omega", 2, {206, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1772 "src/html/html_unescape.gperf" + {"subsub", 3, {226, 171, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1534 "src/html/html_unescape.gperf" + {"rdca", 3, {226, 164, 183}}, +#line 326 "src/html/html_unescape.gperf" + {"cups", 3, {226, 136, 170}}, +#line 864 "src/html/html_unescape.gperf" + {"ldca", 3, {226, 164, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1764 "src/html/html_unescape.gperf" + {"subset", 3, {226, 138, 130}}, +#line 1220 "src/html/html_unescape.gperf" + {"NotSucceeds", 3, {226, 138, 129}}, +#line 877 "src/html/html_unescape.gperf" + {"LeftArrowRightArrow", 3, {226, 135, 134}}, + {(char*)0}, {(char*)0}, +#line 2045 "src/html/html_unescape.gperf" + {"wcirc", 2, {197, 181}}, +#line 1561 "src/html/html_unescape.gperf" + {"RightAngleBracket", 3, {226, 159, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1284 "src/html/html_unescape.gperf" + {"ntrianglerighteq", 3, {226, 139, 173}}, +#line 1682 "src/html/html_unescape.gperf" + {"Sigma", 2, {206, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1223 "src/html/html_unescape.gperf" + {"NotSucceedsTilde", 3, {226, 137, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 373 "src/html/html_unescape.gperf" + {"DiacriticalAcute", 2, {194, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1761 "src/html/html_unescape.gperf" + {"subne", 3, {226, 138, 138}}, + {(char*)0}, +#line 1457 "src/html/html_unescape.gperf" + {"Product", 3, {226, 136, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 259 "src/html/html_unescape.gperf" + {"circleddash", 3, {226, 138, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1773 "src/html/html_unescape.gperf" + {"subsup", 3, {226, 171, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 298 "src/html/html_unescape.gperf" + {"copy", 2, {194, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 534 "src/html/html_unescape.gperf" + {"eta", 2, {206, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 52 "src/html/html_unescape.gperf" + {"angmsd", 3, {226, 136, 161}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1084 "src/html/html_unescape.gperf" + {"natural", 3, {226, 153, 174}}, + {(char*)0}, +#line 1799 "src/html/html_unescape.gperf" + {"supedot", 3, {226, 171, 132}}, +#line 1085 "src/html/html_unescape.gperf" + {"naturals", 3, {226, 132, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1881 "src/html/html_unescape.gperf" + {"triangleright", 3, {226, 150, 185}}, + {(char*)0}, +#line 376 "src/html/html_unescape.gperf" + {"DiacriticalGrave", 1, {96}}, +#line 173 "src/html/html_unescape.gperf" + {"boxuL", 3, {226, 149, 155}}, +#line 288 "src/html/html_unescape.gperf" + {"cong", 3, {226, 137, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1836 "src/html/html_unescape.gperf" + {"telrec", 3, {226, 140, 149}}, + {(char*)0}, {(char*)0}, +#line 282 "src/html/html_unescape.gperf" + {"comma", 1, {44}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1765 "src/html/html_unescape.gperf" + {"Subset", 3, {226, 139, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1222 "src/html/html_unescape.gperf" + {"NotSucceedsSlantEqual", 3, {226, 139, 161}}, +#line 664 "src/html/html_unescape.gperf" + {"gtreqless", 3, {226, 139, 155}}, +#line 80 "src/html/html_unescape.gperf" + {"Atilde", 2, {195, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 327 "src/html/html_unescape.gperf" + {"curarr", 3, {226, 134, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 313 "src/html/html_unescape.gperf" + {"cudarrr", 3, {226, 164, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 312 "src/html/html_unescape.gperf" + {"cudarrl", 3, {226, 164, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1766 "src/html/html_unescape.gperf" + {"subseteq", 3, {226, 138, 134}}, +#line 1767 "src/html/html_unescape.gperf" + {"subseteqq", 3, {226, 171, 133}}, +#line 1579 "src/html/html_unescape.gperf" + {"rightsquigarrow", 3, {226, 134, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 319 "src/html/html_unescape.gperf" + {"cupcap", 3, {226, 169, 134}}, +#line 1769 "src/html/html_unescape.gperf" + {"subsetneq", 3, {226, 138, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 60 "src/html/html_unescape.gperf" + {"aogon", 2, {196, 133}}, +#line 1191 "src/html/html_unescape.gperf" + {"notinvc", 3, {226, 139, 182}}, +#line 1583 "src/html/html_unescape.gperf" + {"rightthreetimes", 3, {226, 139, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 2089 "src/html/html_unescape.gperf" + {"yacute", 2, {195, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1148 "src/html/html_unescape.gperf" + {"nLeftarrow", 3, {226, 135, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1318 "src/html/html_unescape.gperf" + {"ocy", 2, {208, 190}}, +#line 241 "src/html/html_unescape.gperf" + {"cemptyv", 3, {226, 166, 178}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 468 "src/html/html_unescape.gperf" + {"Ecy", 2, {208, 173}}, + {(char*)0}, {(char*)0}, +#line 323 "src/html/html_unescape.gperf" + {"cupcup", 3, {226, 169, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1882 "src/html/html_unescape.gperf" + {"trianglerighteq", 3, {226, 138, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 889 "src/html/html_unescape.gperf" + {"LeftRightArrow", 3, {226, 134, 148}}, + {(char*)0}, {(char*)0}, +#line 1775 "src/html/html_unescape.gperf" + {"succ", 3, {226, 137, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 426 "src/html/html_unescape.gperf" + {"DownArrowUpArrow", 3, {226, 135, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1325 "src/html/html_unescape.gperf" + {"OElig", 2, {197, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 248 "src/html/html_unescape.gperf" + {"chcy", 2, {209, 135}}, +#line 665 "src/html/html_unescape.gperf" + {"gtreqqless", 3, {226, 170, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 43 "src/html/html_unescape.gperf" + {"angle", 3, {226, 136, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 13 "src/html/html_unescape.gperf" + {"acE", 3, {226, 136, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1598 "src/html/html_unescape.gperf" + {"rmoustache", 3, {226, 142, 177}}, + {(char*)0}, +#line 954 "src/html/html_unescape.gperf" + {"lmoustache", 3, {226, 142, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1110 "src/html/html_unescape.gperf" + {"NegativeVeryThinSpace", 3, {226, 128, 139}}, + {(char*)0}, {(char*)0}, +#line 1083 "src/html/html_unescape.gperf" + {"napprox", 3, {226, 137, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1372 "src/html/html_unescape.gperf" + {"Oslash", 2, {195, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1770 "src/html/html_unescape.gperf" + {"subsetneqq", 3, {226, 171, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 72 "src/html/html_unescape.gperf" + {"Aring", 2, {195, 133}}, +#line 177 "src/html/html_unescape.gperf" + {"boxuR", 3, {226, 149, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1762 "src/html/html_unescape.gperf" + {"subplus", 3, {226, 170, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2087 "src/html/html_unescape.gperf" + {"xwedge", 3, {226, 139, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 172 "src/html/html_unescape.gperf" + {"boxul", 3, {226, 148, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 190 "src/html/html_unescape.gperf" + {"boxvr", 3, {226, 148, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 706 "src/html/html_unescape.gperf" + {"HumpDownHump", 3, {226, 137, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 715 "src/html/html_unescape.gperf" + {"Icy", 2, {208, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 71 "src/html/html_unescape.gperf" + {"approxeq", 3, {226, 137, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 8 "src/html/html_unescape.gperf" + {"aacute", 2, {195, 161}}, +#line 67 "src/html/html_unescape.gperf" + {"apid", 3, {226, 137, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1952 "src/html/html_unescape.gperf" + {"UpDownArrow", 3, {226, 134, 149}}, + {(char*)0}, +#line 1114 "src/html/html_unescape.gperf" + {"NestedGreaterGreater", 3, {226, 137, 171}}, + {(char*)0}, +#line 788 "src/html/html_unescape.gperf" + {"jcy", 2, {208, 185}}, + {(char*)0}, {(char*)0}, +#line 667 "src/html/html_unescape.gperf" + {"gtrsim", 3, {226, 137, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 180 "src/html/html_unescape.gperf" + {"boxv", 3, {226, 148, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1315 "src/html/html_unescape.gperf" + {"ocirc", 2, {195, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 464 "src/html/html_unescape.gperf" + {"Ecirc", 2, {195, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1206 "src/html/html_unescape.gperf" + {"notnivc", 3, {226, 139, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 125 "src/html/html_unescape.gperf" + {"bigtriangleup", 3, {226, 150, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 343 "src/html/html_unescape.gperf" + {"daleth", 3, {226, 132, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1317 "src/html/html_unescape.gperf" + {"Ocy", 2, {208, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 682 "src/html/html_unescape.gperf" + {"Hcirc", 2, {196, 164}}, +#line 1591 "src/html/html_unescape.gperf" + {"RightVectorBar", 3, {226, 165, 147}}, +#line 19 "src/html/html_unescape.gperf" + {"AElig", 2, {195, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 557 "src/html/html_unescape.gperf" + {"FilledVerySmallSquare", 3, {226, 150, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 623 "src/html/html_unescape.gperf" + {"ggg", 3, {226, 139, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 100 "src/html/html_unescape.gperf" + {"Bcy", 2, {208, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1427 "src/html/html_unescape.gperf" + {"Poincareplane", 3, {226, 132, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 187 "src/html/html_unescape.gperf" + {"boxvL", 3, {226, 149, 161}}, + {(char*)0}, {(char*)0}, +#line 1393 "src/html/html_unescape.gperf" + {"PartialD", 3, {226, 136, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 713 "src/html/html_unescape.gperf" + {"Icirc", 2, {195, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 316 "src/html/html_unescape.gperf" + {"cularr", 3, {226, 134, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 159 "src/html/html_unescape.gperf" + {"boxh", 3, {226, 148, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 40 "src/html/html_unescape.gperf" + {"andv", 3, {226, 169, 154}}, + {(char*)0}, +#line 1789 "src/html/html_unescape.gperf" + {"sung", 3, {226, 153, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1569 "src/html/html_unescape.gperf" + {"RightDoubleBracket", 3, {226, 159, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 786 "src/html/html_unescape.gperf" + {"jcirc", 2, {196, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1936 "src/html/html_unescape.gperf" + {"UnderBar", 1, {95}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1564 "src/html/html_unescape.gperf" + {"RightArrow", 3, {226, 134, 146}}, +#line 258 "src/html/html_unescape.gperf" + {"circledcirc", 3, {226, 138, 154}}, +#line 28 "src/html/html_unescape.gperf" + {"Alpha", 2, {206, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 886 "src/html/html_unescape.gperf" + {"leftharpoonup", 3, {226, 134, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 317 "src/html/html_unescape.gperf" + {"cularrp", 3, {226, 164, 189}}, + {(char*)0}, +#line 1566 "src/html/html_unescape.gperf" + {"RightArrowLeftArrow", 3, {226, 135, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1995 "src/html/html_unescape.gperf" + {"varsigma", 2, {207, 130}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1288 "src/html/html_unescape.gperf" + {"numero", 3, {226, 132, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 552 "src/html/html_unescape.gperf" + {"ffllig", 3, {239, 172, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 985 "src/html/html_unescape.gperf" + {"LowerLeftArrow", 3, {226, 134, 153}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 543 "src/html/html_unescape.gperf" + {"expectation", 3, {226, 132, 176}}, + {(char*)0}, +#line 1314 "src/html/html_unescape.gperf" + {"Ocirc", 2, {195, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2091 "src/html/html_unescape.gperf" + {"yacy", 2, {209, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 824 "src/html/html_unescape.gperf" + {"lambda", 2, {206, 187}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1221 "src/html/html_unescape.gperf" + {"NotSucceedsEqual", 3, {226, 170, 176}}, +#line 191 "src/html/html_unescape.gperf" + {"boxvR", 3, {226, 149, 158}}, + {(char*)0}, +#line 124 "src/html/html_unescape.gperf" + {"bigtriangledown", 3, {226, 150, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 41 "src/html/html_unescape.gperf" + {"ang", 3, {226, 136, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2084 "src/html/html_unescape.gperf" + {"xuplus", 3, {226, 168, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1075 "src/html/html_unescape.gperf" + {"nabla", 3, {226, 136, 135}}, +#line 186 "src/html/html_unescape.gperf" + {"boxvl", 3, {226, 148, 164}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 533 "src/html/html_unescape.gperf" + {"Eta", 2, {206, 151}}, + {(char*)0}, +#line 17 "src/html/html_unescape.gperf" + {"Acy", 2, {208, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 806 "src/html/html_unescape.gperf" + {"kcy", 2, {208, 186}}, +#line 602 "src/html/html_unescape.gperf" + {"gcy", 2, {208, 179}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 894 "src/html/html_unescape.gperf" + {"LeftRightVector", 3, {226, 165, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 231 "src/html/html_unescape.gperf" + {"ccedil", 2, {195, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 91 "src/html/html_unescape.gperf" + {"Backslash", 3, {226, 136, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 703 "src/html/html_unescape.gperf" + {"hslash", 3, {226, 132, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1394 "src/html/html_unescape.gperf" + {"Pcy", 2, {208, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 601 "src/html/html_unescape.gperf" + {"Gcy", 2, {208, 147}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 660 "src/html/html_unescape.gperf" + {"gtquest", 3, {226, 169, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 823 "src/html/html_unescape.gperf" + {"Lambda", 2, {206, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1322 "src/html/html_unescape.gperf" + {"odiv", 3, {226, 168, 184}}, + {(char*)0}, +#line 885 "src/html/html_unescape.gperf" + {"leftharpoondown", 3, {226, 134, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 972 "src/html/html_unescape.gperf" + {"longmapsto", 3, {226, 159, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 798 "src/html/html_unescape.gperf" + {"Jukcy", 2, {208, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 867 "src/html/html_unescape.gperf" + {"ldrdhar", 3, {226, 165, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2085 "src/html/html_unescape.gperf" + {"xutri", 3, {226, 150, 179}}, +#line 1246 "src/html/html_unescape.gperf" + {"nRightarrow", 3, {226, 135, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 545 "src/html/html_unescape.gperf" + {"ExponentialE", 3, {226, 133, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1245 "src/html/html_unescape.gperf" + {"nrightarrow", 3, {226, 134, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 14 "src/html/html_unescape.gperf" + {"Acirc", 2, {195, 130}}, +#line 1164 "src/html/html_unescape.gperf" + {"NoBreak", 3, {226, 129, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 600 "src/html/html_unescape.gperf" + {"gcirc", 2, {196, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 42 "src/html/html_unescape.gperf" + {"ange", 3, {226, 166, 164}}, +#line 328 "src/html/html_unescape.gperf" + {"curarrm", 3, {226, 164, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1671 "src/html/html_unescape.gperf" + {"SHCHcy", 2, {208, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2107 "src/html/html_unescape.gperf" + {"yuml", 2, {195, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1760 "src/html/html_unescape.gperf" + {"subnE", 3, {226, 171, 139}}, + {(char*)0}, {(char*)0}, +#line 360 "src/html/html_unescape.gperf" + {"DDotrahd", 3, {226, 164, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1629 "src/html/html_unescape.gperf" + {"RuleDelayed", 3, {226, 167, 180}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 599 "src/html/html_unescape.gperf" + {"Gcirc", 2, {196, 156}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 796 "src/html/html_unescape.gperf" + {"Jsercy", 2, {208, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 653 "src/html/html_unescape.gperf" + {"gtcc", 3, {226, 170, 167}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 782 "src/html/html_unescape.gperf" + {"iukcy", 2, {209, 150}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1951 "src/html/html_unescape.gperf" + {"updownarrow", 3, {226, 134, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 331 "src/html/html_unescape.gperf" + {"curlyvee", 3, {226, 139, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 550 "src/html/html_unescape.gperf" + {"ffilig", 3, {239, 172, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2100 "src/html/html_unescape.gperf" + {"yicy", 2, {209, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 390 "src/html/html_unescape.gperf" + {"divonx", 3, {226, 139, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 661 "src/html/html_unescape.gperf" + {"gtrapprox", 3, {226, 170, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1755 "src/html/html_unescape.gperf" + {"subdot", 3, {226, 170, 189}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 891 "src/html/html_unescape.gperf" + {"leftrightarrows", 3, {226, 135, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 83 "src/html/html_unescape.gperf" + {"auml", 2, {195, 164}}, + {(char*)0}, {(char*)0}, +#line 1953 "src/html/html_unescape.gperf" + {"Updownarrow", 3, {226, 135, 149}}, + {(char*)0}, +#line 1576 "src/html/html_unescape.gperf" + {"rightleftarrows", 3, {226, 135, 132}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 437 "src/html/html_unescape.gperf" + {"DownRightVector", 3, {226, 135, 129}}, + {(char*)0}, {(char*)0}, +#line 436 "src/html/html_unescape.gperf" + {"DownRightVectorBar", 3, {226, 165, 151}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 683 "src/html/html_unescape.gperf" + {"hcirc", 2, {196, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1614 "src/html/html_unescape.gperf" + {"Rrightarrow", 3, {226, 135, 155}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 973 "src/html/html_unescape.gperf" + {"longrightarrow", 3, {226, 159, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 324 "src/html/html_unescape.gperf" + {"cupdot", 3, {226, 138, 141}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 11 "src/html/html_unescape.gperf" + {"ac", 3, {226, 136, 190}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 696 "src/html/html_unescape.gperf" + {"hookrightarrow", 3, {226, 134, 170}}, + {(char*)0}, {(char*)0}, +#line 1108 "src/html/html_unescape.gperf" + {"NegativeThickSpace", 3, {226, 128, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1756 "src/html/html_unescape.gperf" + {"subE", 3, {226, 171, 133}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1901 "src/html/html_unescape.gperf" + {"twoheadrightarrow", 3, {226, 134, 160}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 430 "src/html/html_unescape.gperf" + {"downharpoonright", 3, {226, 135, 130}}, +#line 429 "src/html/html_unescape.gperf" + {"downharpoonleft", 3, {226, 135, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 20 "src/html/html_unescape.gperf" + {"aelig", 2, {195, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1535 "src/html/html_unescape.gperf" + {"rdldhar", 3, {226, 165, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 332 "src/html/html_unescape.gperf" + {"curlywedge", 3, {226, 139, 143}}, + {(char*)0}, +#line 708 "src/html/html_unescape.gperf" + {"hybull", 3, {226, 129, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1757 "src/html/html_unescape.gperf" + {"sube", 3, {226, 138, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 975 "src/html/html_unescape.gperf" + {"Longrightarrow", 3, {226, 159, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 240 "src/html/html_unescape.gperf" + {"Cedilla", 2, {194, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1189 "src/html/html_unescape.gperf" + {"notinva", 3, {226, 136, 137}}, +#line 1778 "src/html/html_unescape.gperf" + {"SucceedsEqual", 3, {226, 170, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 888 "src/html/html_unescape.gperf" + {"leftrightarrow", 3, {226, 134, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1750 "src/html/html_unescape.gperf" + {"straightepsilon", 2, {207, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 32 "src/html/html_unescape.gperf" + {"amalg", 3, {226, 168, 191}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 81 "src/html/html_unescape.gperf" + {"atilde", 2, {195, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1568 "src/html/html_unescape.gperf" + {"RightCeiling", 3, {226, 140, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 890 "src/html/html_unescape.gperf" + {"Leftrightarrow", 3, {226, 135, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1771 "src/html/html_unescape.gperf" + {"subsim", 3, {226, 171, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 2023 "src/html/html_unescape.gperf" + {"VerticalLine", 1, {124}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1590 "src/html/html_unescape.gperf" + {"RightUpVector", 3, {226, 134, 190}}, + {(char*)0}, {(char*)0}, +#line 1589 "src/html/html_unescape.gperf" + {"RightUpVectorBar", 3, {226, 165, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1572 "src/html/html_unescape.gperf" + {"RightDownVector", 3, {226, 135, 130}}, + {(char*)0}, {(char*)0}, +#line 1571 "src/html/html_unescape.gperf" + {"RightDownVectorBar", 3, {226, 165, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 26 "src/html/html_unescape.gperf" + {"alefsym", 3, {226, 132, 181}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 256 "src/html/html_unescape.gperf" + {"circlearrowright", 3, {226, 134, 187}}, +#line 255 "src/html/html_unescape.gperf" + {"circlearrowleft", 3, {226, 134, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 781 "src/html/html_unescape.gperf" + {"Iukcy", 2, {208, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1377 "src/html/html_unescape.gperf" + {"otimesas", 3, {226, 168, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 754 "src/html/html_unescape.gperf" + {"intercal", 3, {226, 138, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1846 "src/html/html_unescape.gperf" + {"thickapprox", 3, {226, 137, 136}}, + {(char*)0}, {(char*)0}, +#line 799 "src/html/html_unescape.gperf" + {"jukcy", 2, {209, 148}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1204 "src/html/html_unescape.gperf" + {"notniva", 3, {226, 136, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1444 "src/html/html_unescape.gperf" + {"precnapprox", 3, {226, 170, 185}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 336 "src/html/html_unescape.gperf" + {"cuvee", 3, {226, 139, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 73 "src/html/html_unescape.gperf" + {"aring", 2, {195, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 233 "src/html/html_unescape.gperf" + {"ccirc", 2, {196, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1563 "src/html/html_unescape.gperf" + {"rightarrow", 3, {226, 134, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 753 "src/html/html_unescape.gperf" + {"Integral", 3, {226, 136, 171}}, +#line 2061 "src/html/html_unescape.gperf" + {"xcirc", 3, {226, 151, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 797 "src/html/html_unescape.gperf" + {"jsercy", 2, {209, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 250 "src/html/html_unescape.gperf" + {"checkmark", 3, {226, 156, 147}}, + {(char*)0}, +#line 2025 "src/html/html_unescape.gperf" + {"VerticalTilde", 3, {226, 137, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 183 "src/html/html_unescape.gperf" + {"boxvH", 3, {226, 149, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1211 "src/html/html_unescape.gperf" + {"NotRightTriangleBar", 3, {226, 167, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1213 "src/html/html_unescape.gperf" + {"NotRightTriangleEqual", 3, {226, 139, 173}}, +#line 1212 "src/html/html_unescape.gperf" + {"NotRightTriangle", 3, {226, 139, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 906 "src/html/html_unescape.gperf" + {"LeftVectorBar", 3, {226, 165, 146}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 182 "src/html/html_unescape.gperf" + {"boxvh", 3, {226, 148, 188}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 150 "src/html/html_unescape.gperf" + {"boxbox", 3, {226, 167, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2095 "src/html/html_unescape.gperf" + {"ycy", 2, {209, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1758 "src/html/html_unescape.gperf" + {"subedot", 3, {226, 171, 131}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1707 "src/html/html_unescape.gperf" + {"SOFTcy", 2, {208, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1565 "src/html/html_unescape.gperf" + {"Rightarrow", 3, {226, 135, 146}}, + {(char*)0}, +#line 29 "src/html/html_unescape.gperf" + {"alpha", 2, {206, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1672 "src/html/html_unescape.gperf" + {"shchcy", 2, {209, 137}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1708 "src/html/html_unescape.gperf" + {"softcy", 2, {209, 140}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 18 "src/html/html_unescape.gperf" + {"acy", 2, {208, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2093 "src/html/html_unescape.gperf" + {"ycirc", 2, {197, 183}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 117 "src/html/html_unescape.gperf" + {"bigcirc", 3, {226, 151, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 736 "src/html/html_unescape.gperf" + {"ImaginaryI", 3, {226, 133, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 70 "src/html/html_unescape.gperf" + {"approx", 3, {226, 137, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1801 "src/html/html_unescape.gperf" + {"SupersetEqual", 3, {226, 138, 135}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2043 "src/html/html_unescape.gperf" + {"vzigzag", 3, {226, 166, 154}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 315 "src/html/html_unescape.gperf" + {"cuesc", 3, {226, 139, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1939 "src/html/html_unescape.gperf" + {"UnderParenthesis", 3, {226, 143, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 15 "src/html/html_unescape.gperf" + {"acirc", 2, {195, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1774 "src/html/html_unescape.gperf" + {"succapprox", 3, {226, 170, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1040 "src/html/html_unescape.gperf" + {"mcomma", 3, {226, 168, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 48 "src/html/html_unescape.gperf" + {"angmsdae", 3, {226, 166, 172}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 45 "src/html/html_unescape.gperf" + {"angmsdab", 3, {226, 166, 169}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 49 "src/html/html_unescape.gperf" + {"angmsdaf", 3, {226, 166, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 56 "src/html/html_unescape.gperf" + {"angsph", 3, {226, 136, 162}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1026 "src/html/html_unescape.gperf" + {"luruhar", 3, {226, 165, 166}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 47 "src/html/html_unescape.gperf" + {"angmsdad", 3, {226, 166, 171}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1900 "src/html/html_unescape.gperf" + {"twoheadleftarrow", 3, {226, 134, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 340 "src/html/html_unescape.gperf" + {"cylcty", 3, {226, 140, 173}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1751 "src/html/html_unescape.gperf" + {"straightphi", 2, {207, 149}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1073 "src/html/html_unescape.gperf" + {"multimap", 3, {226, 138, 184}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1562 "src/html/html_unescape.gperf" + {"RightArrowBar", 3, {226, 135, 165}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 868 "src/html/html_unescape.gperf" + {"ldrushar", 3, {226, 165, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 872 "src/html/html_unescape.gperf" + {"LeftAngleBracket", 3, {226, 159, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1630 "src/html/html_unescape.gperf" + {"ruluhar", 3, {226, 165, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 329 "src/html/html_unescape.gperf" + {"curlyeqprec", 3, {226, 139, 158}}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2106 "src/html/html_unescape.gperf" + {"yucy", 2, {209, 142}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1025 "src/html/html_unescape.gperf" + {"lurdshar", 3, {226, 165, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 675 "src/html/html_unescape.gperf" + {"hardcy", 2, {209, 138}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1574 "src/html/html_unescape.gperf" + {"rightharpoondown", 3, {226, 135, 129}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1575 "src/html/html_unescape.gperf" + {"rightharpoonup", 3, {226, 135, 128}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 674 "src/html/html_unescape.gperf" + {"HARDcy", 2, {208, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1768 "src/html/html_unescape.gperf" + {"SubsetEqual", 3, {226, 138, 134}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 385 "src/html/html_unescape.gperf" + {"digamma", 2, {207, 157}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1918 "src/html/html_unescape.gperf" + {"udblac", 2, {197, 177}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1786 "src/html/html_unescape.gperf" + {"SuchThat", 3, {226, 136, 139}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 337 "src/html/html_unescape.gperf" + {"cuwed", 3, {226, 139, 143}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1917 "src/html/html_unescape.gperf" + {"Udblac", 2, {197, 176}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 50 "src/html/html_unescape.gperf" + {"angmsdag", 3, {226, 166, 174}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 51 "src/html/html_unescape.gperf" + {"angmsdah", 3, {226, 166, 175}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2022 "src/html/html_unescape.gperf" + {"VerticalBar", 3, {226, 136, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 2024 "src/html/html_unescape.gperf" + {"VerticalSeparator", 3, {226, 157, 152}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 1567 "src/html/html_unescape.gperf" + {"rightarrowtail", 3, {226, 134, 163}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 1321 "src/html/html_unescape.gperf" + {"odblac", 2, {197, 145}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 1782 "src/html/html_unescape.gperf" + {"succnapprox", 3, {226, 170, 186}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 46 "src/html/html_unescape.gperf" + {"angmsdac", 3, {226, 166, 170}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 1320 "src/html/html_unescape.gperf" + {"Odblac", 2, {197, 144}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, +#line 318 "src/html/html_unescape.gperf" + {"cupbrcap", 3, {226, 169, 136}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 44 "src/html/html_unescape.gperf" + {"angmsdaa", 3, {226, 166, 168}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, +#line 330 "src/html/html_unescape.gperf" + {"curlyeqsucc", 3, {226, 139, 159}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, +#line 334 "src/html/html_unescape.gperf" + {"curvearrowleft", 3, {226, 134, 182}}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, {(char*)0}, {(char*)0}, + {(char*)0}, {(char*)0}, +#line 335 "src/html/html_unescape.gperf" + {"curvearrowright", 3, {226, 134, 183}} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = hash_entity (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + if (len == lengthtable[key]) + { + register const char *s = wordlist[key].entity; + + if (s && *str == *s && !memcmp (str + 1, s + 1, len - 1)) + return &wordlist[key]; + } + } + return 0; +} diff --git a/src/utf8.h b/src/utf8.h new file mode 100644 index 0000000..1e4e556 --- /dev/null +++ b/src/utf8.h @@ -0,0 +1,12 @@ +#ifndef _H_STMD_UTF8_ +#define _H_STMD_UTF8_ + +#include "buffer.h" + +void utf8proc_case_fold(strbuf *dest, const unsigned char *str, int len); +void utf8proc_encode_char(int32_t uc, strbuf *buf); +ssize_t utf8proc_iterate(const uint8_t *str, ssize_t str_len, int32_t *dst); +ssize_t utf8proc_charlen(const uint8_t *str, ssize_t str_len); +void utf8proc_detab(strbuf *dest, const unsigned char *line, size_t size); + +#endif -- cgit v1.2.3 From 798f58a2b614280201141b398c8e498cecc8ab5e Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 6 Sep 2014 21:17:23 +0200 Subject: This is going well --- spec.txt | 35 +++++++++++++++++++----------- src/inlines.c | 68 +++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 64 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/spec.txt b/spec.txt index 616cb96..ebd6d98 100644 --- a/spec.txt +++ b/spec.txt @@ -3688,7 +3688,7 @@ raw HTML: . . -

    http://google.com?find=\*

    +

    http://google.com?find=\*

    . . @@ -3727,25 +3727,37 @@ foo ## Entities -Entities are parsed as entities, not as literal text, in all contexts -except code spans and code blocks. Three kinds of entities are recognized. +With the goal of making this standard as HTML-agnostic as possible, all HTML valid HTML Entities in any +context are recognized as such and converted into their actual values (i.e. the UTF8 characters representing +the entity itself) before they are stored in the AST. + +This allows implementations that target HTML output to trivially escape the entities when generating HTML, +and simplifies the job of implementations targetting other languages, as these will only need to handle the +UTF8 chars and need not be HTML-entity aware. [Named entities](#name-entities) consist of `&` -+ a string of 2-32 alphanumerics beginning with a letter + `;`. ++ any of the valid HTML5 entity names + `;`. The [following document](http://www.whatwg.org/specs/web-apps/current-work/multipage/entities.json) +is used as an authoritative source of the valid entity names and their corresponding codepoints. + +Conforming implementations that target Markdown don't need to generate entities for all the valid +named entities that exist, with the exception of `"` (`"`), `&` (`&`), `<` (`<`) and `>` (`>`), +which always need to be written as entities for security reasons. .   & © Æ Ď ¾ ℋ ⅆ ∲ . -

      & © Æ Ď ¾ ℋ ⅆ ∲

    +

      & © Æ Ď ¾ ℋ ⅆ ∲

    . [Decimal entities](#decimal-entities) -consist of `&#` + a string of 1--8 arabic digits + `;`. +consist of `&#` + a string of 1--8 arabic digits + `;`. Again, these entities need to be recognised +and tranformed into their corresponding UTF8 codepoints. Invalid Unicode codepoints will be written +as the "unknown codepoint" character (`0xFFFD`) . - # Ӓ Ϡ � +# Ӓ Ϡ � . -

     # Ӓ Ϡ �

    +

    # Ӓ Ϡ �

    . [Hexadecimal entities](#hexadecimal-entities) @@ -3767,7 +3779,7 @@ Here are some nonentities: . Although HTML5 does accept some entities without a trailing semicolon -(such as `©`), these are not recognized as entities here: +(such as `©`), these are not recognized as entities here, because it makes the grammar too ambiguous: . © @@ -3775,13 +3787,12 @@ Although HTML5 does accept some entities without a trailing semicolon

    &copy

    . -On the other hand, many strings that are not on the list of HTML5 -named entities are recognized as entities here: +Strings that are not on the list of HTML5 named entities are not recognized as entities either: . &MadeUpEntity; . -

    &MadeUpEntity;

    +

    &MadeUpEntity;

    . Entities are recognized in any context besides code spans or diff --git a/src/inlines.c b/src/inlines.c index 7b27150..aa0e13e 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -20,8 +20,9 @@ typedef struct Subject { reference* lookup_reference(reference** refmap, chunk *label); reference* make_reference(chunk *label, chunk *url, chunk *title); -static unsigned char *clean_url(chunk *url, int is_email); +static unsigned char *clean_url(chunk *url); static unsigned char *clean_title(chunk *title); +static unsigned char *clean_autolink(chunk *url, int is_email); inline static void chunk_free(chunk *c); inline static void chunk_trim(chunk *c); @@ -91,7 +92,7 @@ extern reference* make_reference(chunk *label, chunk *url, chunk *title) reference *ref; ref = malloc(sizeof(reference)); ref->label = normalize_reference(label); - ref->url = clean_url(url, 0); + ref->url = clean_url(url); ref->title = clean_title(title); return ref; } @@ -123,27 +124,31 @@ static unsigned char *bufdup(const unsigned char *buf) return new; } -inline static node_inl* make_link_from_reference(node_inl* label, reference *ref) +static inline node_inl *make_link_(node_inl *label, unsigned char *url, unsigned char *title) { node_inl* e = (node_inl*) malloc(sizeof(node_inl)); e->tag = INL_LINK; e->content.linkable.label = label; - e->content.linkable.url = bufdup(ref->url); - e->content.linkable.title = bufdup(ref->title); + e->content.linkable.url = url; + e->content.linkable.title = title; e->next = NULL; return e; } +inline static node_inl* make_ref_link(node_inl* label, reference *ref) +{ + return make_link_(label, bufdup(ref->url), bufdup(ref->title)); +} + +inline static node_inl* make_autolink(node_inl* label, chunk url, int is_email) +{ + return make_link_(label, clean_autolink(&url, is_email), NULL); +} + // Create an inline with a linkable string value. -inline static node_inl* make_link(node_inl* label, chunk url, chunk title, int is_email) +inline static node_inl* make_link(node_inl* label, chunk url, chunk title) { - node_inl* e = (node_inl*) malloc(sizeof(node_inl)); - e->tag = INL_LINK; - e->content.linkable.label = label; - e->content.linkable.url = clean_url(&url, is_email); - e->content.linkable.title = clean_title(&title); - e->next = NULL; - return e; + return make_link_(label, clean_url(&url), clean_title(&title)); } inline static node_inl* make_inlines(int t, node_inl* contents) @@ -587,7 +592,7 @@ extern void unescape_buffer(strbuf *buf) // Clean a URL: remove surrounding whitespace and surrounding <>, // and remove \ that escape punctuation. -static unsigned char *clean_url(chunk *url, int is_email) +static unsigned char *clean_url(chunk *url) { strbuf buf = GH_BUF_INIT; @@ -596,9 +601,6 @@ static unsigned char *clean_url(chunk *url, int is_email) if (url->len == 0) return NULL; - if (is_email) - strbuf_puts(&buf, "mailto:"); - if (url->data[0] == '<' && url->data[url->len - 1] == '>') { houdini_unescape_html_f(&buf, url->data + 1, url->len - 2); } else { @@ -609,6 +611,22 @@ static unsigned char *clean_url(chunk *url, int is_email) return strbuf_detach(&buf); } +static unsigned char *clean_autolink(chunk *url, int is_email) +{ + strbuf buf = GH_BUF_INIT; + + chunk_trim(url); + + if (url->len == 0) + return NULL; + + if (is_email) + strbuf_puts(&buf, "mailto:"); + + houdini_unescape_html_f(&buf, url->data, url->len); + return strbuf_detach(&buf); +} + // Clean a title: remove surrounding quotes and remove \ that escape punctuation. static unsigned char *clean_title(chunk *title) { @@ -649,11 +667,9 @@ static node_inl* handle_pointy_brace(subject* subj) contents = chunk_dup(&subj->input, subj->pos, matchlen - 1); subj->pos += matchlen; - return make_link( + return make_autolink( make_str_with_entities(&contents), - contents, - chunk_literal(""), - 0 + contents, 0 ); } @@ -663,11 +679,9 @@ static node_inl* handle_pointy_brace(subject* subj) contents = chunk_dup(&subj->input, subj->pos, matchlen - 1); subj->pos += matchlen; - return make_link( + return make_autolink( make_str_with_entities(&contents), - contents, - chunk_literal(""), - 1 + contents, 1 ); } @@ -792,7 +806,7 @@ static node_inl* handle_left_bracket(subject* subj) title = chunk_dup(&subj->input, starttitle, endtitle - starttitle); lab = parse_chunk_inlines(&rawlabel, NULL); - return make_link(lab, url, title, 0); + return make_link(lab, url, title); } else { // if we get here, we matched a label but didn't get further: subj->pos = endlabel; @@ -823,7 +837,7 @@ static node_inl* handle_left_bracket(subject* subj) ref = lookup_reference(subj->reference_map, &reflabel); if (ref != NULL) { // found lab = parse_chunk_inlines(&rawlabel, NULL); - result = make_link_from_reference(lab, ref); + result = make_ref_link(lab, ref); } else { subj->pos = endlabel; lab = parse_chunk_inlines(&rawlabel, subj->reference_map); -- cgit v1.2.3 From 7426f9ae60272a19bd4611b8579647118033a1e6 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 7 Sep 2014 22:48:33 +0200 Subject: Abstract the Block union --- src/blocks.c | 94 +++++++++++++++++++++++++++------------------------------ src/html/html.c | 8 ++--- src/print.c | 11 +++---- src/stmd.h | 20 +++++++----- 4 files changed, 67 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/blocks.c b/src/blocks.c index 8c7d49c..72b2dc2 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -18,35 +18,32 @@ static void finalize(node_block* b, int line_number); static node_block* make_block(int tag, int start_line, int start_column) { node_block* e; - e = (node_block*) malloc(sizeof(node_block)); + + e = malloc(sizeof(node_block)); + memset(e, 0x0, sizeof(*e)); + e->tag = tag; e->open = true; - e->last_line_blank = false; e->start_line = start_line; e->start_column = start_column; e->end_line = start_line; - e->children = NULL; - e->last_child = NULL; - e->parent = NULL; - e->top = NULL; - e->attributes.refmap = NULL; strbuf_init(&e->string_content, 32); - e->inline_content = NULL; - e->next = NULL; - e->prev = NULL; + return e; } // Create a root document node_block. extern node_block* make_document() { - node_block * e = make_block(BLOCK_DOCUMENT, 1, 1); - reference * map = NULL; + node_block *e = make_block(BLOCK_DOCUMENT, 1, 1); + reference *map = NULL; reference ** refmap; + refmap = (reference**) malloc(sizeof(reference*)); *refmap = map; - e->attributes.refmap = refmap; + e->as.document.refmap = refmap; e->top = e; + return e; } @@ -128,8 +125,8 @@ static bool ends_with_blank_line(node_block* node_block) // Break out of all containing lists static int break_out_of_lists(node_block ** bptr, int line_number) { - node_block * container = *bptr; - node_block * b = container->top; + node_block *container = *bptr; + node_block *b = container->top; // find first containing BLOCK_LIST: while (b && b->tag != BLOCK_LIST) { b = b->last_child; @@ -167,7 +164,7 @@ static void finalize(node_block* b, int line_number) case BLOCK_PARAGRAPH: pos = 0; while (strbuf_at(&b->string_content, 0) == '[' && - (pos = parse_reference(&b->string_content, b->top->attributes.refmap))) { + (pos = parse_reference(&b->string_content, b->top->as.document.refmap))) { strbuf_drop(&b->string_content, pos); } @@ -185,27 +182,27 @@ static void finalize(node_block* b, int line_number) // first line of contents becomes info firstlinelen = strbuf_strchr(&b->string_content, '\n', 0); - strbuf_init(&b->attributes.fenced_code_data.info, 0); + strbuf_init(&b->as.code.info, 0); houdini_unescape_html_f( - &b->attributes.fenced_code_data.info, + &b->as.code.info, b->string_content.ptr, firstlinelen ); strbuf_drop(&b->string_content, firstlinelen + 1); - strbuf_trim(&b->attributes.fenced_code_data.info); - unescape_buffer(&b->attributes.fenced_code_data.info); + strbuf_trim(&b->as.code.info); + unescape_buffer(&b->as.code.info); break; case BLOCK_LIST: // determine tight/loose status - b->attributes.list_data.tight = true; // tight by default + b->as.list.tight = true; // tight by default item = b->children; while (item) { // check for non-final non-empty list item ending with blank line: if (item->last_line_blank && item->next) { - b->attributes.list_data.tight = false; + b->as.list.tight = false; break; } // recurse into children of list item, to see if there are @@ -214,12 +211,12 @@ static void finalize(node_block* b, int line_number) while (subitem) { if (ends_with_blank_line(subitem) && (item->next || subitem->next)) { - b->attributes.list_data.tight = false; + b->as.list.tight = false; break; } subitem = subitem->next; } - if (!(b->attributes.list_data.tight)) { + if (!(b->as.list.tight)) { break; } item = item->next; @@ -269,9 +266,9 @@ extern void free_blocks(node_block* e) free_inlines(e->inline_content); strbuf_free(&e->string_content); if (e->tag == BLOCK_FENCED_CODE) { - strbuf_free(&e->attributes.fenced_code_data.info); + strbuf_free(&e->as.code.info); } else if (e->tag == BLOCK_DOCUMENT) { - free_reference_map(e->attributes.refmap); + free_reference_map(e->as.document.refmap); } free_blocks(e->children); free(e); @@ -362,13 +359,12 @@ static int parse_list_marker(chunk *input, int pos, struct ListData ** dataptr) } // Return 1 if list item belongs in list, else 0. -static int lists_match(struct ListData list_data, - struct ListData item_data) +static int lists_match(struct ListData *list_data, struct ListData *item_data) { - return (list_data.list_type == item_data.list_type && - list_data.delimiter == item_data.delimiter && - // list_data.marker_offset == item_data.marker_offset && - list_data.bullet_char == item_data.bullet_char); + return (list_data->list_type == item_data->list_type && + list_data->delimiter == item_data->delimiter && + // list_data->marker_offset == item_data.marker_offset && + list_data->bullet_char == item_data->bullet_char); } static node_block *finalize_document(node_block *document, int linenum) @@ -379,7 +375,7 @@ static node_block *finalize_document(node_block *document, int linenum) } finalize(document, linenum); - process_inlines(document, document->attributes.refmap); + process_inlines(document, document->as.document.refmap); return document; } @@ -496,10 +492,10 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) } else if (container->tag == BLOCK_LIST_ITEM) { - if (indent >= container->attributes.list_data.marker_offset + - container->attributes.list_data.padding) { - offset += container->attributes.list_data.marker_offset + - container->attributes.list_data.padding; + if (indent >= container->as.list.marker_offset + + container->as.list.padding) { + offset += container->as.list.marker_offset + + container->as.list.padding; } else if (blank) { offset = first_nonspace; } else { @@ -525,7 +521,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) } else if (container->tag == BLOCK_FENCED_CODE) { // skip optional spaces of fence offset - i = container->attributes.fenced_code_data.fence_offset; + i = container->as.code.fence_offset; while (i > 0 && peek_at(&input, offset) == ' ') { offset++; i--; @@ -598,14 +594,14 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) level++; hashpos++; } - container->attributes.header_level = level; + container->as.header.level = level; } else if ((matched = scan_open_code_fence(&input, first_nonspace))) { container = add_child(container, BLOCK_FENCED_CODE, line_number, first_nonspace + 1); - container->attributes.fenced_code_data.fence_char = peek_at(&input, first_nonspace); - container->attributes.fenced_code_data.fence_length = matched; - container->attributes.fenced_code_data.fence_offset = first_nonspace - offset; + container->as.code.fence_char = peek_at(&input, first_nonspace); + container->as.code.fence_length = matched; + container->as.code.fence_offset = first_nonspace - offset; offset = first_nonspace + matched; } else if ((matched = scan_html_block_tag(&input, first_nonspace))) { @@ -620,7 +616,7 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) strbuf_len(&container->string_content) - 2) < 0) { container->tag = BLOCK_SETEXT_HEADER; - container->attributes.header_level = lev; + container->as.header.level = lev; offset = input.len - 1; } else if (!(container->tag == BLOCK_PARAGRAPH && !all_matched) && @@ -657,19 +653,19 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) data->marker_offset = indent; if (container->tag != BLOCK_LIST || - !lists_match(container->attributes.list_data, *data)) { + !lists_match(&container->as.list, data)) { container = add_child(container, BLOCK_LIST, line_number, first_nonspace + 1); - container->attributes.list_data = *data; + + memcpy(&container->as.list, data, sizeof(*data)); } // add the list item container = add_child(container, BLOCK_LIST_ITEM, line_number, first_nonspace + 1); /* TODO: static */ - container->attributes.list_data = *data; + memcpy(&container->as.list, data, sizeof(*data)); free(data); - } else { break; } @@ -732,9 +728,9 @@ static void incorporate_line(strbuf *line, int line_number, node_block** curptr) matched = 0; if (indent <= 3 && - peek_at(&input, first_nonspace) == container->attributes.fenced_code_data.fence_char) { + peek_at(&input, first_nonspace) == container->as.code.fence_char) { int fence_len = scan_close_code_fence(&input, first_nonspace); - if (fence_len > container->attributes.fenced_code_data.fence_length) + if (fence_len > container->as.code.fence_length) matched = 1; } diff --git a/src/html/html.c b/src/html/html.c index 595dfcd..129335f 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -72,7 +72,7 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) case BLOCK_LIST: // make sure a list starts at the beginning of the line: cr(html); - data = &(b->attributes.list_data); + data = &(b->as.list); if (data->start > 1) { strbuf_printf(html, "<%s start=\"%d\">\n", @@ -90,9 +90,9 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) case BLOCK_ATX_HEADER: case BLOCK_SETEXT_HEADER: cr(html); - strbuf_printf(html, "", b->attributes.header_level); + strbuf_printf(html, "", b->as.header.level); inlines_to_html(html, b->inline_content); - strbuf_printf(html, "\n", b->attributes.header_level); + strbuf_printf(html, "\n", b->as.header.level); break; case BLOCK_INDENTED_CODE: @@ -102,7 +102,7 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) strbuf_puts(html, "tag == BLOCK_FENCED_CODE) { - strbuf *info = &b->attributes.fenced_code_data.info; + strbuf *info = &b->as.code.info; if (strbuf_len(info) > 0) { int first_tag = strbuf_strchr(info, ' ', 0); diff --git a/src/print.c b/src/print.c index 9240dac..36140a8 100644 --- a/src/print.c +++ b/src/print.c @@ -54,12 +54,11 @@ extern void print_blocks(node_block* b, int indent) print_blocks(b->children, indent + 2); break; case BLOCK_LIST_ITEM: - data = &(b->attributes.list_data); printf("list_item\n"); print_blocks(b->children, indent + 2); break; case BLOCK_LIST: - data = &(b->attributes.list_data); + data = &(b->as.list); if (data->list_type == ordered) { printf("list (type=ordered tight=%s start=%d delim=%s)\n", (data->tight ? "true" : "false"), @@ -73,11 +72,11 @@ extern void print_blocks(node_block* b, int indent) print_blocks(b->children, indent + 2); break; case BLOCK_ATX_HEADER: - printf("atx_header (level=%d)\n", b->attributes.header_level); + printf("atx_header (level=%d)\n", b->as.header.level); print_inlines(b->inline_content, indent + 2); break; case BLOCK_SETEXT_HEADER: - printf("setext_header (level=%d)\n", b->attributes.header_level); + printf("setext_header (level=%d)\n", b->as.header.level); print_inlines(b->inline_content, indent + 2); break; case BLOCK_PARAGRAPH: @@ -94,8 +93,8 @@ extern void print_blocks(node_block* b, int indent) break; case BLOCK_FENCED_CODE: printf("fenced_code length=%d info=", - b->attributes.fenced_code_data.fence_length); - print_str(b->attributes.fenced_code_data.info.ptr, -1); + b->as.code.fence_length); + print_str(b->as.code.info.ptr, -1); putchar(' '); print_str(b->string_content.ptr, -1); putchar('\n'); diff --git a/src/stmd.h b/src/stmd.h index c80eeda..21a86b0 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -96,14 +96,20 @@ struct node_block { struct node_block* top; strbuf string_content; node_inl* inline_content; + union { - struct ListData list_data; - struct FencedCodeData fenced_code_data; - int header_level; - reference** refmap; - } attributes; - struct node_block * next; - struct node_block * prev; + struct ListData list; + struct FencedCodeData code; + struct { + int level; + } header; + struct { + reference** refmap; + } document; + } as; + + struct node_block *next; + struct node_block *prev; }; typedef struct node_block node_block; -- cgit v1.2.3 From 2c06fa95fd3059a099bbe403beaf62f2e033f5b7 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 9 Sep 2014 03:42:05 +0200 Subject: Fix the class attribute for code fences --- src/html/html.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/html/html.c b/src/html/html.c index 129335f..74f6791 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -99,7 +99,7 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) case BLOCK_FENCED_CODE: cr(html); - strbuf_puts(html, "tag == BLOCK_FENCED_CODE) { strbuf *info = &b->as.code.info; @@ -109,14 +109,13 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) if (first_tag < 0) first_tag = strbuf_len(info); - - strbuf_puts(html, " class=\""); + strbuf_puts(html, " class=\"lang-"); escape_html(html, info->ptr, first_tag); strbuf_putc(html, '"'); } } - strbuf_puts(html, ">"); + strbuf_putc(html, '>'); escape_html(html, b->string_content.ptr, b->string_content.size); strbuf_puts(html, "\n"); break; -- cgit v1.2.3 From d21ef7b5db11075e038e60732682dfd8a5cf6a13 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 9 Sep 2014 03:42:46 +0200 Subject: Oops --- src/html/html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/html/html.c b/src/html/html.c index 74f6791..b48b10b 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -109,7 +109,7 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) if (first_tag < 0) first_tag = strbuf_len(info); - strbuf_puts(html, " class=\"lang-"); + strbuf_puts(html, " class=\"language-"); escape_html(html, info->ptr, first_tag); strbuf_putc(html, '"'); } -- cgit v1.2.3 From 9d86d2f32303ae0048f6a5daa552bacceb9b12ea Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 9 Sep 2014 04:00:36 +0200 Subject: Update the spec with better entity handling --- Makefile | 4 ++-- spec.txt | 22 ++++++++++++---------- src/html/houdini_html_u.c | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/Makefile b/Makefile index b5e487d..5d13272 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -CFLAGS=-g -pg -O3 -Wall -Wextra -std=c99 -Isrc $(OPTFLAGS) -LDFLAGS=-g -pg -O3 -Wall -Werror +CFLAGS=-g -O3 -Wall -Wextra -std=c99 -Isrc $(OPTFLAGS) +LDFLAGS=-g -O3 -Wall -Werror SRCDIR=src DATADIR=data diff --git a/spec.txt b/spec.txt index ebd6d98..112dccc 100644 --- a/spec.txt +++ b/spec.txt @@ -3762,20 +3762,20 @@ as the "unknown codepoint" character (`0xFFFD`) [Hexadecimal entities](#hexadecimal-entities) consist of `&#` + either `X` or `x` + a string of 1-8 hexadecimal digits -+ `;`. ++ `;`. They will also be parsed and turned into their corresponding UTF8 values in the AST. . - " ആ ಫ +" ആ ಫ . -

     " ആ ಫ

    +

    " ആ ಫ

    . Here are some nonentities: . -  &x; &#; &#x; � &ThisIsWayTooLongToBeAnEntityIsntIt; &hi?; +  &x; &#; &#x; &ThisIsWayTooLongToBeAnEntityIsntIt; &hi?; . -

    &nbsp &x; &#; &#x; &#123456789; &ThisIsWayTooLongToBeAnEntityIsntIt; &hi?;

    +

    &nbsp &x; &#; &#x; &ThisIsWayTooLongToBeAnEntityIsntIt; &hi?;

    . Although HTML5 does accept some entities without a trailing semicolon @@ -3808,7 +3808,7 @@ code blocks, including raw HTML, URLs, [link titles](#link-title), and . [foo](/föö "föö") . -

    foo

    +

    foo

    . . @@ -3816,7 +3816,7 @@ code blocks, including raw HTML, URLs, [link titles](#link-title), and [foo]: /föö "föö" . -

    foo

    +

    foo

    . . @@ -3824,7 +3824,7 @@ code blocks, including raw HTML, URLs, [link titles](#link-title), and foo ``` . -
    foo
    +
    foo
     
    . @@ -4817,12 +4817,14 @@ in Markdown:

    link

    . -URL-escaping and entities should be left alone inside the destination: +URL-escaping and should be left alone inside the destination, as all URL-escaped characters +are also valid URL characters. HTML entities in the destination will be parsed into their UTF8 +codepoints, as usual, and optionally URL-escaped when written as HTML. . [link](foo%20bä) . -

    link

    +

    link

    . Note that, because titles can often be parsed as destinations, diff --git a/src/html/houdini_html_u.c b/src/html/houdini_html_u.c index 762f980..b8e2d8d 100644 --- a/src/html/houdini_html_u.c +++ b/src/html/houdini_html_u.c @@ -24,7 +24,7 @@ houdini_unescape_ent(strbuf *ob, const uint8_t *src, size_t size) codepoint = (codepoint * 16) + ((src[i] | 32) % 39 - 9); } - if (i < size && src[i] == ';') { + if (i < size && src[i] == ';' && codepoint) { utf8proc_encode_char(codepoint, ob); return i + 1; } -- cgit v1.2.3 From 94a79a605f3e76a43f1f87a5044f6761b99e5ca5 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 10 Sep 2014 18:33:27 +0200 Subject: Cleanup reference implementation --- Makefile | 2 +- src/blocks.c | 16 ++--- src/buffer.c | 43 ++++++++++++++ src/buffer.h | 2 + src/inlines.c | 176 +++++++------------------------------------------------ src/references.c | 109 ++++++++++++++++++++++++++++++++++ src/references.h | 27 +++++++++ src/stmd.h | 26 +++----- src/utf8.c | 10 ++-- src/utf8.h | 5 +- 10 files changed, 225 insertions(+), 191 deletions(-) create mode 100644 src/references.c create mode 100644 src/references.h (limited to 'src') diff --git a/Makefile b/Makefile index 5d13272..11e2141 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ benchjs: node js/bench.js ${BENCHINP} HTML_OBJ=$(SRCDIR)/html/html.o $(SRCDIR)/html/houdini_href_e.o $(SRCDIR)/html/houdini_html_e.o $(SRCDIR)/html/houdini_html_u.o -STMD_OBJ=$(SRCDIR)/inlines.o $(SRCDIR)/buffer.o $(SRCDIR)/blocks.o $(SRCDIR)/scanners.c $(SRCDIR)/print.o $(SRCDIR)/utf8.o +STMD_OBJ=$(SRCDIR)/inlines.o $(SRCDIR)/buffer.o $(SRCDIR)/blocks.o $(SRCDIR)/scanners.c $(SRCDIR)/print.o $(SRCDIR)/utf8.o $(SRCDIR)/references.c $(PROG): $(SRCDIR)/html/html_unescape.h $(SRCDIR)/case_fold_switch.inc $(HTML_OBJ) $(STMD_OBJ) $(SRCDIR)/main.c $(CC) $(LDFLAGS) -o $@ $(HTML_OBJ) $(STMD_OBJ) $(SRCDIR)/main.c diff --git a/src/blocks.c b/src/blocks.c index 72b2dc2..30a8284 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -8,7 +8,6 @@ #include "utf8.h" #include "html/houdini.h" #include "scanners.h" -#include "uthash.h" #define peek_at(i, n) (i)->data[n] @@ -36,12 +35,7 @@ static node_block* make_block(int tag, int start_line, int start_column) extern node_block* make_document() { node_block *e = make_block(BLOCK_DOCUMENT, 1, 1); - reference *map = NULL; - reference ** refmap; - - refmap = (reference**) malloc(sizeof(reference*)); - *refmap = map; - e->as.document.refmap = refmap; + e->as.document.refmap = reference_map_new(); e->top = e; return e; @@ -164,7 +158,7 @@ static void finalize(node_block* b, int line_number) case BLOCK_PARAGRAPH: pos = 0; while (strbuf_at(&b->string_content, 0) == '[' && - (pos = parse_reference(&b->string_content, b->top->as.document.refmap))) { + (pos = parse_reference_inline(&b->string_content, b->top->as.document.refmap))) { strbuf_drop(&b->string_content, pos); } @@ -192,7 +186,7 @@ static void finalize(node_block* b, int line_number) strbuf_drop(&b->string_content, firstlinelen + 1); strbuf_trim(&b->as.code.info); - unescape_buffer(&b->as.code.info); + strbuf_unescape(&b->as.code.info); break; case BLOCK_LIST: // determine tight/loose status @@ -268,7 +262,7 @@ extern void free_blocks(node_block* e) if (e->tag == BLOCK_FENCED_CODE) { strbuf_free(&e->as.code.info); } else if (e->tag == BLOCK_DOCUMENT) { - free_reference_map(e->as.document.refmap); + reference_map_free(e->as.document.refmap); } free_blocks(e->children); free(e); @@ -278,7 +272,7 @@ extern void free_blocks(node_block* e) // Walk through node_block and all children, recursively, parsing // string content into inline content where appropriate. -void process_inlines(node_block* cur, reference** refmap) +void process_inlines(node_block* cur, reference_map *refmap) { switch (cur->tag) { case BLOCK_PARAGRAPH: diff --git a/src/buffer.c b/src/buffer.c index 90c2186..cdf8ca0 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -308,3 +308,46 @@ void strbuf_trim(strbuf *buf) buf->ptr[buf->size] = '\0'; } + +// Destructively modify string, collapsing consecutive +// space and newline characters into a single space. +void strbuf_normalize_whitespace(strbuf *s) +{ + bool last_char_was_space = false; + int r, w; + + for (r = 0, w = 0; r < s->size; ++r) { + switch (s->ptr[r]) { + case ' ': + case '\n': + if (last_char_was_space) + break; + + s->ptr[w++] = ' '; + last_char_was_space = true; + break; + + default: + s->ptr[w++] = s->ptr[r]; + last_char_was_space = false; + } + } + + strbuf_truncate(s, w); +} + +// Destructively unescape a string: remove backslashes before punctuation chars. +extern void strbuf_unescape(strbuf *buf) +{ + int r, w; + + for (r = 0, w = 0; r < buf->size; ++r) { + if (buf->ptr[r] == '\\' && ispunct(buf->ptr[r + 1])) + continue; + + buf->ptr[w++] = buf->ptr[r]; + } + + strbuf_truncate(buf, w); +} + diff --git a/src/buffer.h b/src/buffer.h index 6f45cbb..1bc1eee 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -108,5 +108,7 @@ int strbuf_strrchr(const strbuf *buf, int c, int pos); void strbuf_drop(strbuf *buf, int n); void strbuf_truncate(strbuf *buf, int len); void strbuf_trim(strbuf *buf); +void strbuf_normalize_whitespace(strbuf *s); +void strbuf_unescape(strbuf *s); #endif diff --git a/src/inlines.c b/src/inlines.c index aa0e13e..3040f09 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -7,110 +7,23 @@ #include "stmd.h" #include "html/houdini.h" #include "utf8.h" -#include "uthash.h" #include "scanners.h" typedef struct Subject { chunk input; int pos; - int label_nestlevel; - reference** reference_map; + int label_nestlevel; + reference_map *refmap; } subject; -reference* lookup_reference(reference** refmap, chunk *label); -reference* make_reference(chunk *label, chunk *url, chunk *title); - -static unsigned char *clean_url(chunk *url); -static unsigned char *clean_title(chunk *title); -static unsigned char *clean_autolink(chunk *url, int is_email); - -inline static void chunk_free(chunk *c); -inline static void chunk_trim(chunk *c); - -inline static chunk chunk_literal(const char *data); -inline static chunk chunk_buf_detach(strbuf *buf); -inline static chunk chunk_dup(const chunk *ch, int pos, int len); - -static node_inl *parse_chunk_inlines(chunk *chunk, reference** refmap); +static node_inl *parse_chunk_inlines(chunk *chunk, reference_map *refmap); static node_inl *parse_inlines_while(subject* subj, int (*f)(subject*)); static int parse_inline(subject* subj, node_inl ** last); -static void subject_from_chunk(subject *e, chunk *chunk, reference** refmap); -static void subject_from_buf(subject *e, strbuf *buffer, reference** refmap); +static void subject_from_chunk(subject *e, chunk *chunk, reference_map *refmap); +static void subject_from_buf(subject *e, strbuf *buffer, reference_map *refmap); static int subject_find_special_char(subject *subj); -static void normalize_whitespace(strbuf *s); - -extern void free_reference(reference *ref) { - free(ref->label); - free(ref->url); - free(ref->title); - free(ref); -} - -extern void free_reference_map(reference **refmap) { - /* free the hash table contents */ - reference *s; - reference *tmp; - if (refmap != NULL) { - HASH_ITER(hh, *refmap, s, tmp) { - HASH_DEL(*refmap, s); - free_reference(s); - } - free(refmap); - } -} - -// normalize reference: collapse internal whitespace to single space, -// remove leading/trailing whitespace, case fold -static unsigned char *normalize_reference(chunk *ref) -{ - strbuf normalized = GH_BUF_INIT; - - utf8proc_case_fold(&normalized, ref->data, ref->len); - strbuf_trim(&normalized); - normalize_whitespace(&normalized); - - return strbuf_detach(&normalized); -} - -// Returns reference if refmap contains a reference with matching -// label, otherwise NULL. -extern reference* lookup_reference(reference** refmap, chunk *label) -{ - reference *ref = NULL; - unsigned char *norm = normalize_reference(label); - if (refmap != NULL) { - HASH_FIND_STR(*refmap, (char*)norm, ref); - } - free(norm); - return ref; -} - -extern reference* make_reference(chunk *label, chunk *url, chunk *title) -{ - reference *ref; - ref = malloc(sizeof(reference)); - ref->label = normalize_reference(label); - ref->url = clean_url(url); - ref->title = clean_title(title); - return ref; -} - -extern void add_reference(reference** refmap, reference* ref) -{ - reference * t = NULL; - const char *label = (const char *)ref->label; - - HASH_FIND(hh, *refmap, label, strlen(label), t); - - if (t == NULL) { - HASH_ADD_KEYPTR(hh, *refmap, label, strlen(label), ref); - } else { - free_reference(ref); // we free this now since it won't be in the refmap - } -} - static unsigned char *bufdup(const unsigned char *buf) { unsigned char *new = NULL; @@ -236,26 +149,26 @@ inline static node_inl* append_inlines(node_inl* a, node_inl* b) return a; } -static void subject_from_buf(subject *e, strbuf *buffer, reference** refmap) +static void subject_from_buf(subject *e, strbuf *buffer, reference_map *refmap) { e->input.data = buffer->ptr; e->input.len = buffer->size; e->input.alloc = 0; e->pos = 0; e->label_nestlevel = 0; - e->reference_map = refmap; + e->refmap = refmap; chunk_rtrim(&e->input); } -static void subject_from_chunk(subject *e, chunk *chunk, reference** refmap) +static void subject_from_chunk(subject *e, chunk *chunk, reference_map *refmap) { e->input.data = chunk->data; e->input.len = chunk->len; e->input.alloc = 0; e->pos = 0; e->label_nestlevel = 0; - e->reference_map = refmap; + e->refmap = refmap; chunk_rtrim(&e->input); } @@ -325,33 +238,6 @@ static int scan_to_closing_backticks(subject* subj, int openticklength) return (subj->pos); } -// Destructively modify string, collapsing consecutive -// space and newline characters into a single space. -static void normalize_whitespace(strbuf *s) -{ - bool last_char_was_space = false; - int r, w; - - for (r = 0, w = 0; r < s->size; ++r) { - switch (s->ptr[r]) { - case ' ': - case '\n': - if (last_char_was_space) - break; - - s->ptr[w++] = ' '; - last_char_was_space = true; - break; - - default: - s->ptr[w++] = s->ptr[r]; - last_char_was_space = false; - } - } - - 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 node_inl* handle_backticks(subject *subj) @@ -368,7 +254,7 @@ static node_inl* handle_backticks(subject *subj) strbuf_set(&buf, subj->input.data + startpos, endpos - startpos - openticks.len); strbuf_trim(&buf); - normalize_whitespace(&buf); + strbuf_normalize_whitespace(&buf); return make_code(chunk_buf_detach(&buf)); } @@ -575,24 +461,9 @@ static node_inl *make_str_with_entities(chunk *content) } } -// Destructively unescape a string: remove backslashes before punctuation chars. -extern void unescape_buffer(strbuf *buf) -{ - int r, w; - - for (r = 0, w = 0; r < buf->size; ++r) { - if (buf->ptr[r] == '\\' && ispunct(buf->ptr[r + 1])) - continue; - - buf->ptr[w++] = buf->ptr[r]; - } - - strbuf_truncate(buf, w); -} - // Clean a URL: remove surrounding whitespace and surrounding <>, // and remove \ that escape punctuation. -static unsigned char *clean_url(chunk *url) +unsigned char *clean_url(chunk *url) { strbuf buf = GH_BUF_INIT; @@ -607,11 +478,11 @@ static unsigned char *clean_url(chunk *url) houdini_unescape_html_f(&buf, url->data, url->len); } - unescape_buffer(&buf); + strbuf_unescape(&buf); return strbuf_detach(&buf); } -static unsigned char *clean_autolink(chunk *url, int is_email) +unsigned char *clean_autolink(chunk *url, int is_email) { strbuf buf = GH_BUF_INIT; @@ -628,7 +499,7 @@ static unsigned char *clean_autolink(chunk *url, int is_email) } // Clean a title: remove surrounding quotes and remove \ that escape punctuation. -static unsigned char *clean_title(chunk *title) +unsigned char *clean_title(chunk *title) { strbuf buf = GH_BUF_INIT; unsigned char first, last; @@ -648,7 +519,7 @@ static unsigned char *clean_title(chunk *title) houdini_unescape_html_f(&buf, title->data, title->len); } - unescape_buffer(&buf); + strbuf_unescape(&buf); return strbuf_detach(&buf); } @@ -810,7 +681,7 @@ static node_inl* handle_left_bracket(subject* subj) } else { // if we get here, we matched a label but didn't get further: subj->pos = endlabel; - lab = parse_chunk_inlines(&rawlabel, subj->reference_map); + lab = parse_chunk_inlines(&rawlabel, subj->refmap); result = append_inlines(make_str(chunk_literal("[")), append_inlines(lab, make_str(chunk_literal("]")))); @@ -834,13 +705,13 @@ static node_inl* handle_left_bracket(subject* subj) } // lookup rawlabel in subject->reference_map: - ref = lookup_reference(subj->reference_map, &reflabel); + ref = reference_lookup(subj->refmap, &reflabel); if (ref != NULL) { // found lab = parse_chunk_inlines(&rawlabel, NULL); result = make_ref_link(lab, ref); } else { subj->pos = endlabel; - lab = parse_chunk_inlines(&rawlabel, subj->reference_map); + lab = parse_chunk_inlines(&rawlabel, subj->refmap); result = append_inlines(make_str(chunk_literal("[")), append_inlines(lab, make_str(chunk_literal("]")))); } @@ -887,7 +758,7 @@ extern node_inl* parse_inlines_while(subject* subj, int (*f)(subject*)) return result; } -node_inl *parse_chunk_inlines(chunk *chunk, reference** refmap) +node_inl *parse_chunk_inlines(chunk *chunk, reference_map *refmap) { subject subj; subject_from_chunk(&subj, chunk, refmap); @@ -987,7 +858,7 @@ static int parse_inline(subject* subj, node_inl ** last) return 1; } -extern node_inl* parse_inlines(strbuf *input, reference** refmap) +extern node_inl* parse_inlines(strbuf *input, reference_map *refmap) { subject subj; subject_from_buf(&subj, input, refmap); @@ -1009,7 +880,7 @@ void spnl(subject* subj) // Modify refmap if a reference is encountered. // Return 0 if no reference found, otherwise position of subject // after reference is parsed. -extern int parse_reference(strbuf *input, reference** refmap) +int parse_reference_inline(strbuf *input, reference_map *refmap) { subject subj; @@ -1019,7 +890,6 @@ extern int parse_reference(strbuf *input, reference** refmap) int matchlen = 0; int beforetitle; - reference *new = NULL; subject_from_buf(&subj, input, NULL); @@ -1065,9 +935,7 @@ extern int parse_reference(strbuf *input, reference** refmap) return 0; } // insert reference into refmap - new = make_reference(&lab, &url, &title); - add_reference(refmap, new); - + reference_create(refmap, &lab, &url, &title); return subj.pos; } diff --git a/src/references.c b/src/references.c new file mode 100644 index 0000000..ff64b00 --- /dev/null +++ b/src/references.c @@ -0,0 +1,109 @@ +#include "stmd.h" +#include "utf8.h" +#include "references.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; +} + +// normalize reference: collapse internal whitespace to single space, +// remove leading/trailing whitespace, case fold +static unsigned char *normalize_reference(chunk *ref) +{ + strbuf normalized = GH_BUF_INIT; + + utf8proc_case_fold(&normalized, ref->data, ref->len); + strbuf_trim(&normalized); + strbuf_normalize_whitespace(&normalized); + + return strbuf_detach(&normalized); +} + +static void add_reference(reference_map *map, reference* ref) +{ + ref->next = map->table[ref->hash % REFMAP_SIZE]; + map->table[ref->hash % REFMAP_SIZE] = ref; +} + +extern reference *reference_create(reference_map *map, chunk *label, chunk *url, chunk *title) +{ + reference *ref; + ref = malloc(sizeof(reference)); + ref->label = normalize_reference(label); + ref->hash = refhash(ref->label); + ref->url = clean_url(url); + ref->title = clean_title(title); + ref->next = NULL; + + add_reference(map, ref); + + return ref; +} + +// Returns reference if refmap contains a reference with matching +// label, otherwise NULL. +reference* reference_lookup(reference_map *map, chunk *label) +{ + reference *ref = NULL; + unsigned char *norm; + unsigned int hash; + + if (map == NULL) + return NULL; + + norm = normalize_reference(label); + hash = refhash(norm); + ref = map->table[hash % REFMAP_SIZE]; + + while (ref) { + if (ref->label[0] == norm[0] && + !strcmp((char *)ref->label, (char *)norm)) + break; + ref = ref->next; + } + + free(norm); + return ref; +} + +static void reference_free(reference *ref) +{ + free(ref->label); + free(ref->url); + free(ref->title); + free(ref); +} + +void reference_map_free(reference_map *map) +{ + unsigned int i; + + for (i = 0; i < REFMAP_SIZE; ++i) { + reference *ref = map->table[i]; + reference *next; + + while (ref) { + next = ref->next; + reference_free(ref); + ref = next; + } + } + + free(map->table); + free(map); +} + +reference_map *reference_map_new(void) +{ + reference_map *map = malloc(sizeof(reference_map)); + memset(map, 0x0, sizeof(reference_map)); + return map; +} + diff --git a/src/references.h b/src/references.h new file mode 100644 index 0000000..78fffe7 --- /dev/null +++ b/src/references.h @@ -0,0 +1,27 @@ +#ifndef _REFERENCES_H_ +#define _REFERENCES_H_ + +#define REFMAP_SIZE 16 + +struct reference { + struct reference *next; + unsigned char *label; + unsigned char *url; + unsigned char *title; + unsigned int hash; +}; + +typedef struct reference reference; + +struct reference_map { + reference *table[REFMAP_SIZE]; +}; + +typedef struct reference_map reference_map; + +reference_map *reference_map_new(void); +void reference_map_free(reference_map *map); +reference* reference_lookup(reference_map *map, chunk *label); +extern reference *reference_create(reference_map *map, chunk *label, chunk *url, chunk *title); + +#endif diff --git a/src/stmd.h b/src/stmd.h index 21a86b0..4e21e6c 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -5,7 +5,7 @@ #include #include "buffer.h" #include "chunk.h" -#include "uthash.h" +#include "references.h" #define VERSION "0.1" #define CODE_INDENT 4 @@ -36,17 +36,7 @@ struct node_inl { typedef struct node_inl node_inl; -struct reference { - unsigned char *label; - unsigned char *url; - unsigned char *title; - UT_hash_handle hh; // used by uthash -}; - -typedef struct reference reference; - // Types for blocks - struct ListData { enum { bullet, @@ -104,7 +94,7 @@ struct node_block { int level; } header; struct { - reference** refmap; + reference_map *refmap; } document; } as; @@ -114,14 +104,10 @@ struct node_block { typedef struct node_block node_block; -node_inl* parse_inlines(strbuf *input, reference** refmap); +node_inl* parse_inlines(strbuf *input, reference_map *refmap); void free_inlines(node_inl* e); -int parse_reference(strbuf *input, reference** refmap); -void free_reference(reference *ref); -void free_reference_map(reference **refmap); - -void add_reference(reference** refmap, reference* ref); +int parse_reference_inline(strbuf *input, reference_map *refmap); void unescape_buffer(strbuf *buf); extern node_block* make_document(); @@ -138,4 +124,8 @@ void print_blocks(node_block* blk, int indent); void blocks_to_html(strbuf *html, node_block *b, bool tight); void inlines_to_html(strbuf *html, node_inl *b); +unsigned char *clean_url(chunk *url); +unsigned char *clean_autolink(chunk *url, int is_email); +unsigned char *clean_title(chunk *title); + #endif diff --git a/src/utf8.c b/src/utf8.c index 12d7ba5..c65aec6 100644 --- a/src/utf8.c +++ b/src/utf8.c @@ -25,7 +25,7 @@ static const int8_t utf8proc_utf8class[256] = { static void encode_unknown(strbuf *buf) { - static const unsigned char repl[] = {239, 191, 189}; + static const uint8_t repl[] = {239, 191, 189}; strbuf_put(buf, repl, 3); } @@ -52,9 +52,9 @@ ssize_t utf8proc_charlen(const uint8_t *str, ssize_t str_len) return length; } -void utf8proc_detab(strbuf *ob, const unsigned char *line, size_t size) +void utf8proc_detab(strbuf *ob, const uint8_t *line, size_t size) { - static const unsigned char whitespace[] = " "; + static const uint8_t whitespace[] = " "; size_t i = 0, tab = 0; @@ -132,7 +132,7 @@ ssize_t utf8proc_iterate(const uint8_t *str, ssize_t str_len, int32_t *dst) void utf8proc_encode_char(int32_t uc, strbuf *buf) { - unsigned char dst[4]; + uint8_t dst[4]; int len = 0; assert(uc >= 0); @@ -169,7 +169,7 @@ void utf8proc_encode_char(int32_t uc, strbuf *buf) strbuf_put(buf, dst, len); } -void utf8proc_case_fold(strbuf *dest, const unsigned char *str, int len) +void utf8proc_case_fold(strbuf *dest, const uint8_t *str, int len) { int32_t c; diff --git a/src/utf8.h b/src/utf8.h index 1e4e556..9506b75 100644 --- a/src/utf8.h +++ b/src/utf8.h @@ -1,12 +1,13 @@ #ifndef _H_STMD_UTF8_ #define _H_STMD_UTF8_ +#include #include "buffer.h" -void utf8proc_case_fold(strbuf *dest, const unsigned char *str, int len); +void utf8proc_case_fold(strbuf *dest, const uint8_t *str, int len); void utf8proc_encode_char(int32_t uc, strbuf *buf); ssize_t utf8proc_iterate(const uint8_t *str, ssize_t str_len, int32_t *dst); ssize_t utf8proc_charlen(const uint8_t *str, ssize_t str_len); -void utf8proc_detab(strbuf *dest, const unsigned char *line, size_t size); +void utf8proc_detab(strbuf *dest, const uint8_t *line, size_t size); #endif -- cgit v1.2.3 From 0a0a87333083058e945a54fcf196a6f119302d6b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 10 Sep 2014 18:33:51 +0200 Subject: Remove old hash table --- src/uthash.h | 948 ----------------------------------------------------------- 1 file changed, 948 deletions(-) delete mode 100644 src/uthash.h (limited to 'src') diff --git a/src/uthash.h b/src/uthash.h deleted file mode 100644 index b9bc7e9..0000000 --- a/src/uthash.h +++ /dev/null @@ -1,948 +0,0 @@ -/* -Copyright (c) 2003-2013, Troy D. Hanson http://troydhanson.github.com/uthash/ -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef UTHASH_H -#define UTHASH_H - -#include /* memcmp,strlen */ -#include /* ptrdiff_t */ -#include /* exit() */ - -/* These macros use decltype or the earlier __typeof GNU extension. - As decltype is only available in newer compilers (VS2010 or gcc 4.3+ - when compiling c++ source) this code uses whatever method is needed - or, for VS2008 where neither is available, uses casting workarounds. */ -#ifdef _MSC_VER /* MS compiler */ -#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ -#define DECLTYPE(x) (decltype(x)) -#else /* VS2008 or older (or VS2010 in C mode) */ -#define NO_DECLTYPE -#define DECLTYPE(x) -#endif -#else /* GNU, Sun and other compilers */ -#define DECLTYPE(x) (__typeof(x)) -#endif - -#ifdef NO_DECLTYPE -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - char **_da_dst = (char**)(&(dst)); \ - *_da_dst = (char*)(src); \ -} while(0) -#else -#define DECLTYPE_ASSIGN(dst,src) \ -do { \ - (dst) = DECLTYPE(dst)(src); \ -} while(0) -#endif - -/* a number of the hash function use uint32_t which isn't defined on win32 */ -#ifdef _MSC_VER -typedef unsigned int uint32_t; -typedef unsigned char uint8_t; -#else -#include /* uint32_t */ -#endif - -#define UTHASH_VERSION 1.9.8 - -#ifndef uthash_fatal -#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ -#endif -#ifndef uthash_malloc -#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ -#endif -#ifndef uthash_free -#define uthash_free(ptr,sz) free(ptr) /* free fcn */ -#endif - -#ifndef uthash_noexpand_fyi -#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ -#endif -#ifndef uthash_expand_fyi -#define uthash_expand_fyi(tbl) /* can be defined to log expands */ -#endif - -/* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */ -#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */ - -/* calculate the element whose hash handle address is hhe */ -#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) - -#define HASH_FIND(hh,head,keyptr,keylen,out) \ -do { \ - unsigned _hf_bkt,_hf_hashv; \ - out=NULL; \ - if (head) { \ - HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \ - if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \ - HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \ - keyptr,keylen,out); \ - } \ - } \ -} while (0) - -#ifdef HASH_BLOOM -#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM) -#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0) -#define HASH_BLOOM_MAKE(tbl) \ -do { \ - (tbl)->bloom_nbits = HASH_BLOOM; \ - (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ - if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ - memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ - (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ -} while (0) - -#define HASH_BLOOM_FREE(tbl) \ -do { \ - uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ -} while (0) - -#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8))) -#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8))) - -#define HASH_BLOOM_ADD(tbl,hashv) \ - HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) - -#define HASH_BLOOM_TEST(tbl,hashv) \ - HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) - -#else -#define HASH_BLOOM_MAKE(tbl) -#define HASH_BLOOM_FREE(tbl) -#define HASH_BLOOM_ADD(tbl,hashv) -#define HASH_BLOOM_TEST(tbl,hashv) (1) -#define HASH_BLOOM_BYTELEN 0 -#endif - -#define HASH_MAKE_TABLE(hh,head) \ -do { \ - (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ - sizeof(UT_hash_table)); \ - if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ - (head)->hh.tbl->tail = &((head)->hh); \ - (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ - (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ - (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ - (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl->buckets, 0, \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_MAKE((head)->hh.tbl); \ - (head)->hh.tbl->signature = HASH_SIGNATURE; \ -} while(0) - -#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ - HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add) - -#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ -do { \ - replaced=NULL; \ - HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \ - if (replaced!=NULL) { \ - HASH_DELETE(hh,head,replaced); \ - }; \ - HASH_ADD(hh,head,fieldname,keylen_in,add); \ -} while(0) - -#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ -do { \ - unsigned _ha_bkt; \ - (add)->hh.next = NULL; \ - (add)->hh.key = (char*)(keyptr); \ - (add)->hh.keylen = (unsigned)(keylen_in); \ - if (!(head)) { \ - head = (add); \ - (head)->hh.prev = NULL; \ - HASH_MAKE_TABLE(hh,head); \ - } else { \ - (head)->hh.tbl->tail->next = (add); \ - (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ - (head)->hh.tbl->tail = &((add)->hh); \ - } \ - (head)->hh.tbl->num_items++; \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \ - (add)->hh.hashv, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \ - HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \ - HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \ - HASH_FSCK(hh,head); \ -} while(0) - -#define HASH_TO_BKT( hashv, num_bkts, bkt ) \ -do { \ - bkt = ((hashv) & ((num_bkts) - 1)); \ -} while(0) - -/* delete "delptr" from the hash table. - * "the usual" patch-up process for the app-order doubly-linked-list. - * The use of _hd_hh_del below deserves special explanation. - * These used to be expressed using (delptr) but that led to a bug - * if someone used the same symbol for the head and deletee, like - * HASH_DELETE(hh,users,users); - * We want that to work, but by changing the head (users) below - * we were forfeiting our ability to further refer to the deletee (users) - * in the patch-up process. Solution: use scratch space to - * copy the deletee pointer, then the latter references are via that - * scratch pointer rather than through the repointed (users) symbol. - */ -#define HASH_DELETE(hh,head,delptr) \ -do { \ - unsigned _hd_bkt; \ - struct UT_hash_handle *_hd_hh_del; \ - if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - head = NULL; \ - } else { \ - _hd_hh_del = &((delptr)->hh); \ - if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ - (head)->hh.tbl->tail = \ - (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho); \ - } \ - if ((delptr)->hh.prev) { \ - ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ - } else { \ - DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ - } \ - if (_hd_hh_del->next) { \ - ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \ - (head)->hh.tbl->hho))->prev = \ - _hd_hh_del->prev; \ - } \ - HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ - HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ - (head)->hh.tbl->num_items--; \ - } \ - HASH_FSCK(hh,head); \ -} while (0) - - -/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ -#define HASH_FIND_STR(head,findstr,out) \ - HASH_FIND(hh,head,findstr,strlen(findstr),out) -#define HASH_ADD_STR(head,strfield,add) \ - HASH_ADD(hh,head,strfield,strlen(add->strfield),add) -#define HASH_REPLACE_STR(head,strfield,add,replaced) \ - HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced) -#define HASH_FIND_INT(head,findint,out) \ - HASH_FIND(hh,head,findint,sizeof(int),out) -#define HASH_ADD_INT(head,intfield,add) \ - HASH_ADD(hh,head,intfield,sizeof(int),add) -#define HASH_REPLACE_INT(head,intfield,add,replaced) \ - HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) -#define HASH_FIND_PTR(head,findptr,out) \ - HASH_FIND(hh,head,findptr,sizeof(void *),out) -#define HASH_ADD_PTR(head,ptrfield,add) \ - HASH_ADD(hh,head,ptrfield,sizeof(void *),add) -#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ - HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) -#define HASH_DEL(head,delptr) \ - HASH_DELETE(hh,head,delptr) - -/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. - * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. - */ -#ifdef HASH_DEBUG -#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) -#define HASH_FSCK(hh,head) \ -do { \ - unsigned _bkt_i; \ - unsigned _count, _bkt_count; \ - char *_prev; \ - struct UT_hash_handle *_thh; \ - if (head) { \ - _count = 0; \ - for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ - _bkt_count = 0; \ - _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ - _prev = NULL; \ - while (_thh) { \ - if (_prev != (char*)(_thh->hh_prev)) { \ - HASH_OOPS("invalid hh_prev %p, actual %p\n", \ - _thh->hh_prev, _prev ); \ - } \ - _bkt_count++; \ - _prev = (char*)(_thh); \ - _thh = _thh->hh_next; \ - } \ - _count += _bkt_count; \ - if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ - HASH_OOPS("invalid bucket count %d, actual %d\n", \ - (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ - } \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid hh item count %d, actual %d\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - /* traverse hh in app order; check next/prev integrity, count */ \ - _count = 0; \ - _prev = NULL; \ - _thh = &(head)->hh; \ - while (_thh) { \ - _count++; \ - if (_prev !=(char*)(_thh->prev)) { \ - HASH_OOPS("invalid prev %p, actual %p\n", \ - _thh->prev, _prev ); \ - } \ - _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ - _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ - (head)->hh.tbl->hho) : NULL ); \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid app item count %d, actual %d\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - } \ -} while (0) -#else -#define HASH_FSCK(hh,head) -#endif - -/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to - * the descriptor to which this macro is defined for tuning the hash function. - * The app can #include to get the prototype for write(2). */ -#ifdef HASH_EMIT_KEYS -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ -do { \ - unsigned _klen = fieldlen; \ - write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ - write(HASH_EMIT_KEYS, keyptr, fieldlen); \ -} while (0) -#else -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) -#endif - -/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ -#ifdef HASH_FUNCTION -#define HASH_FCN HASH_FUNCTION -#else -#define HASH_FCN HASH_JEN -#endif - -/* The Bernstein hash function, used in Perl prior to v5.6 */ -#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _hb_keylen=keylen; \ - char *_hb_key=(char*)(key); \ - (hashv) = 0; \ - while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \ - bkt = (hashv) & (num_bkts-1); \ -} while (0) - - -/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at - * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ -#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _sx_i; \ - char *_hs_key=(char*)(key); \ - hashv = 0; \ - for(_sx_i=0; _sx_i < keylen; _sx_i++) \ - hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ - bkt = hashv & (num_bkts-1); \ -} while (0) - -#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _fn_i; \ - char *_hf_key=(char*)(key); \ - hashv = 2166136261UL; \ - for(_fn_i=0; _fn_i < keylen; _fn_i++) \ - hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _ho_i; \ - char *_ho_key=(char*)(key); \ - hashv = 0; \ - for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ - hashv += _ho_key[_ho_i]; \ - hashv += (hashv << 10); \ - hashv ^= (hashv >> 6); \ - } \ - hashv += (hashv << 3); \ - hashv ^= (hashv >> 11); \ - hashv += (hashv << 15); \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#define HASH_JEN_MIX(a,b,c) \ -do { \ - a -= b; a -= c; a ^= ( c >> 13 ); \ - b -= c; b -= a; b ^= ( a << 8 ); \ - c -= a; c -= b; c ^= ( b >> 13 ); \ - a -= b; a -= c; a ^= ( c >> 12 ); \ - b -= c; b -= a; b ^= ( a << 16 ); \ - c -= a; c -= b; c ^= ( b >> 5 ); \ - a -= b; a -= c; a ^= ( c >> 3 ); \ - b -= c; b -= a; b ^= ( a << 10 ); \ - c -= a; c -= b; c ^= ( b >> 15 ); \ -} while (0) - -#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _hj_i,_hj_j,_hj_k; \ - unsigned char *_hj_key=(unsigned char*)(key); \ - hashv = 0xfeedbeef; \ - _hj_i = _hj_j = 0x9e3779b9; \ - _hj_k = (unsigned)(keylen); \ - while (_hj_k >= 12) { \ - _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ - + ( (unsigned)_hj_key[2] << 16 ) \ - + ( (unsigned)_hj_key[3] << 24 ) ); \ - _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ - + ( (unsigned)_hj_key[6] << 16 ) \ - + ( (unsigned)_hj_key[7] << 24 ) ); \ - hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ - + ( (unsigned)_hj_key[10] << 16 ) \ - + ( (unsigned)_hj_key[11] << 24 ) ); \ - \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - \ - _hj_key += 12; \ - _hj_k -= 12; \ - } \ - hashv += keylen; \ - switch ( _hj_k ) { \ - case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ - case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ - case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ - case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ - case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ - case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ - case 5: _hj_j += _hj_key[4]; \ - case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ - case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ - case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ - case 1: _hj_i += _hj_key[0]; \ - } \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -/* The Paul Hsieh hash function */ -#undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -#define get16bits(d) (*((const uint16_t *) (d))) -#endif - -#if !defined (get16bits) -#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ - +(uint32_t)(((const uint8_t *)(d))[0]) ) -#endif -#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned char *_sfh_key=(unsigned char*)(key); \ - uint32_t _sfh_tmp, _sfh_len = keylen; \ - \ - int _sfh_rem = _sfh_len & 3; \ - _sfh_len >>= 2; \ - hashv = 0xcafebabe; \ - \ - /* Main loop */ \ - for (;_sfh_len > 0; _sfh_len--) { \ - hashv += get16bits (_sfh_key); \ - _sfh_tmp = (uint32_t)(get16bits (_sfh_key+2)) << 11 ^ hashv; \ - hashv = (hashv << 16) ^ _sfh_tmp; \ - _sfh_key += 2*sizeof (uint16_t); \ - hashv += hashv >> 11; \ - } \ - \ - /* Handle end cases */ \ - switch (_sfh_rem) { \ - case 3: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 16; \ - hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18); \ - hashv += hashv >> 11; \ - break; \ - case 2: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 11; \ - hashv += hashv >> 17; \ - break; \ - case 1: hashv += *_sfh_key; \ - hashv ^= hashv << 10; \ - hashv += hashv >> 1; \ - } \ - \ - /* Force "avalanching" of final 127 bits */ \ - hashv ^= hashv << 3; \ - hashv += hashv >> 5; \ - hashv ^= hashv << 4; \ - hashv += hashv >> 17; \ - hashv ^= hashv << 25; \ - hashv += hashv >> 6; \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#ifdef HASH_USING_NO_STRICT_ALIASING -/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. - * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. - * MurmurHash uses the faster approach only on CPU's where we know it's safe. - * - * Note the preprocessor built-in defines can be emitted using: - * - * gcc -m64 -dM -E - < /dev/null (on gcc) - * cc -## a.c (where a.c is a simple test file) (Sun Studio) - */ -#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86)) -#define MUR_GETBLOCK(p,i) p[i] -#else /* non intel */ -#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0) -#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1) -#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2) -#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3) -#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) -#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) -#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) -#else /* assume little endian non-intel */ -#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) -#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) -#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) -#endif -#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ - (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ - (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ - MUR_ONE_THREE(p)))) -#endif -#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) -#define MUR_FMIX(_h) \ -do { \ - _h ^= _h >> 16; \ - _h *= 0x85ebca6b; \ - _h ^= _h >> 13; \ - _h *= 0xc2b2ae35l; \ - _h ^= _h >> 16; \ -} while(0) - -#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \ -do { \ - const uint8_t *_mur_data = (const uint8_t*)(key); \ - const int _mur_nblocks = (keylen) / 4; \ - uint32_t _mur_h1 = 0xf88D5353; \ - uint32_t _mur_c1 = 0xcc9e2d51; \ - uint32_t _mur_c2 = 0x1b873593; \ - uint32_t _mur_k1 = 0; \ - const uint8_t *_mur_tail; \ - const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \ - int _mur_i; \ - for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \ - _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - \ - _mur_h1 ^= _mur_k1; \ - _mur_h1 = MUR_ROTL32(_mur_h1,13); \ - _mur_h1 = _mur_h1*5+0xe6546b64; \ - } \ - _mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \ - _mur_k1=0; \ - switch((keylen) & 3) { \ - case 3: _mur_k1 ^= _mur_tail[2] << 16; \ - case 2: _mur_k1 ^= _mur_tail[1] << 8; \ - case 1: _mur_k1 ^= _mur_tail[0]; \ - _mur_k1 *= _mur_c1; \ - _mur_k1 = MUR_ROTL32(_mur_k1,15); \ - _mur_k1 *= _mur_c2; \ - _mur_h1 ^= _mur_k1; \ - } \ - _mur_h1 ^= (keylen); \ - MUR_FMIX(_mur_h1); \ - hashv = _mur_h1; \ - bkt = hashv & (num_bkts-1); \ -} while(0) -#endif /* HASH_USING_NO_STRICT_ALIASING */ - -/* key comparison function; return 0 if keys equal */ -#define HASH_KEYCMP(a,b,len) memcmp(a,b,len) - -/* iterate over items in a known bucket to find desired item */ -#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \ -do { \ - if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \ - else out=NULL; \ - while (out) { \ - if ((out)->hh.keylen == keylen_in) { \ - if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break; \ - } \ - if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \ - else out = NULL; \ - } \ -} while(0) - -/* add an item to a bucket */ -#define HASH_ADD_TO_BKT(head,addhh) \ -do { \ - head.count++; \ - (addhh)->hh_next = head.hh_head; \ - (addhh)->hh_prev = NULL; \ - if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \ - (head).hh_head=addhh; \ - if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \ - && (addhh)->tbl->noexpand != 1) { \ - HASH_EXPAND_BUCKETS((addhh)->tbl); \ - } \ -} while(0) - -/* remove an item from a given bucket */ -#define HASH_DEL_IN_BKT(hh,head,hh_del) \ - (head).count--; \ - if ((head).hh_head == hh_del) { \ - (head).hh_head = hh_del->hh_next; \ - } \ - if (hh_del->hh_prev) { \ - hh_del->hh_prev->hh_next = hh_del->hh_next; \ - } \ - if (hh_del->hh_next) { \ - hh_del->hh_next->hh_prev = hh_del->hh_prev; \ - } - -/* Bucket expansion has the effect of doubling the number of buckets - * and redistributing the items into the new buckets. Ideally the - * items will distribute more or less evenly into the new buckets - * (the extent to which this is true is a measure of the quality of - * the hash function as it applies to the key domain). - * - * With the items distributed into more buckets, the chain length - * (item count) in each bucket is reduced. Thus by expanding buckets - * the hash keeps a bound on the chain length. This bounded chain - * length is the essence of how a hash provides constant time lookup. - * - * The calculation of tbl->ideal_chain_maxlen below deserves some - * explanation. First, keep in mind that we're calculating the ideal - * maximum chain length based on the *new* (doubled) bucket count. - * In fractions this is just n/b (n=number of items,b=new num buckets). - * Since the ideal chain length is an integer, we want to calculate - * ceil(n/b). We don't depend on floating point arithmetic in this - * hash, so to calculate ceil(n/b) with integers we could write - * - * ceil(n/b) = (n/b) + ((n%b)?1:0) - * - * and in fact a previous version of this hash did just that. - * But now we have improved things a bit by recognizing that b is - * always a power of two. We keep its base 2 log handy (call it lb), - * so now we can write this with a bit shift and logical AND: - * - * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) - * - */ -#define HASH_EXPAND_BUCKETS(tbl) \ -do { \ - unsigned _he_bkt; \ - unsigned _he_bkt_i; \ - struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ - UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ - _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ - 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ - memset(_he_new_buckets, 0, \ - 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - tbl->ideal_chain_maxlen = \ - (tbl->num_items >> (tbl->log2_num_buckets+1)) + \ - ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \ - tbl->nonideal_items = 0; \ - for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ - { \ - _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ - while (_he_thh) { \ - _he_hh_nxt = _he_thh->hh_next; \ - HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \ - _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ - if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ - tbl->nonideal_items++; \ - _he_newbkt->expand_mult = _he_newbkt->count / \ - tbl->ideal_chain_maxlen; \ - } \ - _he_thh->hh_prev = NULL; \ - _he_thh->hh_next = _he_newbkt->hh_head; \ - if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \ - _he_thh; \ - _he_newbkt->hh_head = _he_thh; \ - _he_thh = _he_hh_nxt; \ - } \ - } \ - uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ - tbl->num_buckets *= 2; \ - tbl->log2_num_buckets++; \ - tbl->buckets = _he_new_buckets; \ - tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ - (tbl->ineff_expands+1) : 0; \ - if (tbl->ineff_expands > 1) { \ - tbl->noexpand=1; \ - uthash_noexpand_fyi(tbl); \ - } \ - uthash_expand_fyi(tbl); \ -} while(0) - - -/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ -/* Note that HASH_SORT assumes the hash handle name to be hh. - * HASH_SRT was added to allow the hash handle name to be passed in. */ -#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) -#define HASH_SRT(hh,head,cmpfcn) \ -do { \ - unsigned _hs_i; \ - unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ - struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ - if (head) { \ - _hs_insize = 1; \ - _hs_looping = 1; \ - _hs_list = &((head)->hh); \ - while (_hs_looping) { \ - _hs_p = _hs_list; \ - _hs_list = NULL; \ - _hs_tail = NULL; \ - _hs_nmerges = 0; \ - while (_hs_p) { \ - _hs_nmerges++; \ - _hs_q = _hs_p; \ - _hs_psize = 0; \ - for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ - _hs_psize++; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - if (! (_hs_q) ) break; \ - } \ - _hs_qsize = _hs_insize; \ - while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \ - if (_hs_psize == 0) { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \ - _hs_e = _hs_p; \ - if (_hs_p){ \ - _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - } \ - _hs_psize--; \ - } else if (( \ - cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ - DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ - ) <= 0) { \ - _hs_e = _hs_p; \ - if (_hs_p){ \ - _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - } \ - _hs_psize--; \ - } else { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } \ - if ( _hs_tail ) { \ - _hs_tail->next = ((_hs_e) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ - } else { \ - _hs_list = _hs_e; \ - } \ - if (_hs_e) { \ - _hs_e->prev = ((_hs_tail) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ - } \ - _hs_tail = _hs_e; \ - } \ - _hs_p = _hs_q; \ - } \ - if (_hs_tail){ \ - _hs_tail->next = NULL; \ - } \ - if ( _hs_nmerges <= 1 ) { \ - _hs_looping=0; \ - (head)->hh.tbl->tail = _hs_tail; \ - DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ - } \ - _hs_insize *= 2; \ - } \ - HASH_FSCK(hh,head); \ - } \ -} while (0) - -/* This function selects items from one hash into another hash. - * The end result is that the selected items have dual presence - * in both hashes. There is no copy of the items made; rather - * they are added into the new hash through a secondary hash - * hash handle that must be present in the structure. */ -#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ -do { \ - unsigned _src_bkt, _dst_bkt; \ - void *_last_elt=NULL, *_elt; \ - UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ - ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ - if (src) { \ - for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ - for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ - _src_hh; \ - _src_hh = _src_hh->hh_next) { \ - _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ - if (cond(_elt)) { \ - _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ - _dst_hh->key = _src_hh->key; \ - _dst_hh->keylen = _src_hh->keylen; \ - _dst_hh->hashv = _src_hh->hashv; \ - _dst_hh->prev = _last_elt; \ - _dst_hh->next = NULL; \ - if (_last_elt_hh) { _last_elt_hh->next = _elt; } \ - if (!dst) { \ - DECLTYPE_ASSIGN(dst,_elt); \ - HASH_MAKE_TABLE(hh_dst,dst); \ - } else { \ - _dst_hh->tbl = (dst)->hh_dst.tbl; \ - } \ - HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ - HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ - (dst)->hh_dst.tbl->num_items++; \ - _last_elt = _elt; \ - _last_elt_hh = _dst_hh; \ - } \ - } \ - } \ - } \ - HASH_FSCK(hh_dst,dst); \ -} while (0) - -#define HASH_CLEAR(hh,head) \ -do { \ - if (head) { \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head)=NULL; \ - } \ -} while(0) - -#define HASH_OVERHEAD(hh,head) \ - (size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ - ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ - (sizeof(UT_hash_table)) + \ - (HASH_BLOOM_BYTELEN))) - -#ifdef NO_DECLTYPE -#define HASH_ITER(hh,head,el,tmp) \ -for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \ - el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) -#else -#define HASH_ITER(hh,head,el,tmp) \ -for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \ - el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL)) -#endif - -/* obtain a count of items in the hash */ -#define HASH_COUNT(head) HASH_CNT(hh,head) -#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0) - -typedef struct UT_hash_bucket { - struct UT_hash_handle *hh_head; - unsigned count; - - /* expand_mult is normally set to 0. In this situation, the max chain length - * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If - * the bucket's chain exceeds this length, bucket expansion is triggered). - * However, setting expand_mult to a non-zero value delays bucket expansion - * (that would be triggered by additions to this particular bucket) - * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. - * (The multiplier is simply expand_mult+1). The whole idea of this - * multiplier is to reduce bucket expansions, since they are expensive, in - * situations where we know that a particular bucket tends to be overused. - * It is better to let its chain length grow to a longer yet-still-bounded - * value, than to do an O(n) bucket expansion too often. - */ - unsigned expand_mult; - -} UT_hash_bucket; - -/* random signature used only to find hash tables in external analysis */ -#define HASH_SIGNATURE 0xa0111fe1 -#define HASH_BLOOM_SIGNATURE 0xb12220f2 - -typedef struct UT_hash_table { - UT_hash_bucket *buckets; - unsigned num_buckets, log2_num_buckets; - unsigned num_items; - struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ - ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ - - /* in an ideal situation (all buckets used equally), no bucket would have - * more than ceil(#items/#buckets) items. that's the ideal chain length. */ - unsigned ideal_chain_maxlen; - - /* nonideal_items is the number of items in the hash whose chain position - * exceeds the ideal chain maxlen. these items pay the penalty for an uneven - * hash distribution; reaching them in a chain traversal takes >ideal steps */ - unsigned nonideal_items; - - /* ineffective expands occur when a bucket doubling was performed, but - * afterward, more than half the items in the hash had nonideal chain - * positions. If this happens on two consecutive expansions we inhibit any - * further expansion, as it's not helping; this happens when the hash - * function isn't a good fit for the key domain. When expansion is inhibited - * the hash will still work, albeit no longer in constant time. */ - unsigned ineff_expands, noexpand; - - uint32_t signature; /* used only to find hash tables in external analysis */ -#ifdef HASH_BLOOM - uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ - uint8_t *bloom_bv; - char bloom_nbits; -#endif - -} UT_hash_table; - -typedef struct UT_hash_handle { - struct UT_hash_table *tbl; - void *prev; /* prev element in app order */ - void *next; /* next element in app order */ - struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ - struct UT_hash_handle *hh_next; /* next hh in bucket order */ - void *key; /* ptr to enclosing struct's key */ - unsigned keylen; /* enclosing struct's key len */ - unsigned hashv; /* result of hash-fcn(key) */ -} UT_hash_handle; - -#endif /* UTHASH_H */ -- cgit v1.2.3 From c04e1e7aef06ce0836984b17e48a1d09bb83ce04 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 10 Sep 2014 18:38:56 +0200 Subject: Fix misc bugs --- src/references.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/references.c b/src/references.c index ff64b00..84cb773 100644 --- a/src/references.c +++ b/src/references.c @@ -13,6 +13,14 @@ refhash(const unsigned char *link_ref) return hash; } +static void reference_free(reference *ref) +{ + free(ref->label); + free(ref->url); + free(ref->title); + free(ref); +} + // normalize reference: collapse internal whitespace to single space, // remove leading/trailing whitespace, case fold static unsigned char *normalize_reference(chunk *ref) @@ -28,7 +36,18 @@ static unsigned char *normalize_reference(chunk *ref) static void add_reference(reference_map *map, reference* ref) { - ref->next = map->table[ref->hash % REFMAP_SIZE]; + 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(ref); + return; + } + + t = t->next; + } + map->table[ref->hash % REFMAP_SIZE] = ref; } @@ -63,7 +82,7 @@ reference* reference_lookup(reference_map *map, chunk *label) ref = map->table[hash % REFMAP_SIZE]; while (ref) { - if (ref->label[0] == norm[0] && + if (ref->hash == hash && !strcmp((char *)ref->label, (char *)norm)) break; ref = ref->next; @@ -73,14 +92,6 @@ reference* reference_lookup(reference_map *map, chunk *label) return ref; } -static void reference_free(reference *ref) -{ - free(ref->label); - free(ref->url); - free(ref->title); - free(ref); -} - void reference_map_free(reference_map *map) { unsigned int i; @@ -96,7 +107,6 @@ void reference_map_free(reference_map *map) } } - free(map->table); free(map); } -- cgit v1.2.3 From c47e3a34adac00a262f72c6d17a1c87deefa33c4 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 10 Sep 2014 19:39:03 +0200 Subject: Fix infinite loop when case folding invalid UTF8 chars --- src/utf8.c | 24 ++++++++++++------------ src/utf8.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/utf8.c b/src/utf8.c index c65aec6..1b0224b 100644 --- a/src/utf8.c +++ b/src/utf8.c @@ -29,9 +29,9 @@ static void encode_unknown(strbuf *buf) strbuf_put(buf, repl, 3); } -ssize_t utf8proc_charlen(const uint8_t *str, ssize_t str_len) +int utf8proc_charlen(const uint8_t *str, int str_len) { - ssize_t length, i; + int length, i; if (!str_len) return 0; @@ -42,11 +42,11 @@ ssize_t utf8proc_charlen(const uint8_t *str, ssize_t str_len) return -1; if (str_len >= 0 && length > str_len) - return -1; + return -str_len; for (i = 1; i < length; i++) { if ((str[i] & 0xC0) != 0x80) - return -1; + return -i; } return length; @@ -77,7 +77,7 @@ void utf8proc_detab(strbuf *ob, const uint8_t *line, size_t size) i += 1; tab += numspaces; } else { - ssize_t charlen = utf8proc_charlen(line + i, size - i); + int charlen = utf8proc_charlen(line + i, size - i); if (charlen < 0) { encode_unknown(ob); @@ -92,9 +92,9 @@ void utf8proc_detab(strbuf *ob, const uint8_t *line, size_t size) } } -ssize_t utf8proc_iterate(const uint8_t *str, ssize_t str_len, int32_t *dst) +int utf8proc_iterate(const uint8_t *str, int str_len, int32_t *dst) { - ssize_t length; + int length; int32_t uc = -1; *dst = -1; @@ -177,15 +177,15 @@ void utf8proc_case_fold(strbuf *dest, const uint8_t *str, int len) utf8proc_encode_char(x, dest) while (len > 0) { - ssize_t char_len = utf8proc_iterate(str, len, &c); + int char_len = utf8proc_iterate(str, len, &c); - if (char_len < 0) { + if (char_len >= 0) { +#include "case_fold_switch.inc" + } else { encode_unknown(dest); - continue; + char_len = -char_len; } -#include "case_fold_switch.inc" - str += char_len; len -= char_len; } diff --git a/src/utf8.h b/src/utf8.h index 9506b75..c971250 100644 --- a/src/utf8.h +++ b/src/utf8.h @@ -6,8 +6,8 @@ void utf8proc_case_fold(strbuf *dest, const uint8_t *str, int len); void utf8proc_encode_char(int32_t uc, strbuf *buf); -ssize_t utf8proc_iterate(const uint8_t *str, ssize_t str_len, int32_t *dst); -ssize_t utf8proc_charlen(const uint8_t *str, ssize_t str_len); +int utf8proc_iterate(const uint8_t *str, int str_len, int32_t *dst); +int utf8proc_charlen(const uint8_t *str, int str_len); void utf8proc_detab(strbuf *dest, const uint8_t *line, size_t size); #endif -- cgit v1.2.3 From 79e7a4bbf7055e33b346564db769f03e85f98988 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 10 Sep 2014 19:40:40 +0200 Subject: Improve invalid UTF8 codepoint skipping --- src/utf8.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/utf8.c b/src/utf8.c index 1b0224b..6b34831 100644 --- a/src/utf8.c +++ b/src/utf8.c @@ -79,14 +79,14 @@ void utf8proc_detab(strbuf *ob, const uint8_t *line, size_t size) } else { int charlen = utf8proc_charlen(line + i, size - i); - if (charlen < 0) { - encode_unknown(ob); - i++; - } else { + if (charlen >= 0) { strbuf_put(ob, line + i, charlen); - i += charlen; + } else { + encode_unknown(ob); + charlen = -charlen; } + i += charlen; tab += 1; } } -- cgit v1.2.3 From 7c2a062cdf9c0514cdf32f4f8bd07cf52d183c8b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 10 Sep 2014 19:46:34 +0200 Subject: Do not use strchr for span searches Strchr will return a valid pointer for '\0' when searching a static string, as the NULL byte is part of the string. --- src/inlines.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/inlines.c b/src/inlines.c index 3040f09..cd2d124 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -767,10 +767,13 @@ node_inl *parse_chunk_inlines(chunk *chunk, reference_map *refmap) static int subject_find_special_char(subject *subj) { + static const char CHARS[] = "\n\\`&_*[]pos + 1; while (n < subj->input.len) { - if (strchr("\n\\`&_*[]input.data[n])) + if (memchr(CHARS, subj->input.data[n], CHARS_SIZE)) return n; n++; } -- cgit v1.2.3 From 8c028e1a88c2d2aac4a4086202568bee43678aa8 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 10 Sep 2014 19:50:29 +0200 Subject: Do not create references with empty names --- src/buffer.c | 7 ++++--- src/references.c | 31 ++++++++++++++++++++++++++----- src/references.h | 2 +- 3 files changed, 31 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/buffer.c b/src/buffer.c index cdf8ca0..7c2b86b 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -215,11 +215,12 @@ unsigned char *strbuf_detach(strbuf *buf) { unsigned char *data = buf->ptr; - if (buf->asize == 0 || buf->ptr == strbuf__oom) - return NULL; + if (buf->asize == 0 || buf->ptr == strbuf__oom) { + /* return an empty string */ + return calloc(1, 1); + } strbuf_init(buf, 0); - return data; } diff --git a/src/references.c b/src/references.c index 84cb773..300bbcc 100644 --- a/src/references.c +++ b/src/references.c @@ -23,15 +23,29 @@ static void reference_free(reference *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(chunk *ref) { strbuf normalized = GH_BUF_INIT; + unsigned char *result; + + if (ref->len == 0) + return NULL; utf8proc_case_fold(&normalized, ref->data, ref->len); strbuf_trim(&normalized); strbuf_normalize_whitespace(&normalized); - return strbuf_detach(&normalized); + result = strbuf_detach(&normalized); + assert(result); + + if (result[0] == '\0') { + free(result); + return NULL; + } + + return result; } static void add_reference(reference_map *map, reference* ref) @@ -51,19 +65,23 @@ static void add_reference(reference_map *map, reference* ref) map->table[ref->hash % REFMAP_SIZE] = ref; } -extern reference *reference_create(reference_map *map, chunk *label, chunk *url, chunk *title) +extern void reference_create(reference_map *map, chunk *label, chunk *url, chunk *title) { reference *ref; + unsigned char *reflabel = normalize_reference(label); + + /* empty reference name, or composed from only whitespace */ + if (reflabel == NULL) + return; + ref = malloc(sizeof(reference)); - ref->label = normalize_reference(label); + ref->label = reflabel; ref->hash = refhash(ref->label); ref->url = clean_url(url); ref->title = clean_title(title); ref->next = NULL; add_reference(map, ref); - - return ref; } // Returns reference if refmap contains a reference with matching @@ -78,6 +96,9 @@ reference* reference_lookup(reference_map *map, chunk *label) return NULL; norm = normalize_reference(label); + if (norm == NULL) + return NULL; + hash = refhash(norm); ref = map->table[hash % REFMAP_SIZE]; diff --git a/src/references.h b/src/references.h index 78fffe7..28937f1 100644 --- a/src/references.h +++ b/src/references.h @@ -22,6 +22,6 @@ typedef struct reference_map reference_map; reference_map *reference_map_new(void); void reference_map_free(reference_map *map); reference* reference_lookup(reference_map *map, chunk *label); -extern reference *reference_create(reference_map *map, chunk *label, chunk *url, chunk *title); +extern void reference_create(reference_map *map, chunk *label, chunk *url, chunk *title); #endif -- cgit v1.2.3 From 0ae7f4f53720e867c92ac9465062285293568856 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Wed, 10 Sep 2014 20:02:01 +0200 Subject: Handle overflows in the codepoint parser --- src/html/houdini_html_u.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/html/houdini_html_u.c b/src/html/houdini_html_u.c index b8e2d8d..49b4956 100644 --- a/src/html/houdini_html_u.c +++ b/src/html/houdini_html_u.c @@ -15,13 +15,25 @@ houdini_unescape_ent(strbuf *ob, const uint8_t *src, size_t size) int codepoint = 0; if (_isdigit(src[1])) { - for (i = 1; i < size && _isdigit(src[i]); ++i) - codepoint = (codepoint * 10) + (src[i] - '0'); + for (i = 1; i < size && _isdigit(src[i]); ++i) { + int cp = (codepoint * 10) + (src[i] - '0'); + + if (cp < codepoint) + return 0; + + codepoint = cp; + } } else if (src[1] == 'x' || src[1] == 'X') { - for (i = 2; i < size && _isxdigit(src[i]); ++i) - codepoint = (codepoint * 16) + ((src[i] | 32) % 39 - 9); + for (i = 2; i < size && _isxdigit(src[i]); ++i) { + int cp = (codepoint * 16) + ((src[i] | 32) % 39 - 9); + + if (cp < codepoint) + return 0; + + codepoint = cp; + } } if (i < size && src[i] == ';' && codepoint) { -- cgit v1.2.3 From 118e3d3c39242225baa876319cdbfbb1adadc77b Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Mon, 15 Sep 2014 15:28:49 +0200 Subject: Cleanup external APIs --- src/blocks.c | 11 ++-- src/html/html.c | 163 ++++++++++++++++++++++++++++--------------------------- src/inlines.c | 1 + src/main.c | 8 +-- src/print.c | 114 +++++++++++++++++++------------------- src/references.c | 1 + src/stmd.h | 26 ++------- 7 files changed, 159 insertions(+), 165 deletions(-) (limited to 'src') diff --git a/src/blocks.c b/src/blocks.c index 30a8284..2ac7032 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -6,8 +6,9 @@ #include "stmd.h" #include "utf8.h" -#include "html/houdini.h" #include "scanners.h" +#include "inlines.h" +#include "html/houdini.h" #define peek_at(i, n) (i)->data[n] @@ -224,7 +225,7 @@ static void finalize(node_block* b, int line_number) } // Add a node_block as child of another. Return pointer to child. -extern node_block* add_child(node_block* parent, +static node_block* add_child(node_block* parent, int block_type, int start_line, int start_column) { assert(parent); @@ -252,7 +253,7 @@ extern node_block* add_child(node_block* parent, } // Free a node_block list and any children. -extern void free_blocks(node_block* e) +void stmd_free_nodes(node_block *e) { node_block * next; while (e != NULL) { @@ -264,7 +265,7 @@ extern void free_blocks(node_block* e) } else if (e->tag == BLOCK_DOCUMENT) { reference_map_free(e->as.document.refmap); } - free_blocks(e->children); + stmd_free_nodes(e->children); free(e); e = next; } @@ -279,8 +280,6 @@ void process_inlines(node_block* cur, reference_map *refmap) case BLOCK_ATX_HEADER: case BLOCK_SETEXT_HEADER: cur->inline_content = parse_inlines(&cur->string_content, refmap); - // MEM - // strbuf_free(&cur->string_content); break; default: diff --git a/src/html/html.c b/src/html/html.c index b48b10b..6f3bc76 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -32,8 +32,89 @@ static inline void cr(strbuf *html) strbuf_putc(html, '\n'); } +// Convert an inline list to HTML. Returns 0 on success, and sets result. +static void inlines_to_html(strbuf *html, node_inl* ils) +{ + strbuf scrap = GH_BUF_INIT; + + while(ils != NULL) { + switch(ils->tag) { + case INL_STRING: + escape_html(html, ils->content.literal.data, ils->content.literal.len); + break; + + case INL_LINEBREAK: + strbuf_puts(html, "
    \n"); + break; + + case INL_SOFTBREAK: + strbuf_putc(html, '\n'); + break; + + case INL_CODE: + strbuf_puts(html, ""); + escape_html(html, ils->content.literal.data, ils->content.literal.len); + strbuf_puts(html, ""); + break; + + case INL_RAW_HTML: + strbuf_put(html, + ils->content.literal.data, + ils->content.literal.len); + break; + + case INL_LINK: + strbuf_puts(html, "content.linkable.url) + escape_href(html, ils->content.linkable.url, -1); + + if (ils->content.linkable.title) { + strbuf_puts(html, "\" title=\""); + escape_html(html, ils->content.linkable.title, -1); + } + + strbuf_puts(html, "\">"); + inlines_to_html(html, ils->content.inlines); + strbuf_puts(html, ""); + break; + + case INL_IMAGE: + strbuf_puts(html, "content.linkable.url) + escape_href(html, ils->content.linkable.url, -1); + + inlines_to_html(&scrap, ils->content.inlines); + strbuf_puts(html, "\" alt=\""); + if (scrap.size) + escape_html(html, scrap.ptr, scrap.size); + strbuf_clear(&scrap); + + if (ils->content.linkable.title) { + strbuf_puts(html, "\" title=\""); + escape_html(html, ils->content.linkable.title, -1); + } + + strbuf_puts(html, "\"/>"); + break; + + case INL_STRONG: + strbuf_puts(html, ""); + inlines_to_html(html, ils->content.inlines); + strbuf_puts(html, ""); + break; + + case INL_EMPH: + strbuf_puts(html, ""); + inlines_to_html(html, ils->content.inlines); + strbuf_puts(html, ""); + break; + } + ils = ils->next; + } +} + // Convert a node_block list to HTML. Returns 0 on success, and sets result. -void blocks_to_html(strbuf *html, node_block *b, bool tight) +static void blocks_to_html(strbuf *html, node_block *b, bool tight) { struct ListData *data; @@ -139,83 +220,7 @@ void blocks_to_html(strbuf *html, node_block *b, bool tight) } } -// Convert an inline list to HTML. Returns 0 on success, and sets result. -void inlines_to_html(strbuf *html, node_inl* ils) +void stmd_render_html(strbuf *html, node_block *root) { - strbuf scrap = GH_BUF_INIT; - - while(ils != NULL) { - switch(ils->tag) { - case INL_STRING: - escape_html(html, ils->content.literal.data, ils->content.literal.len); - break; - - case INL_LINEBREAK: - strbuf_puts(html, "
    \n"); - break; - - case INL_SOFTBREAK: - strbuf_putc(html, '\n'); - break; - - case INL_CODE: - strbuf_puts(html, ""); - escape_html(html, ils->content.literal.data, ils->content.literal.len); - strbuf_puts(html, ""); - break; - - case INL_RAW_HTML: - strbuf_put(html, - ils->content.literal.data, - ils->content.literal.len); - break; - - case INL_LINK: - strbuf_puts(html, "content.linkable.url) - escape_href(html, ils->content.linkable.url, -1); - - if (ils->content.linkable.title) { - strbuf_puts(html, "\" title=\""); - escape_html(html, ils->content.linkable.title, -1); - } - - strbuf_puts(html, "\">"); - inlines_to_html(html, ils->content.inlines); - strbuf_puts(html, ""); - break; - - case INL_IMAGE: - strbuf_puts(html, "content.linkable.url) - escape_href(html, ils->content.linkable.url, -1); - - inlines_to_html(&scrap, ils->content.inlines); - strbuf_puts(html, "\" alt=\""); - if (scrap.size) - escape_html(html, scrap.ptr, scrap.size); - strbuf_clear(&scrap); - - if (ils->content.linkable.title) { - strbuf_puts(html, "\" title=\""); - escape_html(html, ils->content.linkable.title, -1); - } - - strbuf_puts(html, "\"/>"); - break; - - case INL_STRONG: - strbuf_puts(html, ""); - inlines_to_html(html, ils->content.inlines); - strbuf_puts(html, ""); - break; - - case INL_EMPH: - strbuf_puts(html, ""); - inlines_to_html(html, ils->content.inlines); - strbuf_puts(html, ""); - break; - } - ils = ils->next; - } + blocks_to_html(html, root, false); } diff --git a/src/inlines.c b/src/inlines.c index cd2d124..145825c 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -8,6 +8,7 @@ #include "html/houdini.h" #include "utf8.h" #include "scanners.h" +#include "inlines.h" typedef struct Subject { chunk input; diff --git a/src/main.c b/src/main.c index 90bb16d..76a0e12 100644 --- a/src/main.c +++ b/src/main.c @@ -17,9 +17,9 @@ static void print_document(node_block *document, bool ast) strbuf html = GH_BUF_INIT; if (ast) { - print_blocks(document, 0); + stmd_debug_print(document); } else { - blocks_to_html(&html, document, false); + stmd_render_html(&html, document); printf("%s", html.ptr); strbuf_free(&html); } @@ -54,7 +54,7 @@ int main(int argc, char *argv[]) if (numfps == 0) { document = stmd_parse_file(stdin); print_document(document, ast); - free_blocks(document); + stmd_free_nodes(document); } else { for (i = 0; i < numfps; i++) { FILE *fp = fopen(argv[files[i]], "r"); @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) document = stmd_parse_file(fp); print_document(document, ast); - free_blocks(document); + stmd_free_nodes(document); fclose(fp); } } diff --git a/src/print.c b/src/print.c index 36140a8..83f8daa 100644 --- a/src/print.c +++ b/src/print.c @@ -32,14 +32,69 @@ static void print_str(const unsigned char *s, int len) putchar('"'); } +// Prettyprint an inline list, for debugging. +static void print_inlines(node_inl* ils, int indent) +{ + while(ils != NULL) { + for (int i=0; i < indent; i++) { + putchar(' '); + } + switch(ils->tag) { + case INL_STRING: + printf("str "); + print_str(ils->content.literal.data, ils->content.literal.len); + putchar('\n'); + break; + case INL_LINEBREAK: + printf("linebreak\n"); + break; + case INL_SOFTBREAK: + printf("softbreak\n"); + break; + case INL_CODE: + printf("code "); + print_str(ils->content.literal.data, ils->content.literal.len); + putchar('\n'); + break; + case INL_RAW_HTML: + printf("html "); + print_str(ils->content.literal.data, ils->content.literal.len); + putchar('\n'); + break; + case INL_LINK: + case INL_IMAGE: + printf("%s url=", ils->tag == INL_LINK ? "link" : "image"); + + if (ils->content.linkable.url) + print_str(ils->content.linkable.url, -1); + + if (ils->content.linkable.title) { + printf(" title="); + print_str(ils->content.linkable.title, -1); + } + putchar('\n'); + print_inlines(ils->content.linkable.label, indent + 2); + break; + case INL_STRONG: + printf("strong\n"); + print_inlines(ils->content.linkable.label, indent + 2); + break; + case INL_EMPH: + printf("emph\n"); + print_inlines(ils->content.linkable.label, indent + 2); + break; + } + ils = ils->next; + } +} + // Functions to pretty-print inline and node_block lists, for debugging. // Prettyprint an inline list, for debugging. -extern void print_blocks(node_block* b, int indent) +static void print_blocks(node_block* b, int indent) { struct ListData *data; while(b != NULL) { - // printf("%3d %3d %3d| ", b->start_line, b->start_column, b->end_line); for (int i=0; i < indent; i++) { putchar(' '); } @@ -115,58 +170,7 @@ extern void print_blocks(node_block* b, int indent) } } -// Prettyprint an inline list, for debugging. -extern void print_inlines(node_inl* ils, int indent) +void stmd_debug_print(node_block *root) { - while(ils != NULL) { - for (int i=0; i < indent; i++) { - putchar(' '); - } - switch(ils->tag) { - case INL_STRING: - printf("str "); - print_str(ils->content.literal.data, ils->content.literal.len); - putchar('\n'); - break; - case INL_LINEBREAK: - printf("linebreak\n"); - break; - case INL_SOFTBREAK: - printf("softbreak\n"); - break; - case INL_CODE: - printf("code "); - print_str(ils->content.literal.data, ils->content.literal.len); - putchar('\n'); - break; - case INL_RAW_HTML: - printf("html "); - print_str(ils->content.literal.data, ils->content.literal.len); - putchar('\n'); - break; - case INL_LINK: - case INL_IMAGE: - printf("%s url=", ils->tag == INL_LINK ? "link" : "image"); - - if (ils->content.linkable.url) - print_str(ils->content.linkable.url, -1); - - if (ils->content.linkable.title) { - printf(" title="); - print_str(ils->content.linkable.title, -1); - } - putchar('\n'); - print_inlines(ils->content.linkable.label, indent + 2); - break; - case INL_STRONG: - printf("strong\n"); - print_inlines(ils->content.linkable.label, indent + 2); - break; - case INL_EMPH: - printf("emph\n"); - print_inlines(ils->content.linkable.label, indent + 2); - break; - } - ils = ils->next; - } + print_blocks(root, 0); } diff --git a/src/references.c b/src/references.c index 300bbcc..3e54b48 100644 --- a/src/references.c +++ b/src/references.c @@ -1,6 +1,7 @@ #include "stmd.h" #include "utf8.h" #include "references.h" +#include "inlines.h" static unsigned int refhash(const unsigned char *link_ref) diff --git a/src/stmd.h b/src/stmd.h index 4e21e6c..c6473a6 100644 --- a/src/stmd.h +++ b/src/stmd.h @@ -104,28 +104,12 @@ struct node_block { typedef struct node_block node_block; -node_inl* parse_inlines(strbuf *input, reference_map *refmap); -void free_inlines(node_inl* e); +node_block *stmd_parse_document(const unsigned char *buffer, size_t len); +node_block *stmd_parse_file(FILE *f); -int parse_reference_inline(strbuf *input, reference_map *refmap); -void unescape_buffer(strbuf *buf); +void stmd_free_nodes(node_block *e); -extern node_block* make_document(); -extern node_block* add_child(node_block* parent, - int block_type, int start_line, int start_column); -void free_blocks(node_block* e); - -extern node_block *stmd_parse_document(const unsigned char *buffer, size_t len); -extern node_block *stmd_parse_file(FILE *f); - -void print_inlines(node_inl* ils, int indent); -void print_blocks(node_block* blk, int indent); - -void blocks_to_html(strbuf *html, node_block *b, bool tight); -void inlines_to_html(strbuf *html, node_inl *b); - -unsigned char *clean_url(chunk *url); -unsigned char *clean_autolink(chunk *url, int is_email); -unsigned char *clean_title(chunk *title); +void stmd_debug_print(node_block *root); +void stmd_render_html(strbuf *html, node_block *root); #endif -- cgit v1.2.3 From 3aa56049d4b52b55a2313e51698090ee81e10036 Mon Sep 17 00:00:00 2001 From: Jordan Milne Date: Fri, 12 Sep 2014 04:42:30 -0300 Subject: Better handle trailing backslashes in ATX-style headers Previously something like '# `\' would hang the parser while it waited for an extra character that wasn't there. --- src/blocks.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/blocks.c b/src/blocks.c index 2ac7032..5b38116 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -420,17 +420,17 @@ extern node_block *stmd_parse_document(const unsigned char *buffer, size_t len) static void chop_trailing_hashtags(chunk *ch) { - int n; + int n, orig_n; chunk_rtrim(ch); - n = ch->len - 1; + orig_n = n = ch->len - 1; // if string ends in #s, remove these: while (n >= 0 && peek_at(ch, n) == '#') n--; // the last # was escaped, so we include it. - if (n >= 0 && peek_at(ch, n) == '\\') + if (n != orig_n && n >= 0 && peek_at(ch, n) == '\\') n++; ch->len = n + 1; -- cgit v1.2.3 From f22e1f2536cc70e1f989e457079f1bad252c887a Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Thu, 18 Sep 2014 00:23:23 +0200 Subject: Add missing header --- src/inlines.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/inlines.h (limited to 'src') diff --git a/src/inlines.h b/src/inlines.h new file mode 100644 index 0000000..8c6e2cb --- /dev/null +++ b/src/inlines.h @@ -0,0 +1,13 @@ +#ifndef _INLINES_H_ +#define _INLINES_H_ + +unsigned char *clean_url(chunk *url); +unsigned char *clean_autolink(chunk *url, int is_email); +unsigned char *clean_title(chunk *title); + +node_inl* parse_inlines(strbuf *input, reference_map *refmap); +void free_inlines(node_inl* e); + +int parse_reference_inline(strbuf *input, reference_map *refmap); + +#endif -- cgit v1.2.3 From 2943b3850c5cb9e4561c3d109b4513a123bf4db7 Mon Sep 17 00:00:00 2001 From: Jordan Milne Date: Thu, 18 Sep 2014 17:21:12 -0300 Subject: Use a lookup table for subject_find_special_char --- src/inlines.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/inlines.c b/src/inlines.c index 145825c..71d75e9 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -768,13 +768,29 @@ node_inl *parse_chunk_inlines(chunk *chunk, reference_map *refmap) static int subject_find_special_char(subject *subj) { - static const char CHARS[] = "\n\\`&_*[]pos + 1; while (n < subj->input.len) { - if (memchr(CHARS, subj->input.data[n], CHARS_SIZE)) + if (SPECIAL_CHARS[subj->input.data[n]]) return n; n++; } -- cgit v1.2.3 From 507d8d3a09f6704e8c1f21e5a5df2e4e014e6779 Mon Sep 17 00:00:00 2001 From: Jordan Milne Date: Thu, 18 Sep 2014 09:26:05 -0300 Subject: Fix memory leak when rendering images as HTML --- src/html/html.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/html/html.c b/src/html/html.c index 6f3bc76..ab6fc35 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -111,6 +111,8 @@ static void inlines_to_html(strbuf *html, node_inl* ils) } ils = ils->next; } + + strbuf_free(&scrap); } // Convert a node_block list to HTML. Returns 0 on success, and sets result. -- cgit v1.2.3