diff --git a/.gitignore b/.gitignore index f56da3c14..784c04b6a 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,14 @@ bstrlib.txt build cmark.dSYM/* cmark +.vscode + +# Testing and benchmark +alltests.md +progit/ +bench/benchinput.md +test/afl_results/ + +# Build directories for SwiftPM and Xcode +.swiftpm +.build diff --git a/CMakeLists.txt b/CMakeLists.txt index 1107fb308..e30278cb2 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,27 @@ cmake_minimum_required(VERSION 3.0) -project(cmark VERSION 0.29.0) +project(cmark-gfm) + +set(PROJECT_VERSION_MAJOR 0) +set(PROJECT_VERSION_MINOR 29) +set(PROJECT_VERSION_PATCH 0) +set(PROJECT_VERSION_GFM 0) +set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.gfm.${PROJECT_VERSION_GFM}) include("FindAsan.cmake") +include("CheckFileOffsetBits.cmake") if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") message(FATAL_ERROR "Do not build in-source.\nPlease remove CMakeCache.txt and the CMakeFiles/ directory.\nThen: mkdir build ; cd build ; cmake .. ; make") endif() -option(CMARK_TESTS "Build cmark tests and enable testing" ON) -option(CMARK_STATIC "Build static libcmark library" ON) -option(CMARK_SHARED "Build shared libcmark library" ON) +option(CMARK_TESTS "Build cmark-gfm tests and enable testing" ON) +option(CMARK_STATIC "Build static libcmark-gfm library" ON) +option(CMARK_SHARED "Build shared libcmark-gfm library" ON) option(CMARK_LIB_FUZZER "Build libFuzzer fuzzing harness" OFF) +option(CMARK_THREADING "Add locks around static accesses via pthreads" OFF) add_subdirectory(src) +add_subdirectory(extensions) if(CMARK_TESTS AND (CMARK_SHARED OR CMARK_STATIC)) add_subdirectory(api_test) endif() diff --git a/CheckFileOffsetBits.c b/CheckFileOffsetBits.c new file mode 100644 index 000000000..d948fecf2 --- /dev/null +++ b/CheckFileOffsetBits.c @@ -0,0 +1,14 @@ +#include + +#define KB ((off_t)1024) +#define MB ((off_t)1024 * KB) +#define GB ((off_t)1024 * MB) +#define TB ((off_t)1024 * GB) +int t2[(((64 * GB -1) % 671088649) == 268434537) + && (((TB - (64 * GB -1) + 255) % 1792151290) == 305159546)? 1: -1]; + +int main() +{ + ; + return 0; +} diff --git a/CheckFileOffsetBits.cmake b/CheckFileOffsetBits.cmake new file mode 100644 index 000000000..8a74b9e11 --- /dev/null +++ b/CheckFileOffsetBits.cmake @@ -0,0 +1,43 @@ +# - Check if _FILE_OFFSET_BITS macro needed for large files +# CHECK_FILE_OFFSET_BITS () +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# Copyright (c) 2009, Michihiro NAKAJIMA +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +#INCLUDE(CheckCSourceCompiles) + +GET_FILENAME_COMPONENT(_selfdir_CheckFileOffsetBits + "${CMAKE_CURRENT_LIST_FILE}" PATH) + +MACRO (CHECK_FILE_OFFSET_BITS) + IF(NOT DEFINED _FILE_OFFSET_BITS) + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files") + TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64 + ${CMAKE_CURRENT_BINARY_DIR} + ${_selfdir_CheckFileOffsetBits}/CheckFileOffsetBits.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}) + IF(NOT __WITHOUT_FILE_OFFSET_BITS_64) + TRY_COMPILE(__WITH_FILE_OFFSET_BITS_64 + ${CMAKE_CURRENT_BINARY_DIR} + ${_selfdir_CheckFileOffsetBits}/CheckFileOffsetBits.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=64) + ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64) + + IF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + SET(_FILE_OFFSET_BITS 64 CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files") + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - needed") + ELSE(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + SET(_FILE_OFFSET_BITS "" CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files") + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - not needed") + ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + ENDIF(NOT DEFINED _FILE_OFFSET_BITS) + +ENDMACRO (CHECK_FILE_OFFSET_BITS) diff --git a/Makefile b/Makefile index 84c2e2f35..a05ba97a6 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,12 @@ SRCDIR=src +EXTDIR=extensions DATADIR=data BUILDDIR?=build GENERATOR?=Unix Makefiles MINGW_BUILDDIR?=build-mingw MINGW_INSTALLDIR?=windows SPEC=test/spec.txt +EXTENSIONS_SPEC=test/extensions.txt SITE=_site SPECVERSION=$(shell perl -ne 'print $$1 if /^version: *([0-9.]+)/' $(SPEC)) FUZZCHARS?=2000000 # for fuzztest @@ -12,20 +14,20 @@ BENCHDIR=bench BENCHSAMPLES=$(wildcard $(BENCHDIR)/samples/*.md) BENCHFILE=$(BENCHDIR)/benchinput.md ALLTESTS=alltests.md -NUMRUNS?=10 -CMARK=$(BUILDDIR)/src/cmark +NUMRUNS?=20 +CMARK=$(BUILDDIR)/src/cmark-gfm CMARK_FUZZ=$(BUILDDIR)/src/cmark-fuzz PROG?=$(CMARK) VERSION?=$(SPECVERSION) RELEASE?=CommonMark-$(VERSION) INSTALL_PREFIX?=/usr/local CLANG_CHECK?=clang-check -CLANG_FORMAT=clang-format -style llvm -sort-includes=0 -i +CLANG_FORMAT=clang-format-3.5 -style llvm -sort-includes=0 -i AFL_PATH?=/usr/local/bin -.PHONY: all cmake_build leakcheck clean fuzztest test debug ubsan asan mingw archive newbench bench format update-spec afl clang-check libFuzzer +.PHONY: all cmake_build leakcheck clean fuzztest test debug ubsan asan mingw archive newbench bench format update-spec afl clang-check docker libFuzzer -all: cmake_build man/man3/cmark.3 +all: cmake_build man/man3/cmark-gfm.3 $(CMARK): cmake_build @@ -79,8 +81,9 @@ afl: -i test/afl_test_cases \ -o test/afl_results \ -x test/fuzzing_dictionary \ + $(AFL_OPTIONS) \ -t 100 \ - $(CMARK) $(CMARK_OPTS) + $(CMARK) -e table -e strikethrough -e autolink -e tagfilter $(CMARK_OPTS) libFuzzer: @[ -n "$(LIB_FUZZER_PATH)" ] || { echo '$$LIB_FUZZER_PATH not set'; false; } @@ -98,7 +101,7 @@ mingw: cmake .. -DCMAKE_TOOLCHAIN_FILE=../toolchain-mingw32.cmake -DCMAKE_INSTALL_PREFIX=$(MINGW_INSTALLDIR) ;\ $(MAKE) && $(MAKE) install -man/man3/cmark.3: src/cmark.h | $(CMARK) +man/man3/cmark-gfm.3: src/cmark-gfm.h | $(CMARK) python man/make_man_page.py $< > $@ \ archive: @@ -126,6 +129,19 @@ $(SRCDIR)/scanners.c: $(SRCDIR)/scanners.re --encoding-policy substitute -o $@ $< $(CLANG_FORMAT) $@ +# We include scanners.c in the repository, so this shouldn't +# normally need to be generated. +$(EXTDIR)/ext_scanners.c: $(EXTDIR)/ext_scanners.re + @case "$$(re2c -v)" in \ + *\ 0.13.*|*\ 0.14|*\ 0.14.1) \ + echo "re2c >= 0.14.2 is required"; \ + false; \ + ;; \ + esac + re2c --case-insensitive -b -i --no-generation-date -8 \ + --encoding-policy substitute -o $@ $< + clang-format-3.5 -style llvm -i $@ + # We include entities.inc in the repository, so normally this # doesn't need to be regenerated: $(SRCDIR)/entities.inc: tools/make_entities_inc.py @@ -138,14 +154,19 @@ update-spec: test: $(SPEC) cmake_build $(MAKE) -C $(BUILDDIR) test || (cat $(BUILDDIR)/Testing/Temporary/LastTest.log && exit 1) -$(ALLTESTS): $(SPEC) - python3 test/spec_tests.py --spec $< --dump-tests | python3 -c 'import json; import sys; tests = json.loads(sys.stdin.read()); print("\n".join([test["markdown"] for test in tests]))' > $@ +$(ALLTESTS): $(SPEC) $(EXTENSIONS_SPEC) + ( \ + python3 test/spec_tests.py --spec $(SPEC) --dump-tests | \ + python3 -c 'import json; import sys; tests = json.loads(sys.stdin.read()); u8s = open(1, "w", encoding="utf-8", closefd=False); print("\n".join([test["markdown"] for test in tests]), file=u8s)'; \ + python3 test/spec_tests.py --spec $(EXTENSIONS_SPEC) --dump-tests | \ + python3 -c 'import json; import sys; tests = json.loads(sys.stdin.read()); u8s = open(1, "w", encoding="utf-8", closefd=False); print("\n".join([test["markdown"] for test in tests]), file=u8s)'; \ + ) > $@ leakcheck: $(ALLTESTS) for format in html man xml latex commonmark; do \ for opts in "" "--smart"; do \ - echo "cmark -t $$format $$opts" ; \ - valgrind -q --leak-check=full --dsymutil=yes --error-exitcode=1 $(PROG) -t $$format $$opts $(ALLTESTS) >/dev/null || exit 1;\ + echo "cmark-gfm -t $$format -e table -e strikethrough -e autolink -e tagfilter $$opts" ; \ + valgrind -q --leak-check=full --dsymutil=yes --suppressions=suppressions --error-exitcode=1 $(PROG) -t $$format -e table -e strikethrough -e autolink -e tagfilter $$opts $(ALLTESTS) >/dev/null || exit 1;\ done; \ done; @@ -189,6 +210,9 @@ newbench: format: $(CLANG_FORMAT) src/*.c src/*.h api_test/*.c api_test/*.h +format-extensions: + clang-format-3.5 -style llvm -i extensions/*.c extensions/*.h + operf: $(CMARK) operf $< < $(BENCHFILE) > /dev/null @@ -196,3 +220,7 @@ distclean: clean -rm -rf *.dSYM -rm -f README.html -rm -rf $(BENCHFILE) $(ALLTESTS) progit + +docker: + docker build -t cmark-gfm $(CURDIR)/tools + docker run --privileged -t -i -v $(CURDIR):/src/cmark-gfm -w /src/cmark-gfm cmark-gfm /bin/bash diff --git a/Makefile.nmake b/Makefile.nmake index ecfd4f5f5..80ba4f16d 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -3,7 +3,7 @@ DATADIR=data BUILDDIR=build INSTALLDIR=windows SPEC=test/spec.txt -PROG=$(BUILDDIR)\src\cmark.exe +PROG=$(BUILDDIR)\src\cmark-gfm.exe GENERATOR=NMake Makefiles all: $(BUILDDIR)/CMakeFiles @@ -16,6 +16,8 @@ $(BUILDDIR)/CMakeFiles: -G "$(GENERATOR)" \ -D CMAKE_BUILD_TYPE=$(BUILD_TYPE) \ -D CMAKE_INSTALL_PREFIX=$(INSTALLDIR) \ + -D CMARK_STATIC=ON \ + -D CMARK_SHARED=OFF \ .. && \ cd .. diff --git a/Package.swift b/Package.swift new file mode 100644 index 000000000..cb0474d09 --- /dev/null +++ b/Package.swift @@ -0,0 +1,66 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "cmark-gfm", + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "cmark-gfm", + targets: ["cmark-gfm"]), + .library( + name: "cmark-gfm-extensions", + targets: ["cmark-gfm-extensions"]), + .executable( + name: "cmark-gfm-bin", + targets: ["cmark-gfm-bin"]), + .executable(name: "api_test", + targets: ["api_test"]) + ], + targets: [ + .target(name: "cmark-gfm", + path: "src", + exclude: [ + "scanners.re", + "libcmark-gfm.pc.in", + "config.h.in", + "CMakeLists.txt", + "cmark-gfm_version.h.in", + "case_fold_switch.inc", + "entities.inc", + ] + ), + .target(name: "cmark-gfm-extensions", + dependencies: [ + "cmark-gfm", + ], + path: "extensions", + exclude: [ + "CMakeLists.txt", + "ext_scanners.re", + ] + ), + .target(name: "cmark-gfm-bin", + dependencies: [ + "cmark-gfm", + "cmark-gfm-extensions", + ], + path: "bin", + sources: [ + "main.c", + ] + ), + .target(name: "api_test", + dependencies: [ + "cmark-gfm", + "cmark-gfm-extensions", + ], + path: "api_test", + exclude: [ + "CMakeLists.txt", + ] + ) + ] +) diff --git a/README.md b/README.md index 5f31cccc1..374b10586 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,25 @@ -cmark -===== +cmark-gfm +========= -[![Build Status]](https://travis-ci.org/commonmark/cmark) -[![Windows Build Status]](https://ci.appveyor.com/project/jgm/cmark-0ub06) +`cmark-gfm` is an extended version of the C reference implementation of +[CommonMark], a rationalized version of Markdown syntax with a spec. This +repository adds GitHub Flavored Markdown extensions to +[the upstream implementation], as defined in [the spec]. -`cmark` is the C reference implementation of [CommonMark], a -rationalized version of Markdown syntax with a [spec][the spec]. -(For the JavaScript reference implementation, see -[commonmark.js].) +Changes upstream in `cmark` will be pulled into this `cmark-gfm` project repository +as the upstream project evolves. The original `cmark` repository can be found here: +. + +The rest of the README is preserved as-is from the upstream source. Note that +the library and binaries produced by this fork are suffixed with `-gfm` in +order to distinguish them from the upstream. + +## License + +The original `cmark` code is released under a BSD2 license. This same license +applies to the Swift code included in this `cmark-gfm` repository. + +--- It provides a shared library (`libcmark`) with functions for parsing CommonMark documents to an abstract syntax tree (AST), manipulating @@ -59,8 +71,10 @@ There are also libraries that wrap `libcmark` for [Lua](https://github.com/jgm/cmark-lua), [Perl](https://metacpan.org/release/CommonMark), [Python](https://pypi.python.org/pypi/paka.cmark), -[R](https://cran.r-project.org/package=commonmark) and -[Scala](https://github.com/sparsetech/cmark-scala). +[R](https://cran.r-project.org/package=commonmark), +[Tcl](https://github.com/apnadkarni/tcl-cmark), +[Scala](https://github.com/sparsetech/cmark-scala) and +[Node.js](https://github.com/killa123/node-cmark). Installing ---------- @@ -187,12 +201,13 @@ Nick Wellnhofer contributed many improvements, including most of the C library's API and its test harness. [benchmarks]: benchmarks.md -[the spec]: http://spec.commonmark.org +[the spec]: https://github.github.com/gfm/ +[the upstream implementation]: https://github.com/jgm/cmark [CommonMark]: http://commonmark.org [cmake]: http://www.cmake.org/download/ [re2c]: http://re2c.org [commonmark.js]: https://github.com/commonmark/commonmark.js -[Build Status]: https://img.shields.io/travis/commonmark/cmark/master.svg?style=flat -[Windows Build Status]: https://ci.appveyor.com/api/projects/status/h3fd91vtd1xfmp69?svg=true +[Build Status]: https://img.shields.io/travis/github/cmark-gfm/master.svg?style=flat +[Windows Build Status]: https://ci.appveyor.com/api/projects/status/wv7ifhqhv5itm3d5?svg=true [american fuzzy lop]: http://lcamtuf.coredump.cx/afl/ [libFuzzer]: http://llvm.org/docs/LibFuzzer.html diff --git a/api_test/CMakeLists.txt b/api_test/CMakeLists.txt index 2701abbcd..2ae27d762 100644 --- a/api_test/CMakeLists.txt +++ b/api_test/CMakeLists.txt @@ -5,13 +5,15 @@ add_executable(api_test main.c ) include_directories( - ${PROJECT_SOURCE_DIR}/src - ${PROJECT_BINARY_DIR}/src + ${PROJECT_SOURCE_DIR}/src/include + ${PROJECT_BINARY_DIR}/src/include + ${PROJECT_SOURCE_DIR}/extensions/include + ${PROJECT_BINARY_DIR}/extensions/include ) if(CMARK_SHARED) - target_link_libraries(api_test libcmark) + target_link_libraries(api_test libcmark-gfm-extensions libcmark-gfm) else() - target_link_libraries(api_test libcmark_static) + target_link_libraries(api_test libcmark-gfm-extensions_static libcmark-gfm_static) endif() # Compiler flags diff --git a/api_test/cplusplus.cpp b/api_test/cplusplus.cpp index 5e8f722a3..e06a4e766 100644 --- a/api_test/cplusplus.cpp +++ b/api_test/cplusplus.cpp @@ -1,6 +1,6 @@ #include -#include "cmark.h" +#include #include "cplusplus.h" #include "harness.h" diff --git a/api_test/harness.c b/api_test/harness.c index f6fd0bc96..6b7336f97 100644 --- a/api_test/harness.c +++ b/api_test/harness.c @@ -1,3 +1,4 @@ +#define _DEFAULT_SOURCE #include #include #include @@ -50,6 +51,21 @@ void INT_EQ(test_batch_runner *runner, int got, int expected, const char *msg, } } +#ifndef _WIN32 +#include + +static char *write_tmp(char const *header, char const *data) { + char *name = strdup("/tmp/fileXXXXXX"); + int fd = mkstemp(name); + FILE *f = fdopen(fd, "w+"); + fputs(header, f); + fwrite(data, 1, strlen(data), f); + fclose(f); + return name; +} + +#endif + void STR_EQ(test_batch_runner *runner, const char *got, const char *expected, const char *msg, ...) { int cond = strcmp(got, expected) == 0; @@ -60,8 +76,20 @@ void STR_EQ(test_batch_runner *runner, const char *got, const char *expected, va_end(ap); if (!cond) { +#ifndef _WIN32 + char *got_fn = write_tmp("actual\n", got); + char *expected_fn = write_tmp("expected\n", expected); + char buf[1024]; + snprintf(buf, sizeof(buf), "git diff --no-index %s %s", expected_fn, got_fn); + system(buf); + remove(got_fn); + remove(expected_fn); + free(got_fn); + free(expected_fn); +#else fprintf(stderr, " Got: \"%s\"\n", got); fprintf(stderr, " Expected: \"%s\"\n", expected); +#endif } } diff --git a/api_test/main.c b/api_test/main.c index 83afbff0c..9897c2d85 100644 --- a/api_test/main.c +++ b/api_test/main.c @@ -3,8 +3,9 @@ #include #define CMARK_NO_SHORT_NAMES -#include "cmark.h" +#include #include "node.h" +#include #include "harness.h" #include "cplusplus.h" @@ -24,7 +25,7 @@ static void test_md_to_html(test_batch_runner *runner, const char *markdown, const char *expected_html, const char *msg); static void test_content(test_batch_runner *runner, cmark_node_type type, - int allowed_content); + unsigned int *allowed_content); static void test_char(test_batch_runner *runner, int valid, const char *utf8, const char *msg); @@ -35,8 +36,8 @@ static void test_incomplete_char(test_batch_runner *runner, const char *utf8, static void test_continuation_byte(test_batch_runner *runner, const char *utf8); static void version(test_batch_runner *runner) { - INT_EQ(runner, cmark_version(), CMARK_VERSION, "cmark_version"); - STR_EQ(runner, cmark_version_string(), CMARK_VERSION_STRING, + INT_EQ(runner, cmark_version(), CMARK_GFM_VERSION, "cmark_version"); + STR_EQ(runner, cmark_version_string(), CMARK_GFM_VERSION_STRING, "cmark_version_string"); } @@ -177,8 +178,7 @@ static void accessors(test_batch_runner *runner) { OK(runner, cmark_node_set_literal(string, literal + sizeof("prefix")), "set_literal suffix"); - char *rendered_html = cmark_render_html(doc, - CMARK_OPT_DEFAULT | CMARK_OPT_UNSAFE); + char *rendered_html = cmark_render_html(doc, CMARK_OPT_DEFAULT | CMARK_OPT_UNSAFE, NULL); static const char expected_html[] = "

Header

\n" "
    \n" @@ -300,7 +300,7 @@ static void iterator_delete(test_batch_runner *runner) { } } - char *html = cmark_render_html(doc, CMARK_OPT_DEFAULT); + char *html = cmark_render_html(doc, CMARK_OPT_DEFAULT, NULL); static const char expected[] = "

    a c

    \n" "

    a c

    \n"; STR_EQ(runner, html, expected, "iterate and delete nodes"); @@ -340,7 +340,7 @@ static void create_tree(test_batch_runner *runner) { OK(runner, cmark_node_append_child(emph, str2), "append3"); INT_EQ(runner, cmark_node_check(doc, NULL), 0, "append3 consistent"); - html = cmark_render_html(doc, CMARK_OPT_DEFAULT); + html = cmark_render_html(doc, CMARK_OPT_DEFAULT, NULL); STR_EQ(runner, html, "

    Hello, world!

    \n", "render_html"); free(html); @@ -376,7 +376,7 @@ static void create_tree(test_batch_runner *runner) { cmark_node_unlink(emph); - html = cmark_render_html(doc, CMARK_OPT_DEFAULT); + html = cmark_render_html(doc, CMARK_OPT_DEFAULT, NULL); STR_EQ(runner, html, "

    brzz!

    \n", "render_html after shuffling"); free(html); @@ -408,7 +408,7 @@ static void custom_nodes(test_batch_runner *runner) { STR_EQ(runner, cmark_node_get_on_exit(cb), "", "get_on_exit (empty)"); cmark_node_append_child(doc, cb); - html = cmark_render_html(doc, CMARK_OPT_DEFAULT); + html = cmark_render_html(doc, CMARK_OPT_DEFAULT, NULL); STR_EQ(runner, html, "

    \n CMARK_NODE_LAST_INLINE - ? CMARK_NODE_LAST_BLOCK - : CMARK_NODE_LAST_INLINE; - OK(runner, max_node_type < 32, "all node types < 32"); - - int list_item_flag = 1 << CMARK_NODE_ITEM; - int top_level_blocks = - (1 << CMARK_NODE_BLOCK_QUOTE) | (1 << CMARK_NODE_LIST) | - (1 << CMARK_NODE_CODE_BLOCK) | (1 << CMARK_NODE_HTML_BLOCK) | - (1 << CMARK_NODE_PARAGRAPH) | (1 << CMARK_NODE_HEADING) | - (1 << CMARK_NODE_THEMATIC_BREAK); - int all_inlines = (1 << CMARK_NODE_TEXT) | (1 << CMARK_NODE_SOFTBREAK) | - (1 << CMARK_NODE_LINEBREAK) | (1 << CMARK_NODE_CODE) | - (1 << CMARK_NODE_HTML_INLINE) | (1 << CMARK_NODE_EMPH) | - (1 << CMARK_NODE_STRONG) | (1 << CMARK_NODE_LINK) | - (1 << CMARK_NODE_IMAGE); + unsigned int list_item_flag[] = {CMARK_NODE_ITEM, 0}; + unsigned int top_level_blocks[] = { + CMARK_NODE_BLOCK_QUOTE, CMARK_NODE_LIST, + CMARK_NODE_CODE_BLOCK, CMARK_NODE_HTML_BLOCK, + CMARK_NODE_PARAGRAPH, CMARK_NODE_HEADING, + CMARK_NODE_THEMATIC_BREAK, 0}; + unsigned int all_inlines[] = { + CMARK_NODE_TEXT, CMARK_NODE_SOFTBREAK, + CMARK_NODE_LINEBREAK, CMARK_NODE_CODE, + CMARK_NODE_HTML_INLINE, CMARK_NODE_EMPH, + CMARK_NODE_STRONG, CMARK_NODE_LINK, + CMARK_NODE_IMAGE, 0}; test_content(runner, CMARK_NODE_DOCUMENT, top_level_blocks); test_content(runner, CMARK_NODE_BLOCK_QUOTE, top_level_blocks); @@ -473,7 +469,7 @@ void hierarchy(test_batch_runner *runner) { } static void test_content(test_batch_runner *runner, cmark_node_type type, - int allowed_content) { + unsigned int *allowed_content) { cmark_node *node = cmark_node_new(type); for (int i = 0; i < num_node_types; ++i) { @@ -481,7 +477,10 @@ static void test_content(test_batch_runner *runner, cmark_node_type type, cmark_node *child = cmark_node_new(child_type); int got = cmark_node_append_child(node, child); - int expected = (allowed_content >> child_type) & 1; + int expected = 0; + if (allowed_content) + for (unsigned int *p = allowed_content; *p; ++p) + expected |= *p == (unsigned int)child_type; INT_EQ(runner, got, expected, "add %d as child of %d", child_type, type); @@ -506,17 +505,17 @@ static void render_html(test_batch_runner *runner) { cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT); cmark_node *paragraph = cmark_node_first_child(doc); - html = cmark_render_html(paragraph, CMARK_OPT_DEFAULT); + html = cmark_render_html(paragraph, CMARK_OPT_DEFAULT, NULL); STR_EQ(runner, html, "

    foo bar

    \n", "render single paragraph"); free(html); cmark_node *string = cmark_node_first_child(paragraph); - html = cmark_render_html(string, CMARK_OPT_DEFAULT); + html = cmark_render_html(string, CMARK_OPT_DEFAULT, NULL); STR_EQ(runner, html, "foo ", "render single inline"); free(html); cmark_node *emph = cmark_node_next(string); - html = cmark_render_html(emph, CMARK_OPT_DEFAULT); + html = cmark_render_html(emph, CMARK_OPT_DEFAULT, NULL); STR_EQ(runner, html, "bar", "render inline with children"); free(html); @@ -697,6 +696,50 @@ static void render_commonmark(test_batch_runner *runner) { cmark_node_free(doc); } +static void render_plaintext(test_batch_runner *runner) { + char *plaintext; + + static const char markdown[] = "> \\- foo *bar* \\*bar\\*\n" + "\n" + "- Lorem ipsum dolor sit amet,\n" + " consectetur adipiscing elit,\n" + "- sed do eiusmod tempor incididunt\n" + " ut labore et dolore magna aliqua.\n"; + cmark_node *doc = + cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT); + + plaintext = cmark_render_plaintext(doc, CMARK_OPT_DEFAULT, 26); + STR_EQ(runner, plaintext, "- foo bar *bar*\n" + "\n" + " - Lorem ipsum dolor sit\n" + " amet, consectetur\n" + " adipiscing elit,\n" + " - sed do eiusmod tempor\n" + " incididunt ut labore\n" + " et dolore magna\n" + " aliqua.\n", + "render document with wrapping"); + free(plaintext); + plaintext = cmark_render_plaintext(doc, CMARK_OPT_DEFAULT, 0); + STR_EQ(runner, plaintext, "- foo bar *bar*\n" + "\n" + " - Lorem ipsum dolor sit amet,\n" + " consectetur adipiscing elit,\n" + " - sed do eiusmod tempor incididunt\n" + " ut labore et dolore magna aliqua.\n", + "render document without wrapping"); + free(plaintext); + + cmark_node *text = cmark_node_new(CMARK_NODE_TEXT); + cmark_node_set_literal(text, "Hi"); + plaintext = cmark_render_plaintext(text, CMARK_OPT_DEFAULT, 0); + STR_EQ(runner, plaintext, "Hi\n", "render single inline node"); + free(plaintext); + + cmark_node_free(text); + cmark_node_free(doc); +} + static void utf8(test_batch_runner *runner) { // Ranges test_char(runner, 1, "\x01", "valid utf8 01"); @@ -745,6 +788,13 @@ static void utf8(test_batch_runner *runner) { STR_EQ(runner, html, "
    \xef\xbf\xbd\n
    \n", "utf8 with \\0\\n"); free(html); + + // Test byte-order marker + static const char string_with_bom[] = "\xef\xbb\xbf# Hello\n"; + html = cmark_markdown_to_html( + string_with_bom, sizeof(string_with_bom) - 1, CMARK_OPT_DEFAULT); + STR_EQ(runner, html, "

    Hello

    \n", "utf8 with BOM"); + free(html); } static void test_char(test_batch_runner *runner, int valid, const char *utf8, @@ -888,6 +938,61 @@ static void test_feed_across_line_ending(test_batch_runner *runner) { cmark_node_free(document); } +#if !defined(_WIN32) || defined(__CYGWIN__) +# include +static struct timeval _before, _after; +static int _timing; +# define START_TIMING() \ + gettimeofday(&_before, NULL) + +# define END_TIMING() \ + do { \ + gettimeofday(&_after, NULL); \ + _timing = (_after.tv_sec - _before.tv_sec) * 1000 + (_after.tv_usec - _before.tv_usec) / 1000; \ + } while (0) + +# define TIMING _timing +#else +# define START_TIMING() +# define END_TIMING() +# define TIMING 0 +#endif + +static void test_pathological_regressions(test_batch_runner *runner) { + { + // I don't care what the output is, so long as it doesn't take too long. + char path[] = "[a](b"; + char *input = (char *)calloc(1, (sizeof(path) - 1) * 50000); + for (int i = 0; i < 50000; ++i) + memcpy(input + i * (sizeof(path) - 1), path, sizeof(path) - 1); + + START_TIMING(); + char *html = cmark_markdown_to_html(input, (sizeof(path) - 1) * 50000, + CMARK_OPT_VALIDATE_UTF8); + END_TIMING(); + free(html); + free(input); + + OK(runner, TIMING < 1000, "takes less than 1000ms to run"); + } + + { + char path[] = "[a]( Sure.\n" ">\n" "> 2. Yes, okay.\n" - "> ![ok](hi \"yes\")\n"; + "> ![ok](hi \"yes\")\n" + "\n" + "\n" + "what happens if we spread a link [across multiple\n" + "lines][anchor]\n" + "\n" + "[anchor]: http://example.com\n"; cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT); char *xml = cmark_render_xml(doc, CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS); STR_EQ(runner, xml, "\n" "\n" - "\n" + "\n" " \n" " Hi \n" " \n" @@ -914,7 +1025,7 @@ static void source_pos(test_batch_runner *runner) { " .\n" " \n" " \n" - " Hello “ \n" + " Hello \xe2\x80\x9c \n" " \n" " http://www.google.com\n" " \n" @@ -947,6 +1058,16 @@ static void source_pos(test_batch_runner *runner) { " \n" " \n" " \n" + " <!-- HTML Comment -->\n" + "\n" + " \n" + " what happens if we spread a link \n" + " \n" + " across multiple\n" + " \n" + " lines\n" + " \n" + " \n" "\n", "sourcepos are as expected"); free(xml); @@ -957,13 +1078,15 @@ static void source_pos_inlines(test_batch_runner *runner) { { static const char markdown[] = "*first*\n" - "second\n"; + "second\n" + "\n" + " "; cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_DEFAULT); char *xml = cmark_render_xml(doc, CMARK_OPT_DEFAULT | CMARK_OPT_SOURCEPOS); STR_EQ(runner, xml, "\n" "\n" - "\n" + "\n" " \n" " \n" " first\n" @@ -971,6 +1094,11 @@ static void source_pos_inlines(test_batch_runner *runner) { " \n" " second\n" " \n" + " \n" + " \n" + " http://example.com\n" + " \n" + " \n" "\n", "sourcepos are as expected"); free(xml); @@ -1024,6 +1152,251 @@ static void ref_source_pos(test_batch_runner *runner) { cmark_node_free(doc); } +static void inline_only_opt(test_batch_runner *runner) { + static const char markdown[] = + "# My heading\n" + "> My block quote\n\n" + "- List item\n\n" + "[link](https://github.com)\n"; + + cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1, CMARK_OPT_INLINE_ONLY); + char *html = cmark_render_html(doc, CMARK_OPT_DEFAULT, 0); + STR_EQ(runner, html, "

    # My heading\n" + "> My block quote\n" + "\n" + "- List item\n" + "\n" + "link\n" + "

    \n", "html is as expected"); + free(html); + cmark_node_free(doc); +} + +static void check_markdown_plaintext(test_batch_runner *runner, char *markdown) { + cmark_node *doc = cmark_parse_document(markdown, strlen(markdown), CMARK_OPT_PRESERVE_WHITESPACE); + cmark_node *pg = cmark_node_first_child(doc); + INT_EQ(runner, cmark_node_get_type(pg), CMARK_NODE_PARAGRAPH, "markdown '%s' did not produce a paragraph node", markdown); + cmark_node *textNode = cmark_node_first_child(pg); + INT_EQ(runner, cmark_node_get_type(textNode), CMARK_NODE_TEXT, "markdown '%s' did not produce a text node inside the paragraph node", markdown); + const char *text = cmark_node_get_literal(textNode); + OK(runner, (text != NULL), "Text literal for '%s' was null", markdown); + if (text) { + STR_EQ(runner, text, markdown, "markdown '%s' resulted in '%s'", markdown, text); + } else { + SKIP(runner, 1); + } + cmark_node_free(doc); +} + +static void preserve_whitespace_opt(test_batch_runner *runner) { + check_markdown_plaintext(runner, " "); + check_markdown_plaintext(runner, " "); + check_markdown_plaintext(runner, "hello"); + check_markdown_plaintext(runner, "hello "); + check_markdown_plaintext(runner, " hello"); + check_markdown_plaintext(runner, " hello"); + check_markdown_plaintext(runner, "hello "); + check_markdown_plaintext(runner, "hel\nlo"); + check_markdown_plaintext(runner, "hel\n\nlo"); + check_markdown_plaintext(runner, "hel\nworld\nlo"); + check_markdown_plaintext(runner, " hel \n world \n lo "); + check_markdown_plaintext(runner, " hello \n \n world "); + check_markdown_plaintext(runner, "\n"); + check_markdown_plaintext(runner, "\n\n\n"); + check_markdown_plaintext(runner, "\nHello"); + check_markdown_plaintext(runner, "Hello\n"); + check_markdown_plaintext(runner, "\nHello\n"); +} + +static void check_markdown_attributes_node(test_batch_runner *runner, char *markdown, cmark_node_type expectedType, char *expectedAttributes) { + cmark_node *doc = cmark_parse_document(markdown, strlen(markdown), CMARK_OPT_DEFAULT); + cmark_node *pg = cmark_node_first_child(doc); + INT_EQ(runner, cmark_node_get_type(pg), CMARK_NODE_PARAGRAPH, "markdown '%s' did not produce a paragraph node", markdown); + cmark_node *attributeNode = cmark_node_first_child(pg); + cmark_node_type nodeType = cmark_node_get_type(attributeNode); + INT_EQ(runner, nodeType, expectedType, "markdown '%s' did not produce the correct node type: got %d, expecting %d", markdown, nodeType, expectedType); + const char *attributeContent = cmark_node_get_attributes(attributeNode); + if (attributeContent == NULL) { + OK(runner, expectedAttributes == NULL, "markdown '%s' produced an unexpected NULL attribute", markdown); + } else if (expectedAttributes == NULL) { + OK(runner, attributeContent == NULL, "markdown '%s' produced an unexpected NULL attribute", markdown); + } else { + STR_EQ(runner, attributeContent, expectedAttributes, "markdown '%s' did not produce the correct attributes: got %s, expecting: %s", markdown, attributeContent, expectedAttributes); + } + + cmark_node_free(doc); +} + +static void verify_custom_attributes_node(test_batch_runner *runner) { + // Should produce a TEXT node since there's no `()` to signify attributes + check_markdown_attributes_node(runner, "^[]", CMARK_NODE_TEXT, NULL); + check_markdown_attributes_node(runner, "^[](", CMARK_NODE_TEXT, NULL); + check_markdown_attributes_node(runner, "^[])", CMARK_NODE_TEXT, NULL); + check_markdown_attributes_node(runner, "^[])(", CMARK_NODE_TEXT, NULL); + // Should produce an ATTRIBUTE node with no attributes + check_markdown_attributes_node(runner, "^[]()", CMARK_NODE_ATTRIBUTE, ""); + // Should produce an ATTRIBUTE node with attributes + check_markdown_attributes_node(runner, "^[](rainbow: 'extreme')", CMARK_NODE_ATTRIBUTE, "rainbow: 'extreme'"); +} + +static cmark_node* parse_custom_attributues_footnote(test_batch_runner *runner, const char *markdown, cmark_node **retdoc) { + cmark_node *doc = cmark_parse_document(markdown, strlen(markdown), CMARK_OPT_DEFAULT); + cmark_node *pg = cmark_node_first_child(doc); + INT_EQ(runner, cmark_node_get_type(pg), CMARK_NODE_PARAGRAPH, "markdown '%s' did not produce a paragraph node", markdown); + *retdoc = doc; + return cmark_node_first_child(pg); +} + +static void verify_custom_attributes_footnote_basic(test_batch_runner *runner) { + static const char markdown[] = + "^[caffe][1]\n" + "\n" + "^[1]: rainbow: 'extreme', colors: { r: 255, g: 0, b: 0 }, corgicopter: true"; + cmark_node *doc; + cmark_node *attributeNode = parse_custom_attributues_footnote(runner, markdown, &doc); + INT_EQ(runner, cmark_node_get_type(attributeNode), CMARK_NODE_ATTRIBUTE, "markdown '%s' did not produce an attribute node", markdown); + STR_EQ(runner, cmark_node_get_attributes(attributeNode), + "rainbow: 'extreme', colors: { r: 255, g: 0, b: 0 }, corgicopter: true", + "markdown '%s' did not produce the right attribute in footnote", markdown); + + cmark_node_free(doc); +} + +static void verify_custom_attributes_footnote_multiple_footnotes(test_batch_runner *runner) { + static const char markdown[] = + "^[food][1] and ^[drinks][2]\n" + "\n" + "^[1]: rainbow: 'fun'\n" + "^[2]: magic: 42"; + cmark_node *doc; + cmark_node *attributeNode1 = parse_custom_attributues_footnote(runner, markdown, &doc); + INT_EQ(runner, cmark_node_get_type(attributeNode1), CMARK_NODE_ATTRIBUTE, "markdown '%s' did not produce an attribute node", markdown); + STR_EQ(runner, cmark_node_get_attributes(attributeNode1), "rainbow: 'fun'", "markdown '%s' did not produce the right attribute in footnote", markdown); + cmark_node *textNode = cmark_node_next(attributeNode1); // "and" + cmark_node *attributeNode2 = cmark_node_next(textNode); + INT_EQ(runner, cmark_node_get_type(attributeNode2), CMARK_NODE_ATTRIBUTE, "markdown '%s' did not produce an attribute node", markdown); + STR_EQ(runner, cmark_node_get_attributes(attributeNode2), "magic: 42", "markdown '%s' did not produce the right attribute in footnote", markdown); + + cmark_node_free(doc); +} + +static void verify_custom_attributes_footnote_reuse(test_batch_runner *runner) { + static const char markdown[] = + "^[pizza][1], ^[sandwich][2], ^[ice cream][2], and ^[salad][1]\n" + "\n" + "^[1]: has_tomato: true\n" + "^[2]: price: 12"; + cmark_node *doc; + cmark_node *pizzaNode = parse_custom_attributues_footnote(runner, markdown, &doc); + INT_EQ(runner, cmark_node_get_type(pizzaNode), CMARK_NODE_ATTRIBUTE, "markdown '%s' did not produce an attribute node", markdown); + STR_EQ(runner, cmark_node_get_attributes(pizzaNode), "has_tomato: true", "markdown '%s' did not produce the right attribute in footnote", markdown); + cmark_node *sandwichNode = cmark_node_next(cmark_node_next(pizzaNode)); + INT_EQ(runner, cmark_node_get_type(sandwichNode), CMARK_NODE_ATTRIBUTE, "markdown '%s' did not produce an attribute node", markdown); + STR_EQ(runner, cmark_node_get_attributes(sandwichNode), "price: 12", "markdown '%s' did not produce the right attribute in footnote", markdown); + cmark_node *icecreamNode = cmark_node_next(cmark_node_next(sandwichNode)); + INT_EQ(runner, cmark_node_get_type(icecreamNode), CMARK_NODE_ATTRIBUTE, "markdown '%s' did not produce an attribute node", markdown); + STR_EQ(runner, cmark_node_get_attributes(icecreamNode), "price: 12", "markdown '%s' did not produce the right attribute in footnote", markdown); + cmark_node *saladNode = cmark_node_next(cmark_node_next(icecreamNode)); + INT_EQ(runner, cmark_node_get_type(saladNode), CMARK_NODE_ATTRIBUTE, "markdown '%s' did not produce an attribute node", markdown); + STR_EQ(runner, cmark_node_get_attributes(saladNode), "has_tomato: true", "markdown '%s' did not produce the right attribute in footnote", markdown); + + cmark_node_free(doc); +} + +static void verify_custom_attributes_footnote_mixed_content(test_batch_runner *runner) { + static const char markdown[] = + "^[attribute1][1], [a link][2], ^[attribute2][3], ^[attribute3][1]\n" + "\n" + "^[1]: rainbow: 'fun'\n" + "[2]: https://www.example.com\n" + "Lorem ipsum\n" + "\n" + "^[3]: universe: 42\n"; + cmark_node *doc; + cmark_node *attributeNode1 = parse_custom_attributues_footnote(runner, markdown, &doc); + INT_EQ(runner, cmark_node_get_type(attributeNode1), CMARK_NODE_ATTRIBUTE, "markdown '%s' did not produce an attribute node", markdown); + STR_EQ(runner, cmark_node_get_attributes(attributeNode1), "rainbow: 'fun'", "markdown '%s' did not produce the right attribute in footnote", markdown); + cmark_node *linkNode = cmark_node_next(cmark_node_next(attributeNode1)); + INT_EQ(runner, cmark_node_get_type(linkNode), CMARK_NODE_LINK, "markdown '%s' did not produce an link node", markdown); + STR_EQ(runner, cmark_node_get_url(linkNode), "https://www.example.com", "markdown '%s' did not produce the right link in footnote", markdown); + cmark_node *attributeNode2 = cmark_node_next(cmark_node_next(linkNode)); + INT_EQ(runner, cmark_node_get_type(attributeNode2), CMARK_NODE_ATTRIBUTE, "markdown '%s' did not produce an attribute node", markdown); + STR_EQ(runner, cmark_node_get_attributes(attributeNode2), "universe: 42", "markdown '%s' did not produce the right attribute in footnote", markdown); + cmark_node *attributeNode3 = cmark_node_next(cmark_node_next(attributeNode2)); + INT_EQ(runner, cmark_node_get_type(attributeNode3), CMARK_NODE_ATTRIBUTE, "markdown '%s' did not produce an attribute node", markdown); + STR_EQ(runner, cmark_node_get_attributes(attributeNode3), "rainbow: 'fun'", "markdown '%s' did not produce the right attribute in footnote", markdown); + + cmark_node_free(doc); +} + +static void verify_custom_attributes_node_with_footnote(test_batch_runner *runner) { + verify_custom_attributes_footnote_basic(runner); + verify_custom_attributes_footnote_multiple_footnotes(runner); + verify_custom_attributes_footnote_reuse(runner); + verify_custom_attributes_footnote_mixed_content(runner); +} + +typedef void (*reentrant_call_func) (void); + +static cmark_node *reentrant_parse_inline_ext(cmark_syntax_extension *self, cmark_parser *parser, + cmark_node *parent, unsigned char character, + cmark_inline_parser *inline_parser) { + void *priv = cmark_syntax_extension_get_private(self); + if (priv) { + reentrant_call_func func = (reentrant_call_func)priv; + func(); + cmark_syntax_extension_set_private(self, NULL, NULL); + } + + return NULL; +} + +static void run_inner_parser() { + cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT); + cmark_parser_attach_syntax_extension(parser, cmark_find_syntax_extension("strikethrough")); + + static const char markdown[] = "this is the ~~outer~~ inner document"; + cmark_parser_feed(parser, markdown, sizeof(markdown) - 1); + + cmark_node *doc = cmark_parser_finish(parser); + cmark_node_free(doc); + cmark_parser_free(parser); +} + +static void parser_interrupt(test_batch_runner *runner) { + cmark_gfm_core_extensions_ensure_registered(); + + cmark_syntax_extension *my_ext = cmark_syntax_extension_new("interrupt"); + cmark_syntax_extension_set_private(my_ext, run_inner_parser, NULL); + cmark_syntax_extension_set_match_inline_func(my_ext, reentrant_parse_inline_ext); + + cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT); + cmark_parser_attach_syntax_extension(parser, cmark_find_syntax_extension("strikethrough")); + cmark_parser_attach_syntax_extension(parser, my_ext); + + static const char markdown[] = "this is the ~~inner~~ outer document"; + cmark_parser_feed(parser, markdown, sizeof(markdown) - 1); + + cmark_node *doc = cmark_parser_finish(parser); + char *xml = cmark_render_xml(doc, CMARK_OPT_DEFAULT); + STR_EQ(runner, xml, "\n" + "\n" + "\n" + " \n" + " this is the \n" + " \n" + " inner\n" + " \n" + " outer document\n" + " \n" + "\n", "interrupting the parser should still allow extensions"); + + free(xml); + cmark_node_free(doc); + cmark_parser_free(parser); + cmark_syntax_extension_free(cmark_get_default_mem_allocator(), my_ext); +} + int main() { int retval; test_batch_runner *runner = test_batch_runner_new(); @@ -1043,15 +1416,22 @@ int main() { render_man(runner); render_latex(runner); render_commonmark(runner); + render_plaintext(runner); utf8(runner); line_endings(runner); numeric_entities(runner); test_cplusplus(runner); test_safe(runner); test_feed_across_line_ending(runner); + test_pathological_regressions(runner); source_pos(runner); source_pos_inlines(runner); ref_source_pos(runner); + inline_only_opt(runner); + preserve_whitespace_opt(runner); + verify_custom_attributes_node(runner); + verify_custom_attributes_node_with_footnote(runner); + parser_interrupt(runner); test_print_summary(runner); retval = test_ok(runner) ? 0 : 1; diff --git a/appveyor.yml b/appveyor.yml index fa3fc8621..f88e5cc40 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,8 +14,8 @@ build_script: - 'tools\appveyor-build.bat' artifacts: - - path: build/src/cmark.exe - name: cmark.exe + - path: build/src/cmark-gfm.exe + name: cmark-gfm.exe test_script: - 'nmake test' diff --git a/bin/main.c b/bin/main.c new file mode 100644 index 000000000..2bab06284 --- /dev/null +++ b/bin/main.c @@ -0,0 +1,328 @@ +#include +#include +#include +#include +#include "cmark-gfm_config.h" +#include "cmark-gfm.h" +#include "node.h" +#include "cmark-gfm-extension_api.h" +#include "syntax_extension.h" +#include "parser.h" +#include "registry.h" + +#include + +#if defined(__OpenBSD__) +# include +# if OpenBSD >= 201605 +# define USE_PLEDGE +# include +# endif +#endif + +#if defined(__OpenBSD__) +# include +# if OpenBSD >= 201605 +# define USE_PLEDGE +# include +# endif +#endif + +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#include +#endif + +typedef enum { + FORMAT_NONE, + FORMAT_HTML, + FORMAT_XML, + FORMAT_MAN, + FORMAT_COMMONMARK, + FORMAT_PLAINTEXT, + FORMAT_LATEX +} writer_format; + +void print_usage() { + printf("Usage: cmark-gfm [FILE*]\n"); + printf("Options:\n"); + printf(" --to, -t FORMAT Specify output format (html, xml, man, " + "commonmark, plaintext, latex)\n"); + printf(" --width WIDTH Specify wrap width (default 0 = nowrap)\n"); + printf(" --sourcepos Include source position attribute\n"); + printf(" --hardbreaks Treat newlines as hard line breaks\n"); + printf(" --nobreaks Render soft line breaks as spaces\n"); + printf(" --unsafe Render raw HTML and dangerous URLs\n"); + printf(" --smart Use smart punctuation\n"); + printf(" --validate-utf8 Replace UTF-8 invalid sequences with U+FFFD\n"); + printf(" --github-pre-lang Use GitHub-style
     for code blocks\n");
    +  printf("  --extension, -e EXTENSION_NAME  Specify an extension name to use\n");
    +  printf("  --list-extensions               List available extensions and quit\n");
    +  printf("  --strikethrough-double-tilde    Only parse strikethrough (if enabled)\n");
    +  printf("                                  with two tildes\n");
    +  printf("  --table-prefer-style-attributes Use style attributes to align table cells\n"
    +         "                                  instead of align attributes.\n");
    +  printf("  --full-info-string              Include remainder of code block info\n"
    +         "                                  string in a separate attribute.\n");
    +  printf("  --help, -h       Print usage information\n");
    +  printf("  --version        Print version\n");
    +}
    +
    +static bool print_document(cmark_node *document, writer_format writer,
    +                           int options, int width, cmark_parser *parser) {
    +  char *result;
    +
    +  cmark_mem *mem = cmark_get_default_mem_allocator();
    +
    +  switch (writer) {
    +  case FORMAT_HTML:
    +    result = cmark_render_html_with_mem(document, options, parser->syntax_extensions, mem);
    +    break;
    +  case FORMAT_XML:
    +    result = cmark_render_xml_with_mem(document, options, mem);
    +    break;
    +  case FORMAT_MAN:
    +    result = cmark_render_man_with_mem(document, options, width, mem);
    +    break;
    +  case FORMAT_COMMONMARK:
    +    result = cmark_render_commonmark_with_mem(document, options, width, mem);
    +    break;
    +  case FORMAT_PLAINTEXT:
    +    result = cmark_render_plaintext_with_mem(document, options, width, mem);
    +    break;
    +  case FORMAT_LATEX:
    +    result = cmark_render_latex_with_mem(document, options, width, mem);
    +    break;
    +  default:
    +    fprintf(stderr, "Unknown format %d\n", writer);
    +    return false;
    +  }
    +  printf("%s", result);
    +  mem->free(result);
    +
    +  return true;
    +}
    +
    +static void print_extensions(void) {
    +  cmark_llist *syntax_extensions;
    +  cmark_llist *tmp;
    +
    +  printf ("Available extensions:\nfootnotes\n");
    +
    +  cmark_mem *mem = cmark_get_default_mem_allocator();
    +  syntax_extensions = cmark_list_syntax_extensions(mem);
    +  for (tmp = syntax_extensions; tmp; tmp=tmp->next) {
    +    cmark_syntax_extension *ext = (cmark_syntax_extension *) tmp->data;
    +    printf("%s\n", ext->name);
    +  }
    +
    +  cmark_llist_free(mem, syntax_extensions);
    +}
    +
    +int main(int argc, char *argv[]) {
    +  int i, numfps = 0;
    +  int *files;
    +  char buffer[4096];
    +  cmark_parser *parser = NULL;
    +  size_t bytes;
    +  cmark_node *document = NULL;
    +  int width = 0;
    +  char *unparsed;
    +  writer_format writer = FORMAT_HTML;
    +  int options = CMARK_OPT_DEFAULT;
    +  int res = 1;
    +
    +#ifdef USE_PLEDGE
    +  if (pledge("stdio rpath", NULL) != 0) {
    +    perror("pledge");
    +    return 1;
    +  }
    +#endif
    +
    +  cmark_gfm_core_extensions_ensure_registered();
    +
    +#ifdef USE_PLEDGE
    +  if (pledge("stdio rpath", NULL) != 0) {
    +    perror("pledge");
    +    return 1;
    +  }
    +#endif
    +
    +#if defined(_WIN32) && !defined(__CYGWIN__)
    +  _setmode(_fileno(stdin), _O_BINARY);
    +  _setmode(_fileno(stdout), _O_BINARY);
    +#endif
    +
    +  files = (int *)calloc(argc, sizeof(*files));
    +
    +  for (i = 1; i < argc; i++) {
    +    if (strcmp(argv[i], "--version") == 0) {
    +      printf("cmark-gfm %s", CMARK_GFM_VERSION_STRING);
    +      printf(" - CommonMark with GitHub Flavored Markdown converter\n(C) 2014-2016 John MacFarlane\n");
    +      goto success;
    +    } else if (strcmp(argv[i], "--list-extensions") == 0) {
    +      print_extensions();
    +      goto success;
    +    } else if (strcmp(argv[i], "--full-info-string") == 0) {
    +      options |= CMARK_OPT_FULL_INFO_STRING;
    +    } else if (strcmp(argv[i], "--table-prefer-style-attributes") == 0) {
    +      options |= CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES;
    +    } else if (strcmp(argv[i], "--strikethrough-double-tilde") == 0) {
    +      options |= CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE;
    +    } else if (strcmp(argv[i], "--sourcepos") == 0) {
    +      options |= CMARK_OPT_SOURCEPOS;
    +    } else if (strcmp(argv[i], "--hardbreaks") == 0) {
    +      options |= CMARK_OPT_HARDBREAKS;
    +    } else if (strcmp(argv[i], "--nobreaks") == 0) {
    +      options |= CMARK_OPT_NOBREAKS;
    +    } else if (strcmp(argv[i], "--smart") == 0) {
    +      options |= CMARK_OPT_SMART;
    +    } else if (strcmp(argv[i], "--github-pre-lang") == 0) {
    +      options |= CMARK_OPT_GITHUB_PRE_LANG;
    +    } else if (strcmp(argv[i], "--unsafe") == 0) {
    +      options |= CMARK_OPT_UNSAFE;
    +    } else if (strcmp(argv[i], "--validate-utf8") == 0) {
    +      options |= CMARK_OPT_VALIDATE_UTF8;
    +    } else if (strcmp(argv[i], "--liberal-html-tag") == 0) {
    +      options |= CMARK_OPT_LIBERAL_HTML_TAG;
    +    } else if ((strcmp(argv[i], "--help") == 0) ||
    +               (strcmp(argv[i], "-h") == 0)) {
    +      print_usage();
    +      goto success;
    +    } else if (strcmp(argv[i], "--width") == 0) {
    +      i += 1;
    +      if (i < argc) {
    +        width = (int)strtol(argv[i], &unparsed, 10);
    +        if (unparsed && strlen(unparsed) > 0) {
    +          fprintf(stderr, "failed parsing width '%s' at '%s'\n", argv[i],
    +                  unparsed);
    +          goto failure;
    +        }
    +      } else {
    +        fprintf(stderr, "--width requires an argument\n");
    +        goto failure;
    +      }
    +    } else if ((strcmp(argv[i], "-t") == 0) || (strcmp(argv[i], "--to") == 0)) {
    +      i += 1;
    +      if (i < argc) {
    +        if (strcmp(argv[i], "man") == 0) {
    +          writer = FORMAT_MAN;
    +        } else if (strcmp(argv[i], "html") == 0) {
    +          writer = FORMAT_HTML;
    +        } else if (strcmp(argv[i], "xml") == 0) {
    +          writer = FORMAT_XML;
    +        } else if (strcmp(argv[i], "commonmark") == 0) {
    +          writer = FORMAT_COMMONMARK;
    +        } else if (strcmp(argv[i], "plaintext") == 0) {
    +          writer = FORMAT_PLAINTEXT;
    +        } else if (strcmp(argv[i], "latex") == 0) {
    +          writer = FORMAT_LATEX;
    +        } else {
    +          fprintf(stderr, "Unknown format %s\n", argv[i]);
    +          goto failure;
    +        }
    +      } else {
    +        fprintf(stderr, "No argument provided for %s\n", argv[i - 1]);
    +        goto failure;
    +      }
    +    } else if ((strcmp(argv[i], "-e") == 0) || (strcmp(argv[i], "--extension") == 0)) {
    +      i += 1; // Simpler to handle extensions in a second pass, as we can directly register
    +              // them with the parser.
    +
    +      if (i < argc && strcmp(argv[i], "footnotes") == 0) {
    +        options |= CMARK_OPT_FOOTNOTES;
    +      }
    +    } else if (*argv[i] == '-') {
    +      print_usage();
    +      goto failure;
    +    } else { // treat as file argument
    +      files[numfps++] = i;
    +    }
    +  }
    +
    +#if DEBUG
    +  parser = cmark_parser_new(options);
    +#else
    +  parser = cmark_parser_new_with_mem(options, cmark_get_arena_mem_allocator());
    +#endif
    +
    +  for (i = 1; i < argc; i++) {
    +    if ((strcmp(argv[i], "-e") == 0) || (strcmp(argv[i], "--extension") == 0)) {
    +      i += 1;
    +      if (i < argc) {
    +        if (strcmp(argv[i], "footnotes") == 0) {
    +          continue;
    +        }
    +        cmark_syntax_extension *syntax_extension = cmark_find_syntax_extension(argv[i]);
    +        if (!syntax_extension) {
    +          fprintf(stderr, "Unknown extension %s\n", argv[i]);
    +          goto failure;
    +        }
    +        cmark_parser_attach_syntax_extension(parser, syntax_extension);
    +      } else {
    +        fprintf(stderr, "No argument provided for %s\n", argv[i - 1]);
    +        goto failure;
    +      }
    +    }
    +  }
    +
    +  for (i = 0; i < numfps; i++) {
    +    FILE *fp = fopen(argv[files[i]], "rb");
    +    if (fp == NULL) {
    +      fprintf(stderr, "Error opening file %s: %s\n", argv[files[i]],
    +              strerror(errno));
    +      goto failure;
    +    }
    +
    +    while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
    +      cmark_parser_feed(parser, buffer, bytes);
    +      if (bytes < sizeof(buffer)) {
    +        break;
    +      }
    +    }
    +
    +    fclose(fp);
    +  }
    +
    +  if (numfps == 0) {
    +    while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) {
    +      cmark_parser_feed(parser, buffer, bytes);
    +      if (bytes < sizeof(buffer)) {
    +        break;
    +      }
    +    }
    +  }
    +
    +#ifdef USE_PLEDGE
    +  if (pledge("stdio", NULL) != 0) {
    +    perror("pledge");
    +    return 1;
    +  }
    +#endif
    +
    +  document = cmark_parser_finish(parser);
    +
    +  if (!document || !print_document(document, writer, options, width, parser))
    +    goto failure;
    +
    +success:
    +  res = 0;
    +
    +failure:
    +
    +#if DEBUG
    +  if (parser)
    +  cmark_parser_free(parser);
    +
    +  if (document)
    +    cmark_node_free(document);
    +#else
    +  cmark_arena_reset();
    +#endif
    +
    +  cmark_release_plugins();
    +
    +  free(files);
    +
    +  return res;
    +}
    diff --git a/changelog.txt b/changelog.txt
    index be961a750..b86a41a22 100644
    --- a/changelog.txt
    +++ b/changelog.txt
    @@ -122,6 +122,61 @@
       * Update the Racket wrapper (Eli Barzilay).
       * Makefile: For afl target, don't build tests.
     
    +[0.28.3.gfm.20]
    +
    +  * Add tasklist extension implementation (Watson1978, #94).
    +
    +[0.28.3.gfm.19]
    +
    +  * Prevent out-of-bound memory access in strikethrough matcher (Xavier Décoret, #124).
    +  * Limit recursion in autolink extension (Xavier Décoret, #125).
    +  * Add plaintext rendering for footnotes (Xavier Décoret, #126).
    +
    +[0.28.3.gfm.18]
    +
    +  * Match strikethrough more strictly (#120).
    +  * Default to safe operation (#123).
    +
    +[0.28.3.gfm.17]
    +
    +  * Allow extension to provide opaque allocation function (Nicolás Ojeda
    +    Bär, #89).
    +  * Upstream optimisations and fixes.
    +  * Extensions can add custom XML attributes (#116).
    +  * Support for GFM extensions in cmark XML to CommonMark XSLT converter
    +    (Maëlle Salmon, #117).
    +
    +[0.28.3.gfm.16]
    +
    +  * Do not percent-encode tildes (~) in HTML attribute values (#110).
    +  * Fix footnote references in tables (#112).
    +
    +[0.28.3.gfm.15]
    +
    +  * Escape non-strikethrough tildes (~) in commonmark output (John MacFarlane, #106).
    +  * Cosmetic fix to table HTML output (John MacFarlane, #105).
    +  * Use two tildes for strikethrough CommonMark output (John MacFarlane, #104).
    +  * Normalised header and define names (#109).
    +
    +[0.28.3.gfm.14]
    +
    +  * Added a plaintext renderer for strikethrough nodes.
    +
    +[0.28.3.gfm.13]
    +
    +  * Footnote rendering bugfix (Michael Camilleri, #90).
    +  * Debian packaging (Joachim Nilsson, #97).
    +  * Add CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE for redcarpet compatibility.
    +  * Add CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES (FUJI Goro, #86, #87).
    +  * Fix pathological nested list parsing (Phil Turnbull, #95).
    +  * Expose more of the extension APIs (Minghao Liu, #96).
    +  * Add python example which uses extensions (Greg Stein, #102).
    +  * Add CMARK_OPT_FULL_INFO_STRING (Mike Kavouras, #103).
    +
    +[0.28.3.gfm.12]
    +
    +  * Various security and bug fixes.
    +
     [0.28.3]
     
       * Include GNUInstallDirs in src/CMakeLists.txt (Nick Wellnhofer, #240).
    @@ -145,6 +200,40 @@
       * Update README.md, replace `make astyle` with `make format`
         (Nguyễn Thái Ngọc Duy).
     
    +[0.28.0.gfm.11]
    +
    +  * Do not output empty `` in table extension.
    +
    +[0.28.0.gfm.10]
    +
    +  * Fix denial of service parsing references.
    +
    +[0.28.0.gfm.9]
    +
    +  * Fix denial of service parsing nested links (#49).
    +
    +[0.28.0.gfm.8]
    +
    +  * Fix bug where autolink would cause `:` to be skipped in emphasis
    +    processing.
    +
    +[0.28.0.gfm.7]
    +
    +  * Strikethrough characters do not disturb regular emphasis processing.
    +
    +[0.28.0.gfm.6]
    +
    +  * Fix inline sourcepos info when inlines span multiple lines, and in
    +    ATX headings.
    +
    +[0.28.0.gfm.5]
    +
    +  * Latest spec.
    +  * Fix a typo in the spec (John Gardner).
    +  * Fix quadratic behavior in reference lookups.
    +  * Add `core_extensions_ensure_registered`.
    +  * Add sourcepos information for inlines.
    +
     [0.28.0]
     
       * Update spec.
    @@ -271,6 +360,34 @@
         (Pavlo Kapyshin).
       * README: Add link to cmark-scala (Tim Nieradzik, #196)
     
    +[0.27.1.gfm.4]
    +
    +  * Fix regression with nested parentheses in link targets (#48).
    +
    +[0.27.1.gfm.3]
    +
    +  * Various undefined behavior issues fixed (#38, #39, #40).
    +  * Tag filter is case-insensitive (#43).
    +
    +[0.27.1.gfm.2]
    +
    +  * Fix a number of bugs (reading past end of buffer, undefined behavior.
    +  * Add `cmark_syntax_extension_get_private()`. (Jonathan Müller)
    +
    +[0.27.1.gfm.1]
    +
    +  * Add plaintext renderer.
    +  * Remove normalize option; we now always normalize the AST.
    +  * Add getters for table alignment.
    +  * `make install` also installs the extensions static/shared library.
    +
    +[0.27.1.gfm.0]
    +
    +  * Add extensions: tagfilter, strikethrough, table, autolink.
    +  * Add arena memory implementation.
    +  * Add CMARK_OPT_GITHUB_PRE_LANG for fenced code blocks.
    +  * Skip UTF-8 BOM on input.
    +
     [0.27.1]
     
       * Set policy for CMP0063 to avoid a warning (#162).
    diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt
    new file mode 100644
    index 000000000..4977c98c3
    --- /dev/null
    +++ b/extensions/CMakeLists.txt
    @@ -0,0 +1,130 @@
    +cmake_minimum_required(VERSION 2.8)
    +set(LIBRARY "libcmark-gfm-extensions")
    +set(STATICLIBRARY "libcmark-gfm-extensions_static")
    +set(LIBRARY_SOURCES
    +    core-extensions.c
    +    table.c
    +    strikethrough.c
    +    autolink.c
    +    tagfilter.c
    +    ext_scanners.c
    +    ext_scanners.re
    +    ext_scanners.h
    +    tasklist.c
    +   )
    +
    +include_directories(
    +  ${PROJECT_SOURCE_DIR}/src/include
    +  ${PROJECT_BINARY_DIR}/src/include
    +)
    +
    +include (GenerateExportHeader)
    +
    +include_directories(include ${CMAKE_CURRENT_BINARY_DIR})
    +
    +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE} -pg")
    +set(CMAKE_LINKER_PROFILE "${CMAKE_LINKER_FLAGS_RELEASE} -pg")
    +add_compiler_export_flags()
    +
    +if (CMARK_SHARED)
    +  add_library(${LIBRARY} SHARED ${LIBRARY_SOURCES})
    +
    +  set_target_properties(${LIBRARY} PROPERTIES
    +    OUTPUT_NAME "cmark-gfm-extensions"
    +    SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.gfm.${PROJECT_VERSION_GFM}
    +    VERSION ${PROJECT_VERSION})
    +
    +  set_property(TARGET ${LIBRARY}
    +    APPEND PROPERTY MACOSX_RPATH true)
    +
    +  # Avoid name clash between PROGRAM and LIBRARY pdb files.
    +  set_target_properties(${LIBRARY} PROPERTIES PDB_NAME cmark-gfm-extensions_dll)
    +
    +  generate_export_header(${LIBRARY}
    +    BASE_NAME cmark-gfm-extensions)
    +
    +  list(APPEND CMARK_INSTALL ${LIBRARY})
    +  target_link_libraries(${LIBRARY} libcmark-gfm)
    +
    +endif()
    +
    +if (CMARK_STATIC)
    +  add_library(${STATICLIBRARY} STATIC ${LIBRARY_SOURCES})
    +
    +  set_target_properties(${STATICLIBRARY} PROPERTIES
    +    COMPILE_FLAGS "-DCMARK_GFM_STATIC_DEFINE -DCMARK_GFM_EXTENSIONS_STATIC_DEFINE"
    +    POSITION_INDEPENDENT_CODE ON)
    +
    +  if (MSVC)
    +    set_target_properties(${STATICLIBRARY} PROPERTIES
    +      OUTPUT_NAME "cmark-gfm-extensions_static"
    +      VERSION ${PROJECT_VERSION})
    +  else()
    +    set_target_properties(${STATICLIBRARY} PROPERTIES
    +      OUTPUT_NAME "cmark-gfm-extensions"
    +      VERSION ${PROJECT_VERSION})
    +  endif(MSVC)
    +
    +  if (NOT CMARK_SHARED)
    +    generate_export_header(${STATICLIBRARY}
    +      BASE_NAME cmark-gfm-extensions)
    +  endif()
    +
    +  list(APPEND CMARK_INSTALL ${STATICLIBRARY})
    +endif()
    +
    +set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON)
    +
    +include (InstallRequiredSystemLibraries)
    +install(TARGETS ${CMARK_INSTALL}
    +  EXPORT cmark-gfm-extensions
    +  RUNTIME DESTINATION bin
    +  LIBRARY DESTINATION lib${LIB_SUFFIX}
    +  ARCHIVE DESTINATION lib${LIB_SUFFIX}
    +  )
    +
    +if (CMARK_SHARED OR CMARK_STATIC)
    +  install(FILES
    +  ${CMAKE_CURRENT_SOURCE_DIR}/include/cmark-gfm-core-extensions.h
    +  ${CMAKE_CURRENT_SOURCE_DIR}/include/cmark-gfm-extensions_export.h
    +  DESTINATION include
    +  )
    +
    +  install(EXPORT cmark-gfm-extensions DESTINATION lib${LIB_SUFFIX}/cmake-gfm-extensions)
    +endif()
    +
    +# Feature tests
    +include(CheckIncludeFile)
    +include(CheckCSourceCompiles)
    +include(CheckCSourceRuns)
    +include(CheckSymbolExists)
    +CHECK_INCLUDE_FILE(stdbool.h HAVE_STDBOOL_H)
    +CHECK_C_SOURCE_COMPILES(
    +  "int main() { __builtin_expect(0,0); return 0; }"
    +  HAVE___BUILTIN_EXPECT)
    +CHECK_C_SOURCE_COMPILES("
    +  int f(void) __attribute__ (());
    +  int main() { return 0; }
    +" HAVE___ATTRIBUTE__)
    +
    +# Always compile with warnings
    +if(MSVC)
    +  # Force to always compile with W4
    +  if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
    +    string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
    +  else()
    +    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
    +  endif()
    +  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX /wd4706 /wd4204 /wd4221 /wd4100 /D_CRT_SECURE_NO_WARNINGS")
    +elseif(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
    +  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter -std=c99 -pedantic")
    +endif()
    +
    +# Compile as C++ under MSVC older than 12.0
    +if(MSVC AND MSVC_VERSION LESS 1800)
    +  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /TP")
    +endif()
    +
    +if(CMAKE_BUILD_TYPE STREQUAL "Ubsan")
    +  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
    +endif()
    diff --git a/extensions/autolink.c b/extensions/autolink.c
    new file mode 100644
    index 000000000..41564ee4c
    --- /dev/null
    +++ b/extensions/autolink.c
    @@ -0,0 +1,425 @@
    +#include "autolink.h"
    +#include 
    +#include 
    +#include 
    +
    +#if defined(_WIN32)
    +#define strncasecmp _strnicmp
    +#else
    +#include 
    +#endif
    +
    +static int is_valid_hostchar(const uint8_t *link, size_t link_len) {
    +  int32_t ch;
    +  int r = cmark_utf8proc_iterate(link, (bufsize_t)link_len, &ch);
    +  if (r < 0)
    +    return 0;
    +  return !cmark_utf8proc_is_space(ch) && !cmark_utf8proc_is_punctuation(ch);
    +}
    +
    +static int sd_autolink_issafe(const uint8_t *link, size_t link_len) {
    +  static const size_t valid_uris_count = 3;
    +  static const char *valid_uris[] = {"http://", "https://", "ftp://"};
    +
    +  size_t i;
    +
    +  for (i = 0; i < valid_uris_count; ++i) {
    +    size_t len = strlen(valid_uris[i]);
    +
    +    if (link_len > len && strncasecmp((char *)link, valid_uris[i], len) == 0 &&
    +        is_valid_hostchar(link + len, link_len - len))
    +      return 1;
    +  }
    +
    +  return 0;
    +}
    +
    +static size_t autolink_delim(uint8_t *data, size_t link_end) {
    +  uint8_t cclose, copen;
    +  size_t i;
    +
    +  for (i = 0; i < link_end; ++i)
    +    if (data[i] == '<') {
    +      link_end = i;
    +      break;
    +    }
    +
    +  while (link_end > 0) {
    +    cclose = data[link_end - 1];
    +
    +    switch (cclose) {
    +    case ')':
    +      copen = '(';
    +      break;
    +    default:
    +      copen = 0;
    +    }
    +
    +    if (strchr("?!.,:*_~'\"", data[link_end - 1]) != NULL)
    +      link_end--;
    +
    +    else if (data[link_end - 1] == ';') {
    +      size_t new_end = link_end - 2;
    +
    +      while (new_end > 0 && cmark_isalpha(data[new_end]))
    +        new_end--;
    +
    +      if (new_end < link_end - 2 && data[new_end] == '&')
    +        link_end = new_end;
    +      else
    +        link_end--;
    +    } else if (copen != 0) {
    +      size_t closing = 0;
    +      size_t opening = 0;
    +      i = 0;
    +
    +      /* Allow any number of matching brackets (as recognised in copen/cclose)
    +       * at the end of the URL.  If there is a greater number of closing
    +       * brackets than opening ones, we remove one character from the end of
    +       * the link.
    +       *
    +       * Examples (input text => output linked portion):
    +       *
    +       *	http://www.pokemon.com/Pikachu_(Electric)
    +       *		=> http://www.pokemon.com/Pikachu_(Electric)
    +       *
    +       *	http://www.pokemon.com/Pikachu_((Electric)
    +       *		=> http://www.pokemon.com/Pikachu_((Electric)
    +       *
    +       *	http://www.pokemon.com/Pikachu_(Electric))
    +       *		=> http://www.pokemon.com/Pikachu_(Electric)
    +       *
    +       *	http://www.pokemon.com/Pikachu_((Electric))
    +       *		=> http://www.pokemon.com/Pikachu_((Electric))
    +       */
    +
    +      while (i < link_end) {
    +        if (data[i] == copen)
    +          opening++;
    +        else if (data[i] == cclose)
    +          closing++;
    +
    +        i++;
    +      }
    +
    +      if (closing <= opening)
    +        break;
    +
    +      link_end--;
    +    } else
    +      break;
    +  }
    +
    +  return link_end;
    +}
    +
    +static size_t check_domain(uint8_t *data, size_t size, int allow_short) {
    +  size_t i, np = 0, uscore1 = 0, uscore2 = 0;
    +
    +  for (i = 1; i < size - 1; i++) {
    +    if (data[i] == '_')
    +      uscore2++;
    +    else if (data[i] == '.') {
    +      uscore1 = uscore2;
    +      uscore2 = 0;
    +      np++;
    +    } else if (!is_valid_hostchar(data + i, size - i) && data[i] != '-')
    +      break;
    +  }
    +
    +  if (uscore1 > 0 || uscore2 > 0)
    +    return 0;
    +
    +  if (allow_short) {
    +    /* We don't need a valid domain in the strict sense (with
    +     * least one dot; so just make sure it's composed of valid
    +     * domain characters and return the length of the the valid
    +     * sequence. */
    +    return i;
    +  } else {
    +    /* a valid domain needs to have at least a dot.
    +     * that's as far as we get */
    +    return np ? i : 0;
    +  }
    +}
    +
    +static cmark_node *www_match(cmark_parser *parser, cmark_node *parent,
    +                             cmark_inline_parser *inline_parser) {
    +  cmark_chunk *chunk = cmark_inline_parser_get_chunk(inline_parser);
    +  size_t max_rewind = cmark_inline_parser_get_offset(inline_parser);
    +  uint8_t *data = chunk->data + max_rewind;
    +  size_t size = chunk->len - max_rewind;
    +  int start = cmark_inline_parser_get_column(inline_parser);
    +
    +  size_t link_end;
    +
    +  if (max_rewind > 0 && strchr("*_~(", data[-1]) == NULL &&
    +      !cmark_isspace(data[-1]))
    +    return 0;
    +
    +  if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
    +    return 0;
    +
    +  link_end = check_domain(data, size, 0);
    +
    +  if (link_end == 0)
    +    return NULL;
    +
    +  while (link_end < size && !cmark_isspace(data[link_end]))
    +    link_end++;
    +
    +  link_end = autolink_delim(data, link_end);
    +
    +  if (link_end == 0)
    +    return NULL;
    +
    +  cmark_inline_parser_set_offset(inline_parser, (int)(max_rewind + link_end));
    +
    +  cmark_node *node = cmark_node_new_with_mem(CMARK_NODE_LINK, parser->mem);
    +
    +  cmark_strbuf buf;
    +  cmark_strbuf_init(parser->mem, &buf, 10);
    +  cmark_strbuf_puts(&buf, "http://");
    +  cmark_strbuf_put(&buf, data, (bufsize_t)link_end);
    +  node->as.link.url = cmark_chunk_buf_detach(&buf);
    +
    +  cmark_node *text = cmark_node_new_with_mem(CMARK_NODE_TEXT, parser->mem);
    +  text->as.literal =
    +      cmark_chunk_dup(chunk, (bufsize_t)max_rewind, (bufsize_t)link_end);
    +  cmark_node_append_child(node, text);
    +
    +  node->start_line = text->start_line =
    +    node->end_line = text->end_line =
    +    cmark_inline_parser_get_line(inline_parser);
    +
    +  node->start_column = text->start_column = start - 1;
    +  node->end_column = text->end_column = cmark_inline_parser_get_column(inline_parser) - 1;
    +
    +  return node;
    +}
    +
    +static cmark_node *url_match(cmark_parser *parser, cmark_node *parent,
    +                             cmark_inline_parser *inline_parser) {
    +  size_t link_end, domain_len;
    +  int rewind = 0;
    +
    +  cmark_chunk *chunk = cmark_inline_parser_get_chunk(inline_parser);
    +  int max_rewind = cmark_inline_parser_get_offset(inline_parser);
    +  uint8_t *data = chunk->data + max_rewind;
    +  size_t size = chunk->len - max_rewind;
    +
    +  if (size < 4 || data[1] != '/' || data[2] != '/')
    +    return 0;
    +
    +  while (rewind < max_rewind && cmark_isalpha(data[-rewind - 1]))
    +    rewind++;
    +
    +  if (!sd_autolink_issafe(data - rewind, size + rewind))
    +    return 0;
    +
    +  link_end = strlen("://");
    +
    +  domain_len = check_domain(data + link_end, size - link_end, 1);
    +
    +  if (domain_len == 0)
    +    return 0;
    +
    +  link_end += domain_len;
    +  while (link_end < size && !cmark_isspace(data[link_end]))
    +    link_end++;
    +
    +  link_end = autolink_delim(data, link_end);
    +
    +  if (link_end == 0)
    +    return NULL;
    +
    +  cmark_inline_parser_set_offset(inline_parser, (int)(max_rewind + link_end));
    +  cmark_node_unput(parent, rewind);
    +
    +  cmark_node *node = cmark_node_new_with_mem(CMARK_NODE_LINK, parser->mem);
    +
    +  cmark_chunk url = cmark_chunk_dup(chunk, max_rewind - rewind,
    +                                    (bufsize_t)(link_end + rewind));
    +  node->as.link.url = url;
    +
    +  cmark_node *text = cmark_node_new_with_mem(CMARK_NODE_TEXT, parser->mem);
    +  text->as.literal = url;
    +  cmark_node_append_child(node, text);
    +
    +  return node;
    +}
    +
    +static cmark_node *match(cmark_syntax_extension *ext, cmark_parser *parser,
    +                         cmark_node *parent, unsigned char c,
    +                         cmark_inline_parser *inline_parser) {
    +  if (cmark_inline_parser_in_bracket(inline_parser, false) ||
    +      cmark_inline_parser_in_bracket(inline_parser, true))
    +    return NULL;
    +
    +  if (c == ':')
    +    return url_match(parser, parent, inline_parser);
    +
    +  if (c == 'w')
    +    return www_match(parser, parent, inline_parser);
    +
    +  return NULL;
    +
    +  // note that we could end up re-consuming something already a
    +  // part of an inline, because we don't track when the last
    +  // inline was finished in inlines.c.
    +}
    +
    +static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset, int depth) {
    +  // postprocess_text can recurse very deeply if there is a very long line of
    +  // '@' only.  Stop at a reasonable depth to ensure it cannot crash.
    +  if (depth > 1000) return;
    +
    +  size_t link_end;
    +  uint8_t *data = text->as.literal.data,
    +    *at;
    +  size_t size = text->as.literal.len;
    +  int rewind, max_rewind,
    +      nb = 0, np = 0, ns = 0;
    +
    +  if (offset < 0 || (size_t)offset >= size)
    +    return;
    +
    +  data += offset;
    +  size -= offset;
    +
    +  at = (uint8_t *)memchr(data, '@', size);
    +  if (!at)
    +    return;
    +
    +  max_rewind = (int)(at - data);
    +  data += max_rewind;
    +  size -= max_rewind;
    +
    +  for (rewind = 0; rewind < max_rewind; ++rewind) {
    +    uint8_t c = data[-rewind - 1];
    +
    +    if (cmark_isalnum(c))
    +      continue;
    +
    +    if (strchr(".+-_", c) != NULL)
    +      continue;
    +
    +    if (c == '/')
    +      ns++;
    +
    +    break;
    +  }
    +
    +  if (rewind == 0 || ns > 0) {
    +    postprocess_text(parser, text, max_rewind + 1 + offset, depth + 1);
    +    return;
    +  }
    +
    +  for (link_end = 0; link_end < size; ++link_end) {
    +    uint8_t c = data[link_end];
    +
    +    if (cmark_isalnum(c))
    +      continue;
    +
    +    if (c == '@')
    +      nb++;
    +    else if (c == '.' && link_end < size - 1 && cmark_isalnum(data[link_end + 1]))
    +      np++;
    +    else if (c != '-' && c != '_')
    +      break;
    +  }
    +
    +  if (link_end < 2 || nb != 1 || np == 0 ||
    +      (!cmark_isalpha(data[link_end - 1]) && data[link_end - 1] != '.')) {
    +    postprocess_text(parser, text, max_rewind + 1 + offset, depth + 1);
    +    return;
    +  }
    +
    +  link_end = autolink_delim(data, link_end);
    +
    +  if (link_end == 0) {
    +    postprocess_text(parser, text, max_rewind + 1 + offset, depth + 1);
    +    return;
    +  }
    +
    +  cmark_chunk_to_cstr(parser->mem, &text->as.literal);
    +
    +  cmark_node *link_node = cmark_node_new_with_mem(CMARK_NODE_LINK, parser->mem);
    +  cmark_strbuf buf;
    +  cmark_strbuf_init(parser->mem, &buf, 10);
    +  cmark_strbuf_puts(&buf, "mailto:");
    +  cmark_strbuf_put(&buf, data - rewind, (bufsize_t)(link_end + rewind));
    +  link_node->as.link.url = cmark_chunk_buf_detach(&buf);
    +
    +  cmark_node *link_text = cmark_node_new_with_mem(CMARK_NODE_TEXT, parser->mem);
    +  cmark_chunk email = cmark_chunk_dup(
    +      &text->as.literal,
    +      offset + max_rewind - rewind,
    +      (bufsize_t)(link_end + rewind));
    +  cmark_chunk_to_cstr(parser->mem, &email);
    +  link_text->as.literal = email;
    +  cmark_node_append_child(link_node, link_text);
    +
    +  cmark_node_insert_after(text, link_node);
    +
    +  cmark_node *post = cmark_node_new_with_mem(CMARK_NODE_TEXT, parser->mem);
    +  post->as.literal = cmark_chunk_dup(&text->as.literal,
    +    (bufsize_t)(offset + max_rewind + link_end),
    +    (bufsize_t)(size - link_end));
    +  cmark_chunk_to_cstr(parser->mem, &post->as.literal);
    +
    +  cmark_node_insert_after(link_node, post);
    +
    +  text->as.literal.len = offset + max_rewind - rewind;
    +  text->as.literal.data[text->as.literal.len] = 0;
    +
    +  postprocess_text(parser, post, 0, depth + 1);
    +}
    +
    +static cmark_node *postprocess(cmark_syntax_extension *ext, cmark_parser *parser, cmark_node *root) {
    +  cmark_iter *iter;
    +  cmark_event_type ev;
    +  cmark_node *node;
    +  bool in_link = false;
    +
    +  cmark_consolidate_text_nodes(root);
    +  iter = cmark_iter_new(root);
    +
    +  while ((ev = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
    +    node = cmark_iter_get_node(iter);
    +    if (in_link) {
    +      if (ev == CMARK_EVENT_EXIT && node->type == CMARK_NODE_LINK) {
    +        in_link = false;
    +      }
    +      continue;
    +    }
    +
    +    if (ev == CMARK_EVENT_ENTER && node->type == CMARK_NODE_LINK) {
    +      in_link = true;
    +      continue;
    +    }
    +
    +    if (ev == CMARK_EVENT_ENTER && node->type == CMARK_NODE_TEXT) {
    +      postprocess_text(parser, node, 0, /*depth*/0);
    +    }
    +  }
    +
    +  cmark_iter_free(iter);
    +
    +  return root;
    +}
    +
    +cmark_syntax_extension *create_autolink_extension(void) {
    +  cmark_syntax_extension *ext = cmark_syntax_extension_new("autolink");
    +  cmark_llist *special_chars = NULL;
    +
    +  cmark_syntax_extension_set_match_inline_func(ext, match);
    +  cmark_syntax_extension_set_postprocess_func(ext, postprocess);
    +
    +  cmark_mem *mem = cmark_get_default_mem_allocator();
    +  special_chars = cmark_llist_append(mem, special_chars, (void *)':');
    +  special_chars = cmark_llist_append(mem, special_chars, (void *)'w');
    +  cmark_syntax_extension_set_special_inline_chars(ext, special_chars);
    +
    +  return ext;
    +}
    diff --git a/extensions/autolink.h b/extensions/autolink.h
    new file mode 100644
    index 000000000..4e179379d
    --- /dev/null
    +++ b/extensions/autolink.h
    @@ -0,0 +1,8 @@
    +#ifndef CMARK_GFM_AUTOLINK_H
    +#define CMARK_GFM_AUTOLINK_H
    +
    +#include "cmark-gfm-core-extensions.h"
    +
    +cmark_syntax_extension *create_autolink_extension(void);
    +
    +#endif
    diff --git a/extensions/core-extensions.c b/extensions/core-extensions.c
    new file mode 100644
    index 000000000..131cdf402
    --- /dev/null
    +++ b/extensions/core-extensions.c
    @@ -0,0 +1,29 @@
    +#include "cmark-gfm-core-extensions.h"
    +#include "autolink.h"
    +#include "mutex.h"
    +#include "strikethrough.h"
    +#include "table.h"
    +#include "tagfilter.h"
    +#include "tasklist.h"
    +#include "registry.h"
    +#include "plugin.h"
    +
    +static int core_extensions_registration(cmark_plugin *plugin) {
    +  cmark_plugin_register_syntax_extension(plugin, create_table_extension());
    +  cmark_plugin_register_syntax_extension(plugin,
    +                                         create_strikethrough_extension());
    +  cmark_plugin_register_syntax_extension(plugin, create_autolink_extension());
    +  cmark_plugin_register_syntax_extension(plugin, create_tagfilter_extension());
    +  cmark_plugin_register_syntax_extension(plugin, create_tasklist_extension());
    +  return 1;
    +}
    +
    +CMARK_DEFINE_ONCE(registered);
    +
    +static void register_plugins(void) {
    +  cmark_register_plugin(core_extensions_registration);
    +}
    +
    +void cmark_gfm_core_extensions_ensure_registered(void) {
    +  CMARK_RUN_ONCE(registered, register_plugins);
    +}
    diff --git a/extensions/ext_scanners.c b/extensions/ext_scanners.c
    new file mode 100644
    index 000000000..0d3ba2881
    --- /dev/null
    +++ b/extensions/ext_scanners.c
    @@ -0,0 +1,879 @@
    +/* Generated by re2c 1.3 */
    +
    +#include "ext_scanners.h"
    +#include 
    +
    +bufsize_t _ext_scan_at(bufsize_t (*scanner)(const unsigned char *),
    +                       unsigned char *ptr, int len, bufsize_t offset) {
    +  bufsize_t res;
    +
    +  if (ptr == NULL || offset >= len) {
    +    return 0;
    +  } else {
    +    unsigned char lim = ptr[len];
    +
    +    ptr[len] = '\0';
    +    res = scanner(ptr + offset);
    +    ptr[len] = lim;
    +  }
    +
    +  return res;
    +}
    +
    +bufsize_t _scan_table_start(const unsigned char *p) {
    +  const unsigned char *marker = NULL;
    +  const unsigned char *start = p;
    +
    +  {
    +    unsigned char yych;
    +    static const unsigned char yybm[] = {
    +        0, 0,   0, 0, 0, 0, 0, 0, 0, 64, 0,  64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  64, 0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
    +        0, 128, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,
    +    };
    +    yych = *p;
    +    if (yych <= ' ') {
    +      if (yych <= '\n') {
    +        if (yych == '\t')
    +          goto yy4;
    +      } else {
    +        if (yych <= '\f')
    +          goto yy4;
    +        if (yych >= ' ')
    +          goto yy4;
    +      }
    +    } else {
    +      if (yych <= '9') {
    +        if (yych == '-')
    +          goto yy5;
    +      } else {
    +        if (yych <= ':')
    +          goto yy6;
    +        if (yych == '|')
    +          goto yy4;
    +      }
    +    }
    +    ++p;
    +  yy3 : { return 0; }
    +  yy4:
    +    yych = *(marker = ++p);
    +    if (yybm[0 + yych] & 64) {
    +      goto yy7;
    +    }
    +    if (yych == '-')
    +      goto yy10;
    +    if (yych == ':')
    +      goto yy12;
    +    goto yy3;
    +  yy5:
    +    yych = *(marker = ++p);
    +    if (yybm[0 + yych] & 128) {
    +      goto yy10;
    +    }
    +    if (yych <= ' ') {
    +      if (yych <= 0x08)
    +        goto yy3;
    +      if (yych <= '\r')
    +        goto yy14;
    +      if (yych <= 0x1F)
    +        goto yy3;
    +      goto yy14;
    +    } else {
    +      if (yych <= ':') {
    +        if (yych <= '9')
    +          goto yy3;
    +        goto yy13;
    +      } else {
    +        if (yych == '|')
    +          goto yy14;
    +        goto yy3;
    +      }
    +    }
    +  yy6:
    +    yych = *(marker = ++p);
    +    if (yybm[0 + yych] & 128) {
    +      goto yy10;
    +    }
    +    goto yy3;
    +  yy7:
    +    yych = *++p;
    +    if (yybm[0 + yych] & 64) {
    +      goto yy7;
    +    }
    +    if (yych == '-')
    +      goto yy10;
    +    if (yych == ':')
    +      goto yy12;
    +  yy9:
    +    p = marker;
    +    goto yy3;
    +  yy10:
    +    yych = *++p;
    +    if (yybm[0 + yych] & 128) {
    +      goto yy10;
    +    }
    +    if (yych <= 0x1F) {
    +      if (yych <= '\n') {
    +        if (yych <= 0x08)
    +          goto yy9;
    +        if (yych <= '\t')
    +          goto yy13;
    +        goto yy15;
    +      } else {
    +        if (yych <= '\f')
    +          goto yy13;
    +        if (yych <= '\r')
    +          goto yy17;
    +        goto yy9;
    +      }
    +    } else {
    +      if (yych <= ':') {
    +        if (yych <= ' ')
    +          goto yy13;
    +        if (yych <= '9')
    +          goto yy9;
    +        goto yy13;
    +      } else {
    +        if (yych == '|')
    +          goto yy18;
    +        goto yy9;
    +      }
    +    }
    +  yy12:
    +    yych = *++p;
    +    if (yybm[0 + yych] & 128) {
    +      goto yy10;
    +    }
    +    goto yy9;
    +  yy13:
    +    yych = *++p;
    +  yy14:
    +    if (yych <= '\r') {
    +      if (yych <= '\t') {
    +        if (yych <= 0x08)
    +          goto yy9;
    +        goto yy13;
    +      } else {
    +        if (yych <= '\n')
    +          goto yy15;
    +        if (yych <= '\f')
    +          goto yy13;
    +        goto yy17;
    +      }
    +    } else {
    +      if (yych <= ' ') {
    +        if (yych <= 0x1F)
    +          goto yy9;
    +        goto yy13;
    +      } else {
    +        if (yych == '|')
    +          goto yy18;
    +        goto yy9;
    +      }
    +    }
    +  yy15:
    +    ++p;
    +    { return (bufsize_t)(p - start); }
    +  yy17:
    +    yych = *++p;
    +    if (yych == '\n')
    +      goto yy15;
    +    goto yy9;
    +  yy18:
    +    yych = *++p;
    +    if (yybm[0 + yych] & 128) {
    +      goto yy10;
    +    }
    +    if (yych <= '\r') {
    +      if (yych <= '\t') {
    +        if (yych <= 0x08)
    +          goto yy9;
    +        goto yy18;
    +      } else {
    +        if (yych <= '\n')
    +          goto yy15;
    +        if (yych <= '\f')
    +          goto yy18;
    +        goto yy17;
    +      }
    +    } else {
    +      if (yych <= ' ') {
    +        if (yych <= 0x1F)
    +          goto yy9;
    +        goto yy18;
    +      } else {
    +        if (yych == ':')
    +          goto yy12;
    +        goto yy9;
    +      }
    +    }
    +  }
    +}
    +
    +bufsize_t _scan_table_cell(const unsigned char *p) {
    +  const unsigned char *marker = NULL;
    +  const unsigned char *start = p;
    +
    +  {
    +    unsigned char yych;
    +    unsigned int yyaccept = 0;
    +    static const unsigned char yybm[] = {
    +        64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 0,  64, 64, 0,  64, 64, 64, 64,
    +        64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    +        64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    +        64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    +        64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    +        64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
    +        64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0,  64,
    +        64, 64, 0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    +        0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    +        0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    +        0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    +        0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    +        0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    +        0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    +        0,  0,  0,   0,
    +    };
    +    yych = *p;
    +    if (yybm[0 + yych] & 64) {
    +      goto yy22;
    +    }
    +    if (yych <= 0xEC) {
    +      if (yych <= 0xC1) {
    +        if (yych <= '\r')
    +          goto yy25;
    +        if (yych <= '\\')
    +          goto yy27;
    +        goto yy25;
    +      } else {
    +        if (yych <= 0xDF)
    +          goto yy29;
    +        if (yych <= 0xE0)
    +          goto yy30;
    +        goto yy31;
    +      }
    +    } else {
    +      if (yych <= 0xF0) {
    +        if (yych <= 0xED)
    +          goto yy32;
    +        if (yych <= 0xEF)
    +          goto yy31;
    +        goto yy33;
    +      } else {
    +        if (yych <= 0xF3)
    +          goto yy34;
    +        if (yych <= 0xF4)
    +          goto yy35;
    +        goto yy25;
    +      }
    +    }
    +  yy22:
    +    yyaccept = 0;
    +    yych = *(marker = ++p);
    +    if (yybm[0 + yych] & 64) {
    +      goto yy22;
    +    }
    +    if (yych <= 0xEC) {
    +      if (yych <= 0xC1) {
    +        if (yych <= '\r')
    +          goto yy24;
    +        if (yych <= '\\')
    +          goto yy27;
    +      } else {
    +        if (yych <= 0xDF)
    +          goto yy36;
    +        if (yych <= 0xE0)
    +          goto yy38;
    +        goto yy39;
    +      }
    +    } else {
    +      if (yych <= 0xF0) {
    +        if (yych <= 0xED)
    +          goto yy40;
    +        if (yych <= 0xEF)
    +          goto yy39;
    +        goto yy41;
    +      } else {
    +        if (yych <= 0xF3)
    +          goto yy42;
    +        if (yych <= 0xF4)
    +          goto yy43;
    +      }
    +    }
    +  yy24 : { return (bufsize_t)(p - start); }
    +  yy25:
    +    ++p;
    +  yy26 : { return 0; }
    +  yy27:
    +    yyaccept = 0;
    +    yych = *(marker = ++p);
    +    if (yybm[0 + yych] & 128) {
    +      goto yy27;
    +    }
    +    if (yych <= 0xDF) {
    +      if (yych <= '\f') {
    +        if (yych == '\n')
    +          goto yy24;
    +        goto yy22;
    +      } else {
    +        if (yych <= '\r')
    +          goto yy24;
    +        if (yych <= 0x7F)
    +          goto yy22;
    +        if (yych <= 0xC1)
    +          goto yy24;
    +        goto yy36;
    +      }
    +    } else {
    +      if (yych <= 0xEF) {
    +        if (yych <= 0xE0)
    +          goto yy38;
    +        if (yych == 0xED)
    +          goto yy40;
    +        goto yy39;
    +      } else {
    +        if (yych <= 0xF0)
    +          goto yy41;
    +        if (yych <= 0xF3)
    +          goto yy42;
    +        if (yych <= 0xF4)
    +          goto yy43;
    +        goto yy24;
    +      }
    +    }
    +  yy29:
    +    yych = *++p;
    +    if (yych <= 0x7F)
    +      goto yy26;
    +    if (yych <= 0xBF)
    +      goto yy22;
    +    goto yy26;
    +  yy30:
    +    yyaccept = 1;
    +    yych = *(marker = ++p);
    +    if (yych <= 0x9F)
    +      goto yy26;
    +    if (yych <= 0xBF)
    +      goto yy36;
    +    goto yy26;
    +  yy31:
    +    yyaccept = 1;
    +    yych = *(marker = ++p);
    +    if (yych <= 0x7F)
    +      goto yy26;
    +    if (yych <= 0xBF)
    +      goto yy36;
    +    goto yy26;
    +  yy32:
    +    yyaccept = 1;
    +    yych = *(marker = ++p);
    +    if (yych <= 0x7F)
    +      goto yy26;
    +    if (yych <= 0x9F)
    +      goto yy36;
    +    goto yy26;
    +  yy33:
    +    yyaccept = 1;
    +    yych = *(marker = ++p);
    +    if (yych <= 0x8F)
    +      goto yy26;
    +    if (yych <= 0xBF)
    +      goto yy39;
    +    goto yy26;
    +  yy34:
    +    yyaccept = 1;
    +    yych = *(marker = ++p);
    +    if (yych <= 0x7F)
    +      goto yy26;
    +    if (yych <= 0xBF)
    +      goto yy39;
    +    goto yy26;
    +  yy35:
    +    yyaccept = 1;
    +    yych = *(marker = ++p);
    +    if (yych <= 0x7F)
    +      goto yy26;
    +    if (yych <= 0x8F)
    +      goto yy39;
    +    goto yy26;
    +  yy36:
    +    yych = *++p;
    +    if (yych <= 0x7F)
    +      goto yy37;
    +    if (yych <= 0xBF)
    +      goto yy22;
    +  yy37:
    +    p = marker;
    +    if (yyaccept == 0) {
    +      goto yy24;
    +    } else {
    +      goto yy26;
    +    }
    +  yy38:
    +    yych = *++p;
    +    if (yych <= 0x9F)
    +      goto yy37;
    +    if (yych <= 0xBF)
    +      goto yy36;
    +    goto yy37;
    +  yy39:
    +    yych = *++p;
    +    if (yych <= 0x7F)
    +      goto yy37;
    +    if (yych <= 0xBF)
    +      goto yy36;
    +    goto yy37;
    +  yy40:
    +    yych = *++p;
    +    if (yych <= 0x7F)
    +      goto yy37;
    +    if (yych <= 0x9F)
    +      goto yy36;
    +    goto yy37;
    +  yy41:
    +    yych = *++p;
    +    if (yych <= 0x8F)
    +      goto yy37;
    +    if (yych <= 0xBF)
    +      goto yy39;
    +    goto yy37;
    +  yy42:
    +    yych = *++p;
    +    if (yych <= 0x7F)
    +      goto yy37;
    +    if (yych <= 0xBF)
    +      goto yy39;
    +    goto yy37;
    +  yy43:
    +    yych = *++p;
    +    if (yych <= 0x7F)
    +      goto yy37;
    +    if (yych <= 0x8F)
    +      goto yy39;
    +    goto yy37;
    +  }
    +}
    +
    +bufsize_t _scan_table_cell_end(const unsigned char *p) {
    +  const unsigned char *start = p;
    +
    +  {
    +    unsigned char yych;
    +    static const unsigned char yybm[] = {
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 128, 128, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   128, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0,
    +    };
    +    yych = *p;
    +    if (yych == '|')
    +      goto yy48;
    +    ++p;
    +    { return 0; }
    +  yy48:
    +    yych = *++p;
    +    if (yybm[0 + yych] & 128) {
    +      goto yy48;
    +    }
    +    { return (bufsize_t)(p - start); }
    +  }
    +}
    +
    +bufsize_t _scan_table_row_end(const unsigned char *p) {
    +  const unsigned char *marker = NULL;
    +  const unsigned char *start = p;
    +
    +  {
    +    unsigned char yych;
    +    static const unsigned char yybm[] = {
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 128, 128, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   128, 0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0, 0, 0, 0, 0,
    +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0, 0,   0,   0, 0, 0,
    +    };
    +    yych = *p;
    +    if (yych <= '\f') {
    +      if (yych <= 0x08)
    +        goto yy53;
    +      if (yych == '\n')
    +        goto yy56;
    +      goto yy55;
    +    } else {
    +      if (yych <= '\r')
    +        goto yy58;
    +      if (yych == ' ')
    +        goto yy55;
    +    }
    +  yy53:
    +    ++p;
    +  yy54 : { return 0; }
    +  yy55:
    +    yych = *(marker = ++p);
    +    if (yych <= 0x08)
    +      goto yy54;
    +    if (yych <= '\r')
    +      goto yy60;
    +    if (yych == ' ')
    +      goto yy60;
    +    goto yy54;
    +  yy56:
    +    ++p;
    +    { return (bufsize_t)(p - start); }
    +  yy58:
    +    yych = *++p;
    +    if (yych == '\n')
    +      goto yy56;
    +    goto yy54;
    +  yy59:
    +    yych = *++p;
    +  yy60:
    +    if (yybm[0 + yych] & 128) {
    +      goto yy59;
    +    }
    +    if (yych <= 0x08)
    +      goto yy61;
    +    if (yych <= '\n')
    +      goto yy56;
    +    if (yych <= '\r')
    +      goto yy62;
    +  yy61:
    +    p = marker;
    +    goto yy54;
    +  yy62:
    +    yych = *++p;
    +    if (yych == '\n')
    +      goto yy56;
    +    goto yy61;
    +  }
    +}
    +
    +bufsize_t _scan_tasklist(const unsigned char *p) {
    +  const unsigned char *marker = NULL;
    +  const unsigned char *start = p;
    +
    +  {
    +    unsigned char yych;
    +    static const unsigned char yybm[] = {
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   64,  0, 64, 64, 0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        64,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0,  0,  0, 0, 0,
    +    };
    +    yych = *p;
    +    if (yych <= ' ') {
    +      if (yych <= '\n') {
    +        if (yych == '\t')
    +          goto yy67;
    +      } else {
    +        if (yych <= '\f')
    +          goto yy67;
    +        if (yych >= ' ')
    +          goto yy67;
    +      }
    +    } else {
    +      if (yych <= ',') {
    +        if (yych <= ')')
    +          goto yy65;
    +        if (yych <= '+')
    +          goto yy68;
    +      } else {
    +        if (yych <= '-')
    +          goto yy68;
    +        if (yych <= '/')
    +          goto yy65;
    +        if (yych <= '9')
    +          goto yy69;
    +      }
    +    }
    +  yy65:
    +    ++p;
    +  yy66 : { return 0; }
    +  yy67:
    +    yych = *(marker = ++p);
    +    if (yybm[0 + yych] & 64) {
    +      goto yy70;
    +    }
    +    if (yych <= ',') {
    +      if (yych <= ')')
    +        goto yy66;
    +      if (yych <= '+')
    +        goto yy73;
    +      goto yy66;
    +    } else {
    +      if (yych <= '-')
    +        goto yy73;
    +      if (yych <= '/')
    +        goto yy66;
    +      if (yych <= '9')
    +        goto yy74;
    +      goto yy66;
    +    }
    +  yy68:
    +    yych = *(marker = ++p);
    +    if (yych <= '\n') {
    +      if (yych == '\t')
    +        goto yy75;
    +      goto yy66;
    +    } else {
    +      if (yych <= '\f')
    +        goto yy75;
    +      if (yych == ' ')
    +        goto yy75;
    +      goto yy66;
    +    }
    +  yy69:
    +    yych = *(marker = ++p);
    +    if (yych <= 0x1F) {
    +      if (yych <= '\t') {
    +        if (yych <= 0x08)
    +          goto yy78;
    +        goto yy73;
    +      } else {
    +        if (yych <= '\n')
    +          goto yy66;
    +        if (yych <= '\f')
    +          goto yy73;
    +        goto yy78;
    +      }
    +    } else {
    +      if (yych <= 0x7F) {
    +        if (yych <= ' ')
    +          goto yy73;
    +        goto yy78;
    +      } else {
    +        if (yych <= 0xC1)
    +          goto yy66;
    +        if (yych <= 0xF4)
    +          goto yy78;
    +        goto yy66;
    +      }
    +    }
    +  yy70:
    +    yych = *++p;
    +    if (yybm[0 + yych] & 64) {
    +      goto yy70;
    +    }
    +    if (yych <= ',') {
    +      if (yych <= ')')
    +        goto yy72;
    +      if (yych <= '+')
    +        goto yy73;
    +    } else {
    +      if (yych <= '-')
    +        goto yy73;
    +      if (yych <= '/')
    +        goto yy72;
    +      if (yych <= '9')
    +        goto yy74;
    +    }
    +  yy72:
    +    p = marker;
    +    goto yy66;
    +  yy73:
    +    yych = *++p;
    +    if (yych == '[')
    +      goto yy72;
    +    goto yy76;
    +  yy74:
    +    yych = *++p;
    +    if (yych <= '\n') {
    +      if (yych == '\t')
    +        goto yy73;
    +      goto yy78;
    +    } else {
    +      if (yych <= '\f')
    +        goto yy73;
    +      if (yych == ' ')
    +        goto yy73;
    +      goto yy78;
    +    }
    +  yy75:
    +    yych = *++p;
    +  yy76:
    +    if (yych <= '\f') {
    +      if (yych == '\t')
    +        goto yy75;
    +      if (yych <= '\n')
    +        goto yy72;
    +      goto yy75;
    +    } else {
    +      if (yych <= ' ') {
    +        if (yych <= 0x1F)
    +          goto yy72;
    +        goto yy75;
    +      } else {
    +        if (yych == '[')
    +          goto yy86;
    +        goto yy72;
    +      }
    +    }
    +  yy77:
    +    yych = *++p;
    +  yy78:
    +    if (yybm[0 + yych] & 128) {
    +      goto yy77;
    +    }
    +    if (yych <= 0xC1) {
    +      if (yych <= '\f') {
    +        if (yych <= 0x08)
    +          goto yy73;
    +        if (yych == '\n')
    +          goto yy72;
    +        goto yy75;
    +      } else {
    +        if (yych == ' ')
    +          goto yy75;
    +        if (yych <= 0x7F)
    +          goto yy73;
    +        goto yy72;
    +      }
    +    } else {
    +      if (yych <= 0xED) {
    +        if (yych <= 0xDF)
    +          goto yy79;
    +        if (yych <= 0xE0)
    +          goto yy80;
    +        if (yych <= 0xEC)
    +          goto yy81;
    +        goto yy82;
    +      } else {
    +        if (yych <= 0xF0) {
    +          if (yych <= 0xEF)
    +            goto yy81;
    +          goto yy83;
    +        } else {
    +          if (yych <= 0xF3)
    +            goto yy84;
    +          if (yych <= 0xF4)
    +            goto yy85;
    +          goto yy72;
    +        }
    +      }
    +    }
    +  yy79:
    +    yych = *++p;
    +    if (yych <= 0x7F)
    +      goto yy72;
    +    if (yych <= 0xBF)
    +      goto yy73;
    +    goto yy72;
    +  yy80:
    +    yych = *++p;
    +    if (yych <= 0x9F)
    +      goto yy72;
    +    if (yych <= 0xBF)
    +      goto yy79;
    +    goto yy72;
    +  yy81:
    +    yych = *++p;
    +    if (yych <= 0x7F)
    +      goto yy72;
    +    if (yych <= 0xBF)
    +      goto yy79;
    +    goto yy72;
    +  yy82:
    +    yych = *++p;
    +    if (yych <= 0x7F)
    +      goto yy72;
    +    if (yych <= 0x9F)
    +      goto yy79;
    +    goto yy72;
    +  yy83:
    +    yych = *++p;
    +    if (yych <= 0x8F)
    +      goto yy72;
    +    if (yych <= 0xBF)
    +      goto yy81;
    +    goto yy72;
    +  yy84:
    +    yych = *++p;
    +    if (yych <= 0x7F)
    +      goto yy72;
    +    if (yych <= 0xBF)
    +      goto yy81;
    +    goto yy72;
    +  yy85:
    +    yych = *++p;
    +    if (yych <= 0x7F)
    +      goto yy72;
    +    if (yych <= 0x8F)
    +      goto yy81;
    +    goto yy72;
    +  yy86:
    +    yych = *++p;
    +    if (yych <= 'W') {
    +      if (yych != ' ')
    +        goto yy72;
    +    } else {
    +      if (yych <= 'X')
    +        goto yy87;
    +      if (yych != 'x')
    +        goto yy72;
    +    }
    +  yy87:
    +    yych = *++p;
    +    if (yych != ']')
    +      goto yy72;
    +    yych = *++p;
    +    if (yych <= '\n') {
    +      if (yych != '\t')
    +        goto yy72;
    +    } else {
    +      if (yych <= '\f')
    +        goto yy89;
    +      if (yych != ' ')
    +        goto yy72;
    +    }
    +  yy89:
    +    yych = *++p;
    +    if (yych <= '\n') {
    +      if (yych == '\t')
    +        goto yy89;
    +    } else {
    +      if (yych <= '\f')
    +        goto yy89;
    +      if (yych == ' ')
    +        goto yy89;
    +    }
    +    { return (bufsize_t)(p - start); }
    +  }
    +}
    diff --git a/extensions/ext_scanners.h b/extensions/ext_scanners.h
    new file mode 100644
    index 000000000..6dd4a725d
    --- /dev/null
    +++ b/extensions/ext_scanners.h
    @@ -0,0 +1,24 @@
    +#include "chunk.h"
    +#include "cmark-gfm.h"
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +bufsize_t _ext_scan_at(bufsize_t (*scanner)(const unsigned char *),
    +                       unsigned char *ptr, int len, bufsize_t offset);
    +bufsize_t _scan_table_start(const unsigned char *p);
    +bufsize_t _scan_table_cell(const unsigned char *p);
    +bufsize_t _scan_table_cell_end(const unsigned char *p);
    +bufsize_t _scan_table_row_end(const unsigned char *p);
    +bufsize_t _scan_tasklist(const unsigned char *p);
    +
    +#define scan_table_start(c, l, n) _ext_scan_at(&_scan_table_start, c, l, n)
    +#define scan_table_cell(c, l, n) _ext_scan_at(&_scan_table_cell, c, l, n)
    +#define scan_table_cell_end(c, l, n) _ext_scan_at(&_scan_table_cell_end, c, l, n)
    +#define scan_table_row_end(c, l, n) _ext_scan_at(&_scan_table_row_end, c, l, n)
    +#define scan_tasklist(c, l, n) _ext_scan_at(&_scan_tasklist, c, l, n)
    +
    +#ifdef __cplusplus
    +}
    +#endif
    diff --git a/extensions/ext_scanners.re b/extensions/ext_scanners.re
    new file mode 100644
    index 000000000..9144e5b48
    --- /dev/null
    +++ b/extensions/ext_scanners.re
    @@ -0,0 +1,92 @@
    +/*!re2c re2c:flags:no-debug-info = 1; */
    +/*!re2c re2c:indent:string = '  '; */
    +
    +#include 
    +#include "ext_scanners.h"
    +
    +bufsize_t _ext_scan_at(bufsize_t (*scanner)(const unsigned char *), unsigned char *ptr, int len, bufsize_t offset)
    +{
    +	bufsize_t res;
    +
    +        if (ptr == NULL || offset >= len) {
    +          return 0;
    +        } else {
    +	  unsigned char lim = ptr[len];
    +
    +	  ptr[len] = '\0';
    +	  res = scanner(ptr + offset);
    +	  ptr[len] = lim;
    +        }
    +
    +	return res;
    +}
    +
    +/*!re2c
    +  re2c:define:YYCTYPE  = "unsigned char";
    +  re2c:define:YYCURSOR = p;
    +  re2c:define:YYMARKER = marker;
    +  re2c:yyfill:enable = 0;
    +
    +  spacechar = [ \t\v\f];
    +  newline = [\r]?[\n];
    +  escaped_char = [\\][|!"#$%&'()*+,./:;<=>?@[\\\]^_`{}~-];
    +
    +  table_marker = (spacechar*[:]?[-]+[:]?spacechar*);
    +  table_cell = (escaped_char|[^|\r\n])+;
    +
    +  tasklist = spacechar*("-"|"+"|"*"|[0-9]+.)spacechar+("[ ]"|"[x]")spacechar+;
    +*/
    +
    +bufsize_t _scan_table_start(const unsigned char *p)
    +{
    +  const unsigned char *marker = NULL;
    +  const unsigned char *start = p;
    +  /*!re2c
    +    [|]? table_marker ([|] table_marker)* [|]? spacechar* newline {
    +      return (bufsize_t)(p - start);
    +    }
    +    * { return 0; }
    +  */
    +}
    +
    +bufsize_t _scan_table_cell(const unsigned char *p)
    +{
    +  const unsigned char *marker = NULL;
    +  const unsigned char *start = p;
    +  /*!re2c
    +    // In fact, `table_cell` matches non-empty table cells only. The empty
    +    // string is also a valid table cell, but is handled by the default rule.
    +    // This approach prevents re2c's match-empty-string warning.
    +    table_cell { return (bufsize_t)(p - start); }
    +    * { return 0; }
    +  */
    +}
    +
    +bufsize_t _scan_table_cell_end(const unsigned char *p)
    +{
    +  const unsigned char *start = p;
    +  /*!re2c
    +    [|] spacechar* { return (bufsize_t)(p - start); }
    +    * { return 0; }
    +  */
    +}
    +
    +bufsize_t _scan_table_row_end(const unsigned char *p)
    +{
    +  const unsigned char *marker = NULL;
    +  const unsigned char *start = p;
    +  /*!re2c
    +    spacechar* newline { return (bufsize_t)(p - start); }
    +    * { return 0; }
    +  */
    +}
    +
    +bufsize_t _scan_tasklist(const unsigned char *p)
    +{
    +  const unsigned char *marker = NULL;
    +  const unsigned char *start = p;
    +  /*!re2c
    +    tasklist { return (bufsize_t)(p - start); }
    +    * { return 0; }
    +  */
    +}
    diff --git a/extensions/include/cmark-gfm-core-extensions.h b/extensions/include/cmark-gfm-core-extensions.h
    new file mode 100644
    index 000000000..51103e616
    --- /dev/null
    +++ b/extensions/include/cmark-gfm-core-extensions.h
    @@ -0,0 +1,54 @@
    +#ifndef CMARK_GFM_CORE_EXTENSIONS_H
    +#define CMARK_GFM_CORE_EXTENSIONS_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +#include "cmark-gfm-extension_api.h"
    +#include "cmark-gfm-extensions_export.h"
    +#include "cmark-gfm_config.h" // for bool
    +#include 
    +
    +CMARK_GFM_EXTENSIONS_EXPORT
    +void cmark_gfm_core_extensions_ensure_registered(void);
    +
    +CMARK_GFM_EXTENSIONS_EXPORT
    +uint16_t cmark_gfm_extensions_get_table_columns(cmark_node *node);
    +
    +/** Sets the number of columns for the table, returning 1 on success and 0 on error.
    + */
    +CMARK_GFM_EXTENSIONS_EXPORT
    +int cmark_gfm_extensions_set_table_columns(cmark_node *node, uint16_t n_columns);
    +
    +CMARK_GFM_EXTENSIONS_EXPORT
    +uint8_t *cmark_gfm_extensions_get_table_alignments(cmark_node *node);
    +
    +/** Sets the alignments for the table, returning 1 on success and 0 on error.
    + */
    +CMARK_GFM_EXTENSIONS_EXPORT
    +int cmark_gfm_extensions_set_table_alignments(cmark_node *node, uint16_t ncols, uint8_t *alignments);
    +
    +CMARK_GFM_EXTENSIONS_EXPORT
    +int cmark_gfm_extensions_get_table_row_is_header(cmark_node *node);
    +
    +/** Sets whether the node is a table header row, returning 1 on success and 0 on error.
    + */
    +CMARK_GFM_EXTENSIONS_EXPORT
    +int cmark_gfm_extensions_set_table_row_is_header(cmark_node *node, int is_header);
    +
    +CMARK_GFM_EXTENSIONS_EXPORT
    +bool cmark_gfm_extensions_get_tasklist_item_checked(cmark_node *node);
    +/* For backwards compatibility */
    +#define cmark_gfm_extensions_tasklist_is_checked cmark_gfm_extensions_get_tasklist_item_checked
    +
    +/** Sets whether a tasklist item is "checked" (completed), returning 1 on success and 0 on error.
    + */
    +CMARK_GFM_EXTENSIONS_EXPORT
    +int cmark_gfm_extensions_set_tasklist_item_checked(cmark_node *node, bool is_checked);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif
    diff --git a/extensions/include/cmark-gfm-extensions_export.h b/extensions/include/cmark-gfm-extensions_export.h
    new file mode 100644
    index 000000000..69c0bd787
    --- /dev/null
    +++ b/extensions/include/cmark-gfm-extensions_export.h
    @@ -0,0 +1,42 @@
    +
    +#ifndef CMARK_GFM_EXTENSIONS_EXPORT_H
    +#define CMARK_GFM_EXTENSIONS_EXPORT_H
    +
    +#ifdef CMARK_GFM_EXTENSIONS_STATIC_DEFINE
    +#  define CMARK_GFM_EXTENSIONS_EXPORT
    +#  define CMARK_GFM_EXTENSIONS_NO_EXPORT
    +#else
    +#  ifndef CMARK_GFM_EXTENSIONS_EXPORT
    +#    ifdef libcmark_gfm_extensions_EXPORTS
    +        /* We are building this library */
    +#      define CMARK_GFM_EXTENSIONS_EXPORT __attribute__((visibility("default")))
    +#    else
    +        /* We are using this library */
    +#      define CMARK_GFM_EXTENSIONS_EXPORT __attribute__((visibility("default")))
    +#    endif
    +#  endif
    +
    +#  ifndef CMARK_GFM_EXTENSIONS_NO_EXPORT
    +#    define CMARK_GFM_EXTENSIONS_NO_EXPORT __attribute__((visibility("hidden")))
    +#  endif
    +#endif
    +
    +#ifndef CMARK_GFM_EXTENSIONS_DEPRECATED
    +#  define CMARK_GFM_EXTENSIONS_DEPRECATED __attribute__ ((__deprecated__))
    +#endif
    +
    +#ifndef CMARK_GFM_EXTENSIONS_DEPRECATED_EXPORT
    +#  define CMARK_GFM_EXTENSIONS_DEPRECATED_EXPORT CMARK_GFM_EXTENSIONS_EXPORT CMARK_GFM_EXTENSIONS_DEPRECATED
    +#endif
    +
    +#ifndef CMARK_GFM_EXTENSIONS_DEPRECATED_NO_EXPORT
    +#  define CMARK_GFM_EXTENSIONS_DEPRECATED_NO_EXPORT CMARK_GFM_EXTENSIONS_NO_EXPORT CMARK_GFM_EXTENSIONS_DEPRECATED
    +#endif
    +
    +#if 0 /* DEFINE_NO_DEPRECATED */
    +#  ifndef CMARK_GFM_EXTENSIONS_NO_DEPRECATED
    +#    define CMARK_GFM_EXTENSIONS_NO_DEPRECATED
    +#  endif
    +#endif
    +
    +#endif /* CMARK_GFM_EXTENSIONS_EXPORT_H */
    diff --git a/extensions/strikethrough.c b/extensions/strikethrough.c
    new file mode 100644
    index 000000000..8145d23b0
    --- /dev/null
    +++ b/extensions/strikethrough.c
    @@ -0,0 +1,167 @@
    +#include "strikethrough.h"
    +#include 
    +#include 
    +
    +cmark_node_type CMARK_NODE_STRIKETHROUGH;
    +
    +static cmark_node *match(cmark_syntax_extension *self, cmark_parser *parser,
    +                         cmark_node *parent, unsigned char character,
    +                         cmark_inline_parser *inline_parser) {
    +  cmark_node *res = NULL;
    +  int left_flanking, right_flanking, punct_before, punct_after, delims;
    +  char buffer[101];
    +
    +  if (character != '~')
    +    return NULL;
    +
    +  delims = cmark_inline_parser_scan_delimiters(
    +      inline_parser, sizeof(buffer) - 1, '~',
    +      &left_flanking,
    +      &right_flanking, &punct_before, &punct_after);
    +
    +  memset(buffer, '~', delims);
    +  buffer[delims] = 0;
    +
    +  res = cmark_node_new_with_mem(CMARK_NODE_TEXT, parser->mem);
    +  cmark_node_set_literal(res, buffer);
    +  res->start_line = res->end_line = cmark_inline_parser_get_line(inline_parser);
    +  res->start_column = cmark_inline_parser_get_column(inline_parser) - delims;
    +
    +  if ((left_flanking || right_flanking) &&
    +      (delims == 2 || (!(parser->options & CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE) && delims == 1))) {
    +    cmark_inline_parser_push_delimiter(inline_parser, character, left_flanking,
    +                                       right_flanking, res);
    +  }
    +
    +  return res;
    +}
    +
    +static delimiter *insert(cmark_syntax_extension *self, cmark_parser *parser,
    +                         cmark_inline_parser *inline_parser, delimiter *opener,
    +                         delimiter *closer) {
    +  cmark_node *strikethrough;
    +  cmark_node *tmp, *next;
    +  delimiter *delim, *tmp_delim;
    +  delimiter *res = closer->next;
    +
    +  strikethrough = opener->inl_text;
    +
    +  if (opener->inl_text->as.literal.len != closer->inl_text->as.literal.len)
    +    goto done;
    +
    +  if (!cmark_node_set_type(strikethrough, CMARK_NODE_STRIKETHROUGH))
    +    goto done;
    +
    +  cmark_node_set_syntax_extension(strikethrough, self);
    +
    +  tmp = cmark_node_next(opener->inl_text);
    +
    +  while (tmp) {
    +    if (tmp == closer->inl_text)
    +      break;
    +    next = cmark_node_next(tmp);
    +    cmark_node_append_child(strikethrough, tmp);
    +    tmp = next;
    +  }
    +
    +  strikethrough->end_column = closer->inl_text->start_column + closer->inl_text->as.literal.len - 1;
    +  cmark_node_free(closer->inl_text);
    +
    +  delim = closer;
    +  while (delim != NULL && delim != opener) {
    +    tmp_delim = delim->previous;
    +    cmark_inline_parser_remove_delimiter(inline_parser, delim);
    +    delim = tmp_delim;
    +  }
    +
    +  cmark_inline_parser_remove_delimiter(inline_parser, opener);
    +
    +done:
    +  return res;
    +}
    +
    +static const char *get_type_string(cmark_syntax_extension *extension,
    +                                   cmark_node *node) {
    +  return node->type == CMARK_NODE_STRIKETHROUGH ? "strikethrough" : "";
    +}
    +
    +static int can_contain(cmark_syntax_extension *extension, cmark_node *node,
    +                       cmark_node_type child_type) {
    +  if (node->type != CMARK_NODE_STRIKETHROUGH)
    +    return false;
    +
    +  return CMARK_NODE_TYPE_INLINE_P(child_type);
    +}
    +
    +static void commonmark_render(cmark_syntax_extension *extension,
    +                              cmark_renderer *renderer, cmark_node *node,
    +                              cmark_event_type ev_type, int options) {
    +  renderer->out(renderer, node, "~~", false, LITERAL);
    +}
    +
    +static void latex_render(cmark_syntax_extension *extension,
    +                         cmark_renderer *renderer, cmark_node *node,
    +                         cmark_event_type ev_type, int options) {
    +  // requires \usepackage{ulem}
    +  bool entering = (ev_type == CMARK_EVENT_ENTER);
    +  if (entering) {
    +    renderer->out(renderer, node, "\\sout{", false, LITERAL);
    +  } else {
    +    renderer->out(renderer, node, "}", false, LITERAL);
    +  }
    +}
    +
    +static void man_render(cmark_syntax_extension *extension,
    +                       cmark_renderer *renderer, cmark_node *node,
    +                       cmark_event_type ev_type, int options) {
    +  bool entering = (ev_type == CMARK_EVENT_ENTER);
    +  if (entering) {
    +    renderer->cr(renderer);
    +    renderer->out(renderer, node, ".ST \"", false, LITERAL);
    +  } else {
    +    renderer->out(renderer, node, "\"", false, LITERAL);
    +    renderer->cr(renderer);
    +  }
    +}
    +
    +static void html_render(cmark_syntax_extension *extension,
    +                        cmark_html_renderer *renderer, cmark_node *node,
    +                        cmark_event_type ev_type, int options) {
    +  bool entering = (ev_type == CMARK_EVENT_ENTER);
    +  if (entering) {
    +    cmark_strbuf_puts(renderer->html, "");
    +  } else {
    +    cmark_strbuf_puts(renderer->html, "");
    +  }
    +}
    +
    +static void plaintext_render(cmark_syntax_extension *extension,
    +                             cmark_renderer *renderer, cmark_node *node,
    +                             cmark_event_type ev_type, int options) {
    +  renderer->out(renderer, node, "~", false, LITERAL);
    +}
    +
    +cmark_syntax_extension *create_strikethrough_extension(void) {
    +  cmark_syntax_extension *ext = cmark_syntax_extension_new("strikethrough");
    +  cmark_llist *special_chars = NULL;
    +
    +  cmark_syntax_extension_set_get_type_string_func(ext, get_type_string);
    +  cmark_syntax_extension_set_can_contain_func(ext, can_contain);
    +  cmark_syntax_extension_set_commonmark_render_func(ext, commonmark_render);
    +  cmark_syntax_extension_set_latex_render_func(ext, latex_render);
    +  cmark_syntax_extension_set_man_render_func(ext, man_render);
    +  cmark_syntax_extension_set_html_render_func(ext, html_render);
    +  cmark_syntax_extension_set_plaintext_render_func(ext, plaintext_render);
    +  CMARK_NODE_STRIKETHROUGH = cmark_syntax_extension_add_node(1);
    +
    +  cmark_syntax_extension_set_match_inline_func(ext, match);
    +  cmark_syntax_extension_set_inline_from_delim_func(ext, insert);
    +
    +  cmark_mem *mem = cmark_get_default_mem_allocator();
    +  special_chars = cmark_llist_append(mem, special_chars, (void *)'~');
    +  cmark_syntax_extension_set_special_inline_chars(ext, special_chars);
    +
    +  cmark_syntax_extension_set_emphasis(ext, 1);
    +
    +  return ext;
    +}
    diff --git a/extensions/strikethrough.h b/extensions/strikethrough.h
    new file mode 100644
    index 000000000..a52a2b4ac
    --- /dev/null
    +++ b/extensions/strikethrough.h
    @@ -0,0 +1,9 @@
    +#ifndef CMARK_GFM_STRIKETHROUGH_H
    +#define CMARK_GFM_STRIKETHROUGH_H
    +
    +#include "cmark-gfm-core-extensions.h"
    +
    +extern cmark_node_type CMARK_NODE_STRIKETHROUGH;
    +cmark_syntax_extension *create_strikethrough_extension(void);
    +
    +#endif
    diff --git a/extensions/table.c b/extensions/table.c
    new file mode 100644
    index 000000000..f5b4016aa
    --- /dev/null
    +++ b/extensions/table.c
    @@ -0,0 +1,822 @@
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +#include 
    +
    +#include "ext_scanners.h"
    +#include "strikethrough.h"
    +#include "table.h"
    +#include "cmark-gfm-core-extensions.h"
    +
    +cmark_node_type CMARK_NODE_TABLE, CMARK_NODE_TABLE_ROW,
    +    CMARK_NODE_TABLE_CELL;
    +
    +typedef struct {
    +  uint16_t n_columns;
    +  int paragraph_offset;
    +  cmark_llist *cells;
    +} table_row;
    +
    +typedef struct {
    +  uint16_t n_columns;
    +  uint8_t *alignments;
    +} node_table;
    +
    +typedef struct {
    +  bool is_header;
    +} node_table_row;
    +
    +typedef struct {
    +  cmark_strbuf *buf;
    +  int start_offset, end_offset, internal_offset;
    +} node_cell;
    +
    +static void free_table_cell(cmark_mem *mem, void *data) {
    +  node_cell *cell = (node_cell *)data;
    +  cmark_strbuf_free((cmark_strbuf *)cell->buf);
    +  mem->free(cell->buf);
    +  mem->free(cell);
    +}
    +
    +static void free_table_row(cmark_mem *mem, table_row *row) {
    +  if (!row)
    +    return;
    +
    +  cmark_llist_free_full(mem, row->cells, (cmark_free_func)free_table_cell);
    +
    +  mem->free(row);
    +}
    +
    +static void free_node_table(cmark_mem *mem, void *ptr) {
    +  node_table *t = (node_table *)ptr;
    +  mem->free(t->alignments);
    +  mem->free(t);
    +}
    +
    +static void free_node_table_row(cmark_mem *mem, void *ptr) {
    +  mem->free(ptr);
    +}
    +
    +static int get_n_table_columns(cmark_node *node) {
    +  if (!node || node->type != CMARK_NODE_TABLE)
    +    return -1;
    +
    +  return (int)((node_table *)node->as.opaque)->n_columns;
    +}
    +
    +static int set_n_table_columns(cmark_node *node, uint16_t n_columns) {
    +  if (!node || node->type != CMARK_NODE_TABLE)
    +    return 0;
    +
    +  ((node_table *)node->as.opaque)->n_columns = n_columns;
    +  return 1;
    +}
    +
    +static uint8_t *get_table_alignments(cmark_node *node) {
    +  if (!node || node->type != CMARK_NODE_TABLE)
    +    return 0;
    +
    +  return ((node_table *)node->as.opaque)->alignments;
    +}
    +
    +static int set_table_alignments(cmark_node *node, uint8_t *alignments) {
    +  if (!node || node->type != CMARK_NODE_TABLE)
    +    return 0;
    +
    +  ((node_table *)node->as.opaque)->alignments = alignments;
    +  return 1;
    +}
    +
    +static cmark_strbuf *unescape_pipes(cmark_mem *mem, unsigned char *string, bufsize_t len)
    +{
    +  cmark_strbuf *res = (cmark_strbuf *)mem->calloc(1, sizeof(cmark_strbuf));
    +  bufsize_t r, w;
    +
    +  cmark_strbuf_init(mem, res, len + 1);
    +  cmark_strbuf_put(res, string, len);
    +  cmark_strbuf_putc(res, '\0');
    +
    +  for (r = 0, w = 0; r < len; ++r) {
    +    if (res->ptr[r] == '\\' && res->ptr[r + 1] == '|')
    +      r++;
    +
    +    res->ptr[w++] = res->ptr[r];
    +  }
    +
    +  cmark_strbuf_truncate(res, w);
    +
    +  return res;
    +}
    +
    +static table_row *row_from_string(cmark_syntax_extension *self,
    +                                  cmark_parser *parser, unsigned char *string,
    +                                  int len) {
    +  // Parses a single table row. It has the following form:
    +  // `delim? table_cell (delim table_cell)* delim? newline`
    +  // Note that cells are allowed to be empty.
    +  //
    +  // From the GitHub-flavored Markdown specification:
    +  //
    +  // > Each row consists of cells containing arbitrary text, in which inlines
    +  // > are parsed, separated by pipes (|). A leading and trailing pipe is also
    +  // > recommended for clarity of reading, and if there’s otherwise parsing
    +  // > ambiguity.
    +
    +  table_row *row = NULL;
    +  bufsize_t cell_matched = 1, pipe_matched = 1, offset;
    +  int expect_more_cells = 1;
    +  int row_end_offset = 0;
    +
    +  row = (table_row *)parser->mem->calloc(1, sizeof(table_row));
    +  row->n_columns = 0;
    +  row->cells = NULL;
    +
    +  // Scan past the (optional) leading pipe.
    +  offset = scan_table_cell_end(string, len, 0);
    +
    +  // Parse the cells of the row. Stop if we reach the end of the input, or if we
    +  // cannot detect any more cells.
    +  while (offset < len && expect_more_cells) {
    +    cell_matched = scan_table_cell(string, len, offset);
    +    pipe_matched = scan_table_cell_end(string, len, offset + cell_matched);
    +
    +    if (cell_matched || pipe_matched) {
    +      // We are guaranteed to have a cell, since (1) either we found some
    +      // content and cell_matched, or (2) we found an empty cell followed by a
    +      // pipe.
    +      cmark_strbuf *cell_buf = unescape_pipes(parser->mem, string + offset,
    +          cell_matched);
    +      cmark_strbuf_trim(cell_buf);
    +
    +      node_cell *cell = (node_cell *)parser->mem->calloc(1, sizeof(*cell));
    +      cell->buf = cell_buf;
    +      cell->start_offset = offset;
    +      cell->end_offset = offset + cell_matched - 1;
    +
    +      while (cell->start_offset > 0 && string[cell->start_offset - 1] != '|') {
    +        --cell->start_offset;
    +        ++cell->internal_offset;
    +      }
    +
    +      row->n_columns += 1;
    +      row->cells = cmark_llist_append(parser->mem, row->cells, cell);
    +    }
    +
    +    offset += cell_matched + pipe_matched;
    +
    +    if (pipe_matched) {
    +      expect_more_cells = 1;
    +    } else {
    +      // We've scanned the last cell. Check if we have reached the end of the row
    +      row_end_offset = scan_table_row_end(string, len, offset);
    +      offset += row_end_offset;
    +
    +      // If the end of the row is not the end of the input,
    +      // the row is not a real row but potentially part of the paragraph
    +      // preceding the table.
    +      if (row_end_offset && offset != len) {
    +        row->paragraph_offset = offset;
    +
    +        cmark_llist_free_full(parser->mem, row->cells, (cmark_free_func)free_table_cell);
    +        row->cells = NULL;
    +        row->n_columns = 0;
    +
    +        // Scan past the (optional) leading pipe.
    +        offset += scan_table_cell_end(string, len, offset);
    +
    +        expect_more_cells = 1;
    +      } else {
    +        expect_more_cells = 0;
    +      }
    +    }
    +  }
    +
    +  if (offset != len || row->n_columns == 0) {
    +    free_table_row(parser->mem, row);
    +    row = NULL;
    +  }
    +
    +  return row;
    +}
    +
    +static void try_inserting_table_header_paragraph(cmark_parser *parser,
    +                                                 cmark_node *parent_container,
    +                                                 unsigned char *parent_string,
    +                                                 int paragraph_offset) {
    +  cmark_node *paragraph;
    +  cmark_strbuf *paragraph_content;
    +
    +  paragraph = cmark_node_new_with_mem(CMARK_NODE_PARAGRAPH, parser->mem);
    +
    +  paragraph_content = unescape_pipes(parser->mem, parent_string, paragraph_offset);
    +  cmark_strbuf_trim(paragraph_content);
    +  cmark_node_set_string_content(paragraph, (char *) paragraph_content->ptr);
    +  cmark_strbuf_free(paragraph_content);
    +  parser->mem->free(paragraph_content);
    +
    +  if (!cmark_node_insert_before(parent_container, paragraph)) {
    +    parser->mem->free(paragraph);
    +  }
    +}
    +
    +static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
    +                                            cmark_parser *parser,
    +                                            cmark_node *parent_container,
    +                                            unsigned char *input, int len) {
    +  cmark_node *table_header;
    +  table_row *header_row = NULL;
    +  table_row *marker_row = NULL;
    +  node_table_row *ntr;
    +  const char *parent_string;
    +  uint16_t i;
    +
    +  if (!scan_table_start(input, len, cmark_parser_get_first_nonspace(parser))) {
    +    return parent_container;
    +  }
    +
    +  // Since scan_table_start was successful, we must have a marker row.
    +  marker_row = row_from_string(self, parser,
    +                               input + cmark_parser_get_first_nonspace(parser),
    +                               len - cmark_parser_get_first_nonspace(parser));
    +  assert(marker_row);
    +
    +  cmark_arena_push();
    +
    +  // Check for a matching header row. We call `row_from_string` with the entire
    +  // (potentially long) parent container as input, but this should be safe since
    +  // `row_from_string` bails out early if it does not find a row.
    +  parent_string = cmark_node_get_string_content(parent_container);
    +  header_row = row_from_string(self, parser, (unsigned char *)parent_string,
    +                               (int)strlen(parent_string));
    +  if (!header_row || header_row->n_columns != marker_row->n_columns) {
    +    free_table_row(parser->mem, marker_row);
    +    free_table_row(parser->mem, header_row);
    +    cmark_arena_pop();
    +    return parent_container;
    +  }
    +
    +  if (cmark_arena_pop()) {
    +    marker_row = row_from_string(
    +        self, parser, input + cmark_parser_get_first_nonspace(parser),
    +        len - cmark_parser_get_first_nonspace(parser));
    +    header_row = row_from_string(self, parser, (unsigned char *)parent_string,
    +                                 (int)strlen(parent_string));
    +  }
    +
    +  if (!cmark_node_set_type(parent_container, CMARK_NODE_TABLE)) {
    +    free_table_row(parser->mem, header_row);
    +    free_table_row(parser->mem, marker_row);
    +    return parent_container;
    +  }
    +
    +  if (header_row->paragraph_offset) {
    +    try_inserting_table_header_paragraph(parser, parent_container, (unsigned char *)parent_string,
    +                                         header_row->paragraph_offset);
    +  }
    +
    +  cmark_node_set_syntax_extension(parent_container, self);
    +  parent_container->as.opaque = parser->mem->calloc(1, sizeof(node_table));
    +  set_n_table_columns(parent_container, header_row->n_columns);
    +
    +  uint8_t *alignments =
    +      (uint8_t *)parser->mem->calloc(header_row->n_columns, sizeof(uint8_t));
    +  cmark_llist *it = marker_row->cells;
    +  for (i = 0; it; it = it->next, ++i) {
    +    node_cell *node = (node_cell *)it->data;
    +    bool left = node->buf->ptr[0] == ':', right = node->buf->ptr[node->buf->size - 1] == ':';
    +
    +    if (left && right)
    +      alignments[i] = 'c';
    +    else if (left)
    +      alignments[i] = 'l';
    +    else if (right)
    +      alignments[i] = 'r';
    +  }
    +  set_table_alignments(parent_container, alignments);
    +
    +  table_header =
    +      cmark_parser_add_child(parser, parent_container, CMARK_NODE_TABLE_ROW,
    +                             parent_container->start_column);
    +  cmark_node_set_syntax_extension(table_header, self);
    +  table_header->end_column = parent_container->start_column + (int)strlen(parent_string) - 2;
    +  table_header->start_line = table_header->end_line = parent_container->start_line;
    +
    +  table_header->as.opaque = ntr = (node_table_row *)parser->mem->calloc(1, sizeof(node_table_row));
    +  ntr->is_header = true;
    +
    +  {
    +    cmark_llist *tmp;
    +
    +    for (tmp = header_row->cells; tmp; tmp = tmp->next) {
    +      node_cell *cell = (node_cell *) tmp->data;
    +      cmark_node *header_cell = cmark_parser_add_child(parser, table_header,
    +          CMARK_NODE_TABLE_CELL, parent_container->start_column + cell->start_offset);
    +      header_cell->start_line = header_cell->end_line = parent_container->start_line;
    +      header_cell->internal_offset = cell->internal_offset;
    +      header_cell->end_column = parent_container->start_column + cell->end_offset;
    +      cmark_node_set_string_content(header_cell, (char *) cell->buf->ptr);
    +      cmark_node_set_syntax_extension(header_cell, self);
    +    }
    +  }
    +
    +  cmark_parser_advance_offset(
    +      parser, (char *)input,
    +      (int)strlen((char *)input) - 1 - cmark_parser_get_offset(parser), false);
    +
    +  free_table_row(parser->mem, header_row);
    +  free_table_row(parser->mem, marker_row);
    +  return parent_container;
    +}
    +
    +static cmark_node *try_opening_table_row(cmark_syntax_extension *self,
    +                                         cmark_parser *parser,
    +                                         cmark_node *parent_container,
    +                                         unsigned char *input, int len) {
    +  cmark_node *table_row_block;
    +  table_row *row;
    +
    +  if (cmark_parser_is_blank(parser))
    +    return NULL;
    +
    +  table_row_block =
    +      cmark_parser_add_child(parser, parent_container, CMARK_NODE_TABLE_ROW,
    +                             parent_container->start_column);
    +  cmark_node_set_syntax_extension(table_row_block, self);
    +  table_row_block->end_column = parent_container->end_column;
    +  table_row_block->as.opaque = parser->mem->calloc(1, sizeof(node_table_row));
    +
    +  row = row_from_string(self, parser, input + cmark_parser_get_first_nonspace(parser),
    +      len - cmark_parser_get_first_nonspace(parser));
    +
    +  {
    +    cmark_llist *tmp;
    +    int i, table_columns = get_n_table_columns(parent_container);
    +
    +    for (tmp = row->cells, i = 0; tmp && i < table_columns; tmp = tmp->next, ++i) {
    +      node_cell *cell = (node_cell *) tmp->data;
    +      cmark_node *node = cmark_parser_add_child(parser, table_row_block,
    +          CMARK_NODE_TABLE_CELL, parent_container->start_column + cell->start_offset);
    +      node->internal_offset = cell->internal_offset;
    +      node->end_column = parent_container->start_column + cell->end_offset;
    +      cmark_node_set_string_content(node, (char *) cell->buf->ptr);
    +      cmark_node_set_syntax_extension(node, self);
    +    }
    +
    +    for (; i < table_columns; ++i) {
    +      cmark_node *node = cmark_parser_add_child(
    +          parser, table_row_block, CMARK_NODE_TABLE_CELL, 0);
    +      cmark_node_set_syntax_extension(node, self);
    +    }
    +  }
    +
    +  free_table_row(parser->mem, row);
    +
    +  cmark_parser_advance_offset(parser, (char *)input,
    +                              len - 1 - cmark_parser_get_offset(parser), false);
    +
    +  return table_row_block;
    +}
    +
    +static cmark_node *try_opening_table_block(cmark_syntax_extension *self,
    +                                           int indented, cmark_parser *parser,
    +                                           cmark_node *parent_container,
    +                                           unsigned char *input, int len) {
    +  cmark_node_type parent_type = cmark_node_get_type(parent_container);
    +
    +  if (!indented && parent_type == CMARK_NODE_PARAGRAPH) {
    +    return try_opening_table_header(self, parser, parent_container, input, len);
    +  } else if (!indented && parent_type == CMARK_NODE_TABLE) {
    +    return try_opening_table_row(self, parser, parent_container, input, len);
    +  }
    +
    +  return NULL;
    +}
    +
    +static int matches(cmark_syntax_extension *self, cmark_parser *parser,
    +                   unsigned char *input, int len,
    +                   cmark_node *parent_container) {
    +  int res = 0;
    +
    +  if (cmark_node_get_type(parent_container) == CMARK_NODE_TABLE) {
    +    cmark_arena_push();
    +    table_row *new_row = row_from_string(
    +        self, parser, input + cmark_parser_get_first_nonspace(parser),
    +        len - cmark_parser_get_first_nonspace(parser));
    +    if (new_row && new_row->n_columns)
    +      res = 1;
    +    free_table_row(parser->mem, new_row);
    +    cmark_arena_pop();
    +  }
    +
    +  return res;
    +}
    +
    +static const char *get_type_string(cmark_syntax_extension *self,
    +                                   cmark_node *node) {
    +  if (node->type == CMARK_NODE_TABLE) {
    +    return "table";
    +  } else if (node->type == CMARK_NODE_TABLE_ROW) {
    +    if (((node_table_row *)node->as.opaque)->is_header)
    +      return "table_header";
    +    else
    +      return "table_row";
    +  } else if (node->type == CMARK_NODE_TABLE_CELL) {
    +    return "table_cell";
    +  }
    +
    +  return "";
    +}
    +
    +static int can_contain(cmark_syntax_extension *extension, cmark_node *node,
    +                       cmark_node_type child_type) {
    +  if (node->type == CMARK_NODE_TABLE) {
    +    return child_type == CMARK_NODE_TABLE_ROW;
    +  } else if (node->type == CMARK_NODE_TABLE_ROW) {
    +    return child_type == CMARK_NODE_TABLE_CELL;
    +  } else if (node->type == CMARK_NODE_TABLE_CELL) {
    +    return child_type == CMARK_NODE_TEXT || child_type == CMARK_NODE_CODE ||
    +           child_type == CMARK_NODE_EMPH || child_type == CMARK_NODE_STRONG ||
    +           child_type == CMARK_NODE_LINK || child_type == CMARK_NODE_IMAGE || child_type == CMARK_NODE_ATTRIBUTE ||
    +           child_type == CMARK_NODE_STRIKETHROUGH ||
    +           child_type == CMARK_NODE_HTML_INLINE ||
    +           child_type == CMARK_NODE_FOOTNOTE_REFERENCE;
    +  }
    +  return false;
    +}
    +
    +static int contains_inlines(cmark_syntax_extension *extension,
    +                            cmark_node *node) {
    +  return node->type == CMARK_NODE_TABLE_CELL;
    +}
    +
    +static void commonmark_render(cmark_syntax_extension *extension,
    +                              cmark_renderer *renderer, cmark_node *node,
    +                              cmark_event_type ev_type, int options) {
    +  bool entering = (ev_type == CMARK_EVENT_ENTER);
    +
    +  if (node->type == CMARK_NODE_TABLE) {
    +    renderer->blankline(renderer);
    +  } else if (node->type == CMARK_NODE_TABLE_ROW) {
    +    if (entering) {
    +      renderer->cr(renderer);
    +      renderer->out(renderer, node, "|", false, LITERAL);
    +    }
    +  } else if (node->type == CMARK_NODE_TABLE_CELL) {
    +    if (entering) {
    +      renderer->out(renderer, node, " ", false, LITERAL);
    +    } else {
    +      renderer->out(renderer, node, " |", false, LITERAL);
    +      if (((node_table_row *)node->parent->as.opaque)->is_header &&
    +          !node->next) {
    +        int i;
    +        uint8_t *alignments = get_table_alignments(node->parent->parent);
    +        uint16_t n_cols =
    +            ((node_table *)node->parent->parent->as.opaque)->n_columns;
    +        renderer->cr(renderer);
    +        renderer->out(renderer, node, "|", false, LITERAL);
    +        for (i = 0; i < n_cols; i++) {
    +          switch (alignments[i]) {
    +          case 0:   renderer->out(renderer, node, " --- |", false, LITERAL); break;
    +          case 'l': renderer->out(renderer, node, " :-- |", false, LITERAL); break;
    +          case 'c': renderer->out(renderer, node, " :-: |", false, LITERAL); break;
    +          case 'r': renderer->out(renderer, node, " --: |", false, LITERAL); break;
    +          }
    +        }
    +        renderer->cr(renderer);
    +      }
    +    }
    +  } else {
    +    assert(false);
    +  }
    +}
    +
    +static void latex_render(cmark_syntax_extension *extension,
    +                         cmark_renderer *renderer, cmark_node *node,
    +                         cmark_event_type ev_type, int options) {
    +  bool entering = (ev_type == CMARK_EVENT_ENTER);
    +
    +  if (node->type == CMARK_NODE_TABLE) {
    +    if (entering) {
    +      int i;
    +      uint16_t n_cols;
    +      uint8_t *alignments = get_table_alignments(node);
    +
    +      renderer->cr(renderer);
    +      renderer->out(renderer, node, "\\begin{table}", false, LITERAL);
    +      renderer->cr(renderer);
    +      renderer->out(renderer, node, "\\begin{tabular}{", false, LITERAL);
    +
    +      n_cols = ((node_table *)node->as.opaque)->n_columns;
    +      for (i = 0; i < n_cols; i++) {
    +        switch(alignments[i]) {
    +        case 0:
    +        case 'l':
    +          renderer->out(renderer, node, "l", false, LITERAL);
    +          break;
    +        case 'c':
    +          renderer->out(renderer, node, "c", false, LITERAL);
    +          break;
    +        case 'r':
    +          renderer->out(renderer, node, "r", false, LITERAL);
    +          break;
    +        }
    +      }
    +      renderer->out(renderer, node, "}", false, LITERAL);
    +      renderer->cr(renderer);
    +    } else {
    +      renderer->out(renderer, node, "\\end{tabular}", false, LITERAL);
    +      renderer->cr(renderer);
    +      renderer->out(renderer, node, "\\end{table}", false, LITERAL);
    +      renderer->cr(renderer);
    +    }
    +  } else if (node->type == CMARK_NODE_TABLE_ROW) {
    +    if (!entering) {
    +      renderer->cr(renderer);
    +    }
    +  } else if (node->type == CMARK_NODE_TABLE_CELL) {
    +    if (!entering) {
    +      if (node->next) {
    +        renderer->out(renderer, node, " & ", false, LITERAL);
    +      } else {
    +        renderer->out(renderer, node, " \\\\", false, LITERAL);
    +      }
    +    }
    +  } else {
    +    assert(false);
    +  }
    +}
    +
    +static const char *xml_attr(cmark_syntax_extension *extension,
    +                            cmark_node *node) {
    +  if (node->type == CMARK_NODE_TABLE_CELL) {
    +    if (cmark_gfm_extensions_get_table_row_is_header(node->parent)) {
    +      uint8_t *alignments = get_table_alignments(node->parent->parent);
    +      int i = 0;
    +      cmark_node *n;
    +      for (n = node->parent->first_child; n; n = n->next, ++i)
    +        if (n == node)
    +          break;
    +      switch (alignments[i]) {
    +      case 'l': return " align=\"left\"";
    +      case 'c': return " align=\"center\"";
    +      case 'r': return " align=\"right\"";
    +      }
    +    }
    +  }
    +
    +  return NULL;
    +}
    +
    +static void man_render(cmark_syntax_extension *extension,
    +                       cmark_renderer *renderer, cmark_node *node,
    +                       cmark_event_type ev_type, int options) {
    +  bool entering = (ev_type == CMARK_EVENT_ENTER);
    +
    +  if (node->type == CMARK_NODE_TABLE) {
    +    if (entering) {
    +      int i;
    +      uint16_t n_cols;
    +      uint8_t *alignments = get_table_alignments(node);
    +
    +      renderer->cr(renderer);
    +      renderer->out(renderer, node, ".TS", false, LITERAL);
    +      renderer->cr(renderer);
    +      renderer->out(renderer, node, "tab(@);", false, LITERAL);
    +      renderer->cr(renderer);
    +
    +      n_cols = ((node_table *)node->as.opaque)->n_columns;
    +
    +      for (i = 0; i < n_cols; i++) {
    +        switch (alignments[i]) {
    +        case 'l':
    +          renderer->out(renderer, node, "l", false, LITERAL);
    +          break;
    +        case 0:
    +        case 'c':
    +          renderer->out(renderer, node, "c", false, LITERAL);
    +          break;
    +        case 'r':
    +          renderer->out(renderer, node, "r", false, LITERAL);
    +          break;
    +        }
    +      }
    +
    +      if (n_cols) {
    +        renderer->out(renderer, node, ".", false, LITERAL);
    +        renderer->cr(renderer);
    +      }
    +    } else {
    +      renderer->out(renderer, node, ".TE", false, LITERAL);
    +      renderer->cr(renderer);
    +    }
    +  } else if (node->type == CMARK_NODE_TABLE_ROW) {
    +    if (!entering) {
    +      renderer->cr(renderer);
    +    }
    +  } else if (node->type == CMARK_NODE_TABLE_CELL) {
    +    if (!entering && node->next) {
    +      renderer->out(renderer, node, "@", false, LITERAL);
    +    }
    +  } else {
    +    assert(false);
    +  }
    +}
    +
    +static void html_table_add_align(cmark_strbuf* html, const char* align, int options) {
    +  if (options & CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES) {
    +    cmark_strbuf_puts(html, " style=\"text-align: ");
    +    cmark_strbuf_puts(html, align);
    +    cmark_strbuf_puts(html, "\"");
    +  } else {
    +    cmark_strbuf_puts(html, " align=\"");
    +    cmark_strbuf_puts(html, align);
    +    cmark_strbuf_puts(html, "\"");
    +  }
    +}
    +
    +struct html_table_state {
    +  unsigned need_closing_table_body : 1;
    +  unsigned in_table_header : 1;
    +};
    +
    +static void html_render(cmark_syntax_extension *extension,
    +                        cmark_html_renderer *renderer, cmark_node *node,
    +                        cmark_event_type ev_type, int options) {
    +  bool entering = (ev_type == CMARK_EVENT_ENTER);
    +  cmark_strbuf *html = renderer->html;
    +  cmark_node *n;
    +
    +  // XXX: we just monopolise renderer->opaque.
    +  struct html_table_state *table_state =
    +      (struct html_table_state *)&renderer->opaque;
    +
    +  if (node->type == CMARK_NODE_TABLE) {
    +    if (entering) {
    +      cmark_html_render_cr(html);
    +      cmark_strbuf_puts(html, "');
    +      table_state->need_closing_table_body = false;
    +    } else {
    +      if (table_state->need_closing_table_body) {
    +        cmark_html_render_cr(html);
    +        cmark_strbuf_puts(html, "");
    +        cmark_html_render_cr(html);
    +      }
    +      table_state->need_closing_table_body = false;
    +      cmark_html_render_cr(html);
    +      cmark_strbuf_puts(html, "");
    +      cmark_html_render_cr(html);
    +    }
    +  } else if (node->type == CMARK_NODE_TABLE_ROW) {
    +    if (entering) {
    +      cmark_html_render_cr(html);
    +      if (((node_table_row *)node->as.opaque)->is_header) {
    +        table_state->in_table_header = 1;
    +        cmark_strbuf_puts(html, "");
    +        cmark_html_render_cr(html);
    +      } else if (!table_state->need_closing_table_body) {
    +        cmark_strbuf_puts(html, "");
    +        cmark_html_render_cr(html);
    +        table_state->need_closing_table_body = 1;
    +      }
    +      cmark_strbuf_puts(html, "');
    +    } else {
    +      cmark_html_render_cr(html);
    +      cmark_strbuf_puts(html, "");
    +      if (((node_table_row *)node->as.opaque)->is_header) {
    +        cmark_html_render_cr(html);
    +        cmark_strbuf_puts(html, "");
    +        table_state->in_table_header = false;
    +      }
    +    }
    +  } else if (node->type == CMARK_NODE_TABLE_CELL) {
    +    uint8_t *alignments = get_table_alignments(node->parent->parent);
    +    if (entering) {
    +      cmark_html_render_cr(html);
    +      if (table_state->in_table_header) {
    +        cmark_strbuf_puts(html, "parent->first_child; n; n = n->next, ++i)
    +        if (n == node)
    +          break;
    +
    +      switch (alignments[i]) {
    +      case 'l': html_table_add_align(html, "left", options); break;
    +      case 'c': html_table_add_align(html, "center", options); break;
    +      case 'r': html_table_add_align(html, "right", options); break;
    +      }
    +
    +      cmark_html_render_sourcepos(node, html, options);
    +      cmark_strbuf_putc(html, '>');
    +    } else {
    +      if (table_state->in_table_header) {
    +        cmark_strbuf_puts(html, "");
    +      } else {
    +        cmark_strbuf_puts(html, "");
    +      }
    +    }
    +  } else {
    +    assert(false);
    +  }
    +}
    +
    +static void opaque_alloc(cmark_syntax_extension *self, cmark_mem *mem, cmark_node *node) {
    +  if (node->type == CMARK_NODE_TABLE) {
    +    node->as.opaque = mem->calloc(1, sizeof(node_table));
    +  } else if (node->type == CMARK_NODE_TABLE_ROW) {
    +    node->as.opaque = mem->calloc(1, sizeof(node_table_row));
    +  } else if (node->type == CMARK_NODE_TABLE_CELL) {
    +    node->as.opaque = mem->calloc(1, sizeof(node_cell));
    +  }
    +}
    +
    +static void opaque_free(cmark_syntax_extension *self, cmark_mem *mem, cmark_node *node) {
    +  if (node->type == CMARK_NODE_TABLE) {
    +    free_node_table(mem, node->as.opaque);
    +  } else if (node->type == CMARK_NODE_TABLE_ROW) {
    +    free_node_table_row(mem, node->as.opaque);
    +  }
    +}
    +
    +static int escape(cmark_syntax_extension *self, cmark_node *node, int c) {
    +  return
    +    node->type != CMARK_NODE_TABLE &&
    +    node->type != CMARK_NODE_TABLE_ROW &&
    +    node->type != CMARK_NODE_TABLE_CELL &&
    +    c == '|';
    +}
    +
    +cmark_syntax_extension *create_table_extension(void) {
    +  cmark_syntax_extension *self = cmark_syntax_extension_new("table");
    +
    +  cmark_syntax_extension_set_match_block_func(self, matches);
    +  cmark_syntax_extension_set_open_block_func(self, try_opening_table_block);
    +  cmark_syntax_extension_set_get_type_string_func(self, get_type_string);
    +  cmark_syntax_extension_set_can_contain_func(self, can_contain);
    +  cmark_syntax_extension_set_contains_inlines_func(self, contains_inlines);
    +  cmark_syntax_extension_set_commonmark_render_func(self, commonmark_render);
    +  cmark_syntax_extension_set_plaintext_render_func(self, commonmark_render);
    +  cmark_syntax_extension_set_latex_render_func(self, latex_render);
    +  cmark_syntax_extension_set_xml_attr_func(self, xml_attr);
    +  cmark_syntax_extension_set_man_render_func(self, man_render);
    +  cmark_syntax_extension_set_html_render_func(self, html_render);
    +  cmark_syntax_extension_set_opaque_alloc_func(self, opaque_alloc);
    +  cmark_syntax_extension_set_opaque_free_func(self, opaque_free);
    +  cmark_syntax_extension_set_commonmark_escape_func(self, escape);
    +  CMARK_NODE_TABLE = cmark_syntax_extension_add_node(0);
    +  CMARK_NODE_TABLE_ROW = cmark_syntax_extension_add_node(0);
    +  CMARK_NODE_TABLE_CELL = cmark_syntax_extension_add_node(0);
    +
    +  return self;
    +}
    +
    +uint16_t cmark_gfm_extensions_get_table_columns(cmark_node *node) {
    +  if (node->type != CMARK_NODE_TABLE)
    +    return 0;
    +
    +  return ((node_table *)node->as.opaque)->n_columns;
    +}
    +
    +uint8_t *cmark_gfm_extensions_get_table_alignments(cmark_node *node) {
    +  if (node->type != CMARK_NODE_TABLE)
    +    return 0;
    +
    +  return ((node_table *)node->as.opaque)->alignments;
    +}
    +
    +int cmark_gfm_extensions_set_table_columns(cmark_node *node, uint16_t n_columns) {
    +  return set_n_table_columns(node, n_columns);
    +}
    +
    +int cmark_gfm_extensions_set_table_alignments(cmark_node *node, uint16_t ncols, uint8_t *alignments) {
    +  uint8_t *a = (uint8_t *)cmark_node_mem(node)->calloc(1, ncols);
    +  memcpy(a, alignments, ncols);
    +  return set_table_alignments(node, a);
    +}
    +
    +int cmark_gfm_extensions_get_table_row_is_header(cmark_node *node)
    +{
    +  if (!node || node->type != CMARK_NODE_TABLE_ROW)
    +    return 0;
    +
    +  return ((node_table_row *)node->as.opaque)->is_header;
    +}
    +
    +int cmark_gfm_extensions_set_table_row_is_header(cmark_node *node, int is_header)
    +{
    +  if (!node || node->type != CMARK_NODE_TABLE_ROW)
    +    return 0;
    +
    +  ((node_table_row *)node->as.opaque)->is_header = (is_header != 0);
    +  return 1;
    +}
    diff --git a/extensions/table.h b/extensions/table.h
    new file mode 100644
    index 000000000..f6a0634f0
    --- /dev/null
    +++ b/extensions/table.h
    @@ -0,0 +1,12 @@
    +#ifndef CMARK_GFM_TABLE_H
    +#define CMARK_GFM_TABLE_H
    +
    +#include "cmark-gfm-core-extensions.h"
    +
    +
    +extern cmark_node_type CMARK_NODE_TABLE, CMARK_NODE_TABLE_ROW,
    +    CMARK_NODE_TABLE_CELL;
    +
    +cmark_syntax_extension *create_table_extension(void);
    +
    +#endif
    diff --git a/extensions/tagfilter.c b/extensions/tagfilter.c
    new file mode 100644
    index 000000000..262352e0c
    --- /dev/null
    +++ b/extensions/tagfilter.c
    @@ -0,0 +1,60 @@
    +#include "tagfilter.h"
    +#include 
    +#include 
    +
    +static const char *blacklist[] = {
    +    "title",   "textarea", "style",  "xmp",       "iframe",
    +    "noembed", "noframes", "script", "plaintext", NULL,
    +};
    +
    +static int is_tag(const unsigned char *tag_data, size_t tag_size,
    +                  const char *tagname) {
    +  size_t i;
    +
    +  if (tag_size < 3 || tag_data[0] != '<')
    +    return 0;
    +
    +  i = 1;
    +
    +  if (tag_data[i] == '/') {
    +    i++;
    +  }
    +
    +  for (; i < tag_size; ++i, ++tagname) {
    +    if (*tagname == 0)
    +      break;
    +
    +    if (tolower(tag_data[i]) != *tagname)
    +      return 0;
    +  }
    +
    +  if (i == tag_size)
    +    return 0;
    +
    +  if (cmark_isspace(tag_data[i]) || tag_data[i] == '>')
    +    return 1;
    +
    +  if (tag_data[i] == '/' && tag_size >= i + 2 && tag_data[i + 1] == '>')
    +    return 1;
    +
    +  return 0;
    +}
    +
    +static int filter(cmark_syntax_extension *ext, const unsigned char *tag,
    +                  size_t tag_len) {
    +  const char **it;
    +
    +  for (it = blacklist; *it; ++it) {
    +    if (is_tag(tag, tag_len, *it)) {
    +      return 0;
    +    }
    +  }
    +
    +  return 1;
    +}
    +
    +cmark_syntax_extension *create_tagfilter_extension(void) {
    +  cmark_syntax_extension *ext = cmark_syntax_extension_new("tagfilter");
    +  cmark_syntax_extension_set_html_filter_func(ext, filter);
    +  return ext;
    +}
    diff --git a/extensions/tagfilter.h b/extensions/tagfilter.h
    new file mode 100644
    index 000000000..9a5f388d4
    --- /dev/null
    +++ b/extensions/tagfilter.h
    @@ -0,0 +1,8 @@
    +#ifndef CMARK_GFM_TAGFILTER_H
    +#define CMARK_GFM_TAGFILTER_H
    +
    +#include "cmark-gfm-core-extensions.h"
    +
    +cmark_syntax_extension *create_tagfilter_extension(void);
    +
    +#endif
    diff --git a/extensions/tasklist.c b/extensions/tasklist.c
    new file mode 100644
    index 000000000..7bef45499
    --- /dev/null
    +++ b/extensions/tasklist.c
    @@ -0,0 +1,156 @@
    +#include "tasklist.h"
    +#include 
    +#include 
    +#include 
    +#include "ext_scanners.h"
    +
    +typedef enum {
    +  CMARK_TASKLIST_NOCHECKED,
    +  CMARK_TASKLIST_CHECKED,
    +} cmark_tasklist_type;
    +
    +// Local constants
    +static const char *TYPE_STRING = "tasklist";
    +
    +static const char *get_type_string(cmark_syntax_extension *extension, cmark_node *node) {
    +  return TYPE_STRING;
    +}
    +
    +
    +// Return 1 if state was set, 0 otherwise
    +int cmark_gfm_extensions_set_tasklist_item_checked(cmark_node *node, bool is_checked) {
    +  // The node has to exist, and be an extension, and actually be the right type in order to get the value.
    +  if (!node || !node->extension || strcmp(cmark_node_get_type_string(node), TYPE_STRING))
    +    return 0;
    +
    +  node->as.list.checked = is_checked;
    +  return 1;
    +}
    +
    +bool cmark_gfm_extensions_get_tasklist_item_checked(cmark_node *node) {
    +  if (!node || !node->extension || strcmp(cmark_node_get_type_string(node), TYPE_STRING))
    +    return false;
    +
    +  if (node->as.list.checked) {
    +    return true;
    +  }
    +  else {
    +    return false;
    +  }
    +}
    +
    +static bool parse_node_item_prefix(cmark_parser *parser, const char *input,
    +                                   cmark_node *container) {
    +  bool res = false;
    +
    +  if (parser->indent >=
    +      container->as.list.marker_offset + container->as.list.padding) {
    +    cmark_parser_advance_offset(parser, input, container->as.list.marker_offset +
    +                                        container->as.list.padding,
    +                     true);
    +    res = true;
    +  } else if (parser->blank && container->first_child != NULL) {
    +    // if container->first_child is NULL, then the opening line
    +    // of the list item was blank after the list marker; in this
    +    // case, we are done with the list item.
    +    cmark_parser_advance_offset(parser, input, parser->first_nonspace - parser->offset,
    +                     false);
    +    res = true;
    +  }
    +  return res;
    +}
    +
    +static int matches(cmark_syntax_extension *self, cmark_parser *parser,
    +                   unsigned char *input, int len,
    +                   cmark_node *parent_container) {
    +  return parse_node_item_prefix(parser, (const char*)input, parent_container);
    +}
    +
    +static int can_contain(cmark_syntax_extension *extension, cmark_node *node,
    +                       cmark_node_type child_type) {
    +  return (node->type == CMARK_NODE_ITEM) ? 1 : 0;
    +}
    +
    +static cmark_node *open_tasklist_item(cmark_syntax_extension *self,
    +                                      int indented, cmark_parser *parser,
    +                                      cmark_node *parent_container,
    +                                      unsigned char *input, int len) {
    +  cmark_node_type node_type = cmark_node_get_type(parent_container);
    +  if (node_type != CMARK_NODE_ITEM) {
    +    return NULL;
    +  }
    +
    +  bufsize_t matched = scan_tasklist(input, len, 0);
    +  if (!matched) {
    +    return NULL;
    +  }
    +
    +  cmark_node_set_syntax_extension(parent_container, self);
    +  cmark_parser_advance_offset(parser, (char *)input, 3, false);
    +
    +  // Either an upper or lower case X means the task is completed.
    +  parent_container->as.list.checked = (strstr((char*)input, "[x]") || strstr((char*)input, "[X]"));
    +
    +  return NULL;
    +}
    +
    +static void commonmark_render(cmark_syntax_extension *extension,
    +                              cmark_renderer *renderer, cmark_node *node,
    +                              cmark_event_type ev_type, int options) {
    +  bool entering = (ev_type == CMARK_EVENT_ENTER);
    +  if (entering) {
    +    renderer->cr(renderer);
    +    if (node->as.list.checked) {
    +      renderer->out(renderer, node, "- [x] ", false, LITERAL);
    +    } else {
    +      renderer->out(renderer, node, "- [ ] ", false, LITERAL);
    +    }
    +    cmark_strbuf_puts(renderer->prefix, "  ");
    +  } else {
    +    cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 2);
    +    renderer->cr(renderer);
    +  }
    +}
    +
    +static void html_render(cmark_syntax_extension *extension,
    +                        cmark_html_renderer *renderer, cmark_node *node,
    +                        cmark_event_type ev_type, int options) {
    +  bool entering = (ev_type == CMARK_EVENT_ENTER);
    +  if (entering) {
    +    cmark_html_render_cr(renderer->html);
    +    cmark_strbuf_puts(renderer->html, "html, options);
    +    cmark_strbuf_putc(renderer->html, '>');
    +    if (node->as.list.checked) {
    +      cmark_strbuf_puts(renderer->html, " ");
    +    } else {
    +      cmark_strbuf_puts(renderer->html, " ");
    +    }
    +  } else {
    +    cmark_strbuf_puts(renderer->html, "\n");
    +  }
    +}
    +
    +static const char *xml_attr(cmark_syntax_extension *extension,
    +                            cmark_node *node) {
    +  if (node->as.list.checked) {
    +    return " completed=\"true\"";
    +  } else {
    +    return " completed=\"false\"";
    +  }
    +}
    +
    +cmark_syntax_extension *create_tasklist_extension(void) {
    +  cmark_syntax_extension *ext = cmark_syntax_extension_new("tasklist");
    +
    +  cmark_syntax_extension_set_match_block_func(ext, matches);
    +  cmark_syntax_extension_set_get_type_string_func(ext, get_type_string);
    +  cmark_syntax_extension_set_open_block_func(ext, open_tasklist_item);
    +  cmark_syntax_extension_set_can_contain_func(ext, can_contain);
    +  cmark_syntax_extension_set_commonmark_render_func(ext, commonmark_render);
    +  cmark_syntax_extension_set_plaintext_render_func(ext, commonmark_render);
    +  cmark_syntax_extension_set_html_render_func(ext, html_render);
    +  cmark_syntax_extension_set_xml_attr_func(ext, xml_attr);
    +
    +  return ext;
    +}
    diff --git a/extensions/tasklist.h b/extensions/tasklist.h
    new file mode 100644
    index 000000000..26e9d96d2
    --- /dev/null
    +++ b/extensions/tasklist.h
    @@ -0,0 +1,8 @@
    +#ifndef TASKLIST_H
    +#define TASKLIST_H
    +
    +#include "cmark-gfm-core-extensions.h"
    +
    +cmark_syntax_extension *create_tasklist_extension(void);
    +
    +#endif
    diff --git a/man/CMakeLists.txt b/man/CMakeLists.txt
    index e0acd7544..d0c5b6066 100644
    --- a/man/CMakeLists.txt
    +++ b/man/CMakeLists.txt
    @@ -2,9 +2,9 @@ if (NOT MSVC)
     
     include(GNUInstallDirs)
     
    -  install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man1/cmark.1
    +  install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man1/cmark-gfm.1
         DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
     
    -  install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man3/cmark.3
    +  install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man3/cmark-gfm.3
         DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
     endif(NOT MSVC)
    diff --git a/man/make_man_page.py b/man/make_man_page.py
    index 4b49dbd3b..d95620252 100644
    --- a/man/make_man_page.py
    +++ b/man/make_man_page.py
    @@ -21,9 +21,9 @@
     sysname = platform.system()
     
     if sysname == 'Darwin':
    -    cmark = CDLL("build/src/libcmark.dylib")
    +    cmark = CDLL("build/src/libcmark-gfm.dylib")
     else:
    -    cmark = CDLL("build/src/libcmark.so")
    +    cmark = CDLL("build/src/libcmark-gfm.so")
     
     parse_document = cmark.cmark_parse_document
     parse_document.restype = c_void_p
    @@ -46,9 +46,9 @@ def md2man(text):
     comment_start_re = re.compile('^\/\*\* ?')
     comment_delim_re = re.compile('^[/ ]\** ?')
     comment_end_re = re.compile('^ \**\/')
    -function_re = re.compile('^ *(?:CMARK_EXPORT\s+)?(?P(?:const\s+)?\w+(?:\s*[*])?)\s*(?P\w+)\s*\((?P[^)]*)\)')
    +function_re = re.compile('^ *(?:CMARK_GFM_EXPORT\s+)?(?P(?:const\s+)?\w+(?:\s*[*])?)\s*(?P\w+)\s*\((?P[^)]*)\)')
     blank_re = re.compile('^\s*$')
    -macro_re = re.compile('CMARK_EXPORT *')
    +macro_re = re.compile('CMARK_GFM_EXPORT *')
     typedef_start_re = re.compile('typedef.*{$')
     typedef_end_re = re.compile('}')
     single_quote_re = re.compile("(?
    +#include 
    +#include 
    +#include "cmark-gfm.h"
    +#include "cmark-gfm-extension_api.h"
    +#include "mutex.h"
    +
    +CMARK_DEFINE_LOCK(arena)
    +
    +static struct arena_chunk {
    +  size_t sz, used;
    +  uint8_t push_point;
    +  void *ptr;
    +  struct arena_chunk *prev;
    +} *A = NULL;
    +
    +static struct arena_chunk *alloc_arena_chunk(size_t sz, struct arena_chunk *prev) {
    +  struct arena_chunk *c = (struct arena_chunk *)calloc(1, sizeof(*c));
    +  if (!c)
    +    abort();
    +  c->sz = sz;
    +  c->ptr = calloc(1, sz);
    +  if (!c->ptr)
    +    abort();
    +  c->prev = prev;
    +  return c;
    +}
    +
    +void cmark_arena_push(void) {
    +  CMARK_INITIALIZE_AND_LOCK(arena);
    +  if (A) {
    +    A->push_point = 1;
    +    A = alloc_arena_chunk(10240, A);
    +  }
    +  CMARK_UNLOCK(arena);
    +}
    +
    +int cmark_arena_pop(void) {
    +  int ret = 1;
    +  CMARK_INITIALIZE_AND_LOCK(arena);
    +  if (!A)
    +    ret = 0;
    +  else {
    +    while (A && !A->push_point) {
    +      free(A->ptr);
    +      struct arena_chunk *n = A->prev;
    +      free(A);
    +      A = n;
    +    }
    +    if (A)
    +      A->push_point = 0;
    +  }
    +  CMARK_UNLOCK(arena);
    +  return ret;
    +}
    +
    +static void init_arena(void) {
    +  CMARK_INITIALIZE_AND_LOCK(arena);
    +  A = alloc_arena_chunk(4 * 1048576, NULL);
    +  CMARK_UNLOCK(arena);
    +}
    +
    +void cmark_arena_reset(void) {
    +  CMARK_INITIALIZE_AND_LOCK(arena);
    +  while (A) {
    +    free(A->ptr);
    +    struct arena_chunk *n = A->prev;
    +    free(A);
    +    A = n;
    +  }
    +  CMARK_UNLOCK(arena);
    +}
    +
    +static void *arena_calloc(size_t nmem, size_t size) {
    +  if (!A)
    +    init_arena();
    +
    +  size_t sz = nmem * size + sizeof(size_t);
    +
    +  // Round allocation sizes to largest integer size to
    +  // ensure returned memory is correctly aligned
    +  const size_t align = sizeof(size_t) - 1;
    +  sz = (sz + align) & ~align;
    +
    +  CMARK_INITIALIZE_AND_LOCK(arena);
    +
    +  void *ptr = NULL;
    +
    +  if (sz > A->sz) {
    +    A->prev = alloc_arena_chunk(sz, A->prev);
    +    ptr = (uint8_t *) A->prev->ptr;
    +  } else {
    +    if (sz > A->sz - A->used) {
    +      A = alloc_arena_chunk(A->sz + A->sz / 2, A);
    +    }
    +    ptr = (uint8_t *) A->ptr + A->used;
    +    A->used += sz;
    +    *((size_t *) ptr) = sz - sizeof(size_t);
    +  }
    +  
    +  CMARK_UNLOCK(arena);
    +
    +  return (uint8_t *) ptr + sizeof(size_t);
    +}
    +
    +static void *arena_realloc(void *ptr, size_t size) {
    +  if (!A)
    +    init_arena();
    +
    +  void *new_ptr = arena_calloc(1, size);
    +  if (ptr)
    +    memcpy(new_ptr, ptr, ((size_t *) ptr)[-1]);
    +  return new_ptr;
    +}
    +
    +static void arena_free(void *ptr) {
    +  (void) ptr;
    +  /* no-op */
    +}
    +
    +cmark_mem CMARK_ARENA_MEM_ALLOCATOR = {arena_calloc, arena_realloc, arena_free};
    +
    +cmark_mem *cmark_get_arena_mem_allocator() {
    +  return &CMARK_ARENA_MEM_ALLOCATOR;
    +}
    diff --git a/src/blocks.c b/src/blocks.c
    index b6077eb96..6e87f19cb 100644
    --- a/src/blocks.c
    +++ b/src/blocks.c
    @@ -10,9 +10,10 @@
     #include 
     
     #include "cmark_ctype.h"
    -#include "config.h"
    +#include "syntax_extension.h"
    +#include "cmark-gfm_config.h"
     #include "parser.h"
    -#include "cmark.h"
    +#include "cmark-gfm.h"
     #include "node.h"
     #include "references.h"
     #include "utf8.h"
    @@ -20,6 +21,7 @@
     #include "inlines.h"
     #include "houdini.h"
     #include "buffer.h"
    +#include "footnotes.h"
     
     #define CODE_INDENT 4
     #define TAB_STOP 4
    @@ -65,7 +67,7 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
                               size_t len, bool eof);
     
     static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
    -                           bufsize_t bytes);
    +                           bufsize_t bytes, bool ensureEndsInNewline);
     
     static cmark_node *make_block(cmark_mem *mem, cmark_node_type tag,
                                   int start_line, int start_column) {
    @@ -88,44 +90,94 @@ static cmark_node *make_document(cmark_mem *mem) {
       return e;
     }
     
    -cmark_parser *cmark_parser_new_with_mem(int options, cmark_mem *mem) {
    -  cmark_parser *parser = (cmark_parser *)mem->calloc(1, sizeof(cmark_parser));
    -  parser->mem = mem;
    +int cmark_parser_attach_syntax_extension(cmark_parser *parser,
    +                                         cmark_syntax_extension *extension) {
    +  parser->syntax_extensions = cmark_llist_append(parser->mem, parser->syntax_extensions, extension);
    +  if (extension->match_inline || extension->insert_inline_from_delim) {
    +    if (!parser->inline_syntax_extensions) {
    +      // if we're loading an inline extension into this parser for the first time,
    +      // allocate new buffers for the inline parser character arrays
    +      parser->skip_chars = (int8_t *)parser->mem->calloc(sizeof(int8_t), 256);
    +      cmark_set_default_skip_chars(&parser->skip_chars, true);
    +
    +      parser->special_chars = (int8_t *)parser->mem->calloc(sizeof(int8_t), 256);
    +      cmark_set_default_special_chars(&parser->special_chars, true);
    +    }
    +
    +    parser->inline_syntax_extensions = cmark_llist_append(
    +      parser->mem, parser->inline_syntax_extensions, extension);
    +  }
    +
    +  return 1;
    +}
    +
    +static void cmark_parser_dispose(cmark_parser *parser) {
    +  if (parser->root)
    +    cmark_node_free(parser->root);
    +
    +  if (parser->refmap)
    +    cmark_map_free(parser->refmap);
    +}
    +
    +static void cmark_parser_reset(cmark_parser *parser) {
    +  cmark_llist *saved_exts = parser->syntax_extensions;
    +  cmark_llist *saved_inline_exts = parser->inline_syntax_extensions;
    +  int saved_options = parser->options;
    +  cmark_mem *saved_mem = parser->mem;
    +  int8_t *saved_specials = parser->special_chars;
    +  int8_t *saved_skips = parser->skip_chars;
    +
    +  cmark_parser_dispose(parser);
     
    -  cmark_node *document = make_document(mem);
    +  memset(parser, 0, sizeof(cmark_parser));
    +  parser->mem = saved_mem;
     
    -  cmark_strbuf_init(mem, &parser->curline, 256);
    -  cmark_strbuf_init(mem, &parser->linebuf, 0);
    +  cmark_strbuf_init(parser->mem, &parser->curline, 256);
    +  cmark_strbuf_init(parser->mem, &parser->linebuf, 0);
     
    -  parser->refmap = cmark_reference_map_new(mem);
    +  cmark_node *document = make_document(parser->mem);
    +
    +  parser->refmap = cmark_reference_map_new(parser->mem);
       parser->root = document;
       parser->current = document;
    -  parser->line_number = 0;
    -  parser->offset = 0;
    -  parser->column = 0;
    -  parser->first_nonspace = 0;
    -  parser->first_nonspace_column = 0;
    -  parser->thematic_break_kill_pos = 0;
    -  parser->indent = 0;
    -  parser->blank = false;
    -  parser->partially_consumed_tab = false;
    -  parser->last_line_length = 0;
    -  parser->options = options;
    -  parser->last_buffer_ended_with_cr = false;
     
    +  parser->syntax_extensions = saved_exts;
    +  parser->inline_syntax_extensions = saved_inline_exts;
    +  parser->options = saved_options;
    +
    +  parser->special_chars = saved_specials;
    +  parser->skip_chars = saved_skips;
    +}
    +
    +cmark_parser *cmark_parser_new_with_mem(int options, cmark_mem *mem) {
    +  cmark_parser *parser = (cmark_parser *)mem->calloc(1, sizeof(cmark_parser));
    +  parser->mem = mem;
    +  parser->options = options;
    +  cmark_set_default_skip_chars(&parser->skip_chars, false);
    +  cmark_set_default_special_chars(&parser->special_chars, false);
    +  cmark_parser_reset(parser);
       return parser;
     }
     
     cmark_parser *cmark_parser_new(int options) {
    -  extern cmark_mem DEFAULT_MEM_ALLOCATOR;
    -  return cmark_parser_new_with_mem(options, &DEFAULT_MEM_ALLOCATOR);
    +  extern cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR;
    +  return cmark_parser_new_with_mem(options, &CMARK_DEFAULT_MEM_ALLOCATOR);
     }
     
     void cmark_parser_free(cmark_parser *parser) {
       cmark_mem *mem = parser->mem;
    +
    +  // If any inline syntax extensions were added, free the memory allocated for the special-chars arrays
    +  if (parser->inline_syntax_extensions) {
    +    mem->free(parser->special_chars);
    +    mem->free(parser->skip_chars);
    +  }
    +
    +  cmark_parser_dispose(parser);
       cmark_strbuf_free(&parser->curline);
       cmark_strbuf_free(&parser->linebuf);
    -  cmark_reference_map_free(parser->refmap);
    +  cmark_llist_free(parser->mem, parser->syntax_extensions);
    +  cmark_llist_free(parser->mem, parser->inline_syntax_extensions);
       mem->free(parser);
     }
     
    @@ -152,23 +204,19 @@ static bool is_blank(cmark_strbuf *s, bufsize_t offset) {
       return true;
     }
     
    -static CMARK_INLINE bool can_contain(cmark_node_type parent_type,
    -                                     cmark_node_type child_type) {
    -  return (parent_type == CMARK_NODE_DOCUMENT ||
    -          parent_type == CMARK_NODE_BLOCK_QUOTE ||
    -          parent_type == CMARK_NODE_ITEM ||
    -          (parent_type == CMARK_NODE_LIST && child_type == CMARK_NODE_ITEM));
    -}
    -
     static CMARK_INLINE bool accepts_lines(cmark_node_type block_type) {
       return (block_type == CMARK_NODE_PARAGRAPH ||
               block_type == CMARK_NODE_HEADING ||
               block_type == CMARK_NODE_CODE_BLOCK);
     }
     
    -static CMARK_INLINE bool contains_inlines(cmark_node_type block_type) {
    -  return (block_type == CMARK_NODE_PARAGRAPH ||
    -          block_type == CMARK_NODE_HEADING);
    +static CMARK_INLINE bool contains_inlines(cmark_node *node) {
    +  if (node->extension && node->extension->contains_inlines_func) {
    +    return node->extension->contains_inlines_func(node->extension, node) != 0;
    +  }
    +
    +  return (node->type == CMARK_NODE_PARAGRAPH ||
    +          node->type == CMARK_NODE_HEADING);
     }
     
     static void add_line(cmark_node *node, cmark_chunk *ch, cmark_parser *parser) {
    @@ -236,9 +284,10 @@ static bool resolve_reference_link_definitions(
       bufsize_t pos;
       cmark_strbuf *node_content = &b->content;
       cmark_chunk chunk = {node_content->ptr, node_content->size, 0};
    -  while (chunk.len && chunk.data[0] == '[' &&
    -         (pos = cmark_parse_reference_inline(parser->mem, &chunk,
    -					     parser->refmap))) {
    +  while ((chunk.len && chunk.data[0] == '[' &&
    +            (pos = cmark_parse_reference_inline(parser->mem, &chunk, parser->refmap))) ||
    +         (chunk.len && chunk.data[0] == '^' && chunk.data[1] == '[' &&
    +            (pos = cmark_parse_reference_attributes_inline(parser->mem, &chunk, parser->refmap)))) {
     
         chunk.data += pos;
         chunk.len -= pos;
    @@ -265,7 +314,8 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
         b->end_column = parser->last_line_length;
       } else if (S_type(b) == CMARK_NODE_DOCUMENT ||
                  (S_type(b) == CMARK_NODE_CODE_BLOCK && b->as.code.fenced) ||
    -             (S_type(b) == CMARK_NODE_HEADING && b->as.heading.setext)) {
    +             (S_type(b) == CMARK_NODE_HEADING && b->as.heading.setext) ||
    +             (parser->line_number - 1 < b->end_line)) {
         b->end_line = parser->line_number;
         b->end_column = parser->curline.size;
         if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\n')
    @@ -283,7 +333,7 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
       case CMARK_NODE_PARAGRAPH:
       {
         has_content = resolve_reference_link_definitions(parser, b);
    -    if (!has_content) {
    +    if (!has_content && (parser->options & CMARK_OPT_PRESERVE_WHITESPACE) == 0) {
           // remove blank node (former reference def)
           cmark_node_free(b);
         }
    @@ -364,7 +414,7 @@ static cmark_node *add_child(cmark_parser *parser, cmark_node *parent,
     
       // if 'parent' isn't the kind of node that can accept this child,
       // then back up til we hit a node that can.
    -  while (!can_contain(S_type(parent), block_type)) {
    +  while (!cmark_node_can_contain_type(parent, block_type)) {
         parent = finalize(parser, parent);
       }
     
    @@ -383,26 +433,124 @@ static cmark_node *add_child(cmark_parser *parser, cmark_node *parent,
       return child;
     }
     
    +void cmark_manage_extensions_special_characters(cmark_parser *parser, int add) {
    +  cmark_llist *tmp_ext;
    +
    +  for (tmp_ext = parser->inline_syntax_extensions; tmp_ext; tmp_ext=tmp_ext->next) {
    +    cmark_syntax_extension *ext = (cmark_syntax_extension *) tmp_ext->data;
    +    cmark_llist *tmp_char;
    +    for (tmp_char = ext->special_inline_chars; tmp_char; tmp_char=tmp_char->next) {
    +      unsigned char c = (unsigned char)(size_t)tmp_char->data;
    +      if (add)
    +        cmark_inlines_add_special_character(parser, c, ext->emphasis);
    +      else
    +        cmark_inlines_remove_special_character(parser, c, ext->emphasis);
    +    }
    +  }
    +}
    +
     // Walk through node and all children, recursively, parsing
     // string content into inline content where appropriate.
    -static void process_inlines(cmark_mem *mem, cmark_node *root,
    -                            cmark_reference_map *refmap, int options) {
    -  cmark_iter *iter = cmark_iter_new(root);
    +static void process_inlines(cmark_parser *parser,
    +                            cmark_map *refmap, int options) {
    +  cmark_iter *iter = cmark_iter_new(parser->root);
       cmark_node *cur;
       cmark_event_type ev_type;
     
    +  cmark_manage_extensions_special_characters(parser, true);
    +
       while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
         cur = cmark_iter_get_node(iter);
         if (ev_type == CMARK_EVENT_ENTER) {
    -      if (contains_inlines(S_type(cur))) {
    -        cmark_parse_inlines(mem, cur, refmap, options);
    +      if (contains_inlines(cur)) {
    +        cmark_parse_inlines(parser, cur, refmap, options);
           }
         }
       }
     
    +  cmark_manage_extensions_special_characters(parser, false);
    +
       cmark_iter_free(iter);
     }
     
    +static int sort_footnote_by_ix(const void *_a, const void *_b) {
    +  cmark_footnote *a = *(cmark_footnote **)_a;
    +  cmark_footnote *b = *(cmark_footnote **)_b;
    +  return (int)a->ix - (int)b->ix;
    +}
    +
    +static void process_footnotes(cmark_parser *parser) {
    +  // * Collect definitions in a map.
    +  // * Iterate the references in the document in order, assigning indices to
    +  //   definitions in the order they're seen.
    +  // * Write out the footnotes at the bottom of the document in index order.
    +
    +  cmark_map *map = cmark_footnote_map_new(parser->mem);
    +
    +  cmark_iter *iter = cmark_iter_new(parser->root);
    +  cmark_node *cur;
    +  cmark_event_type ev_type;
    +
    +  while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
    +    cur = cmark_iter_get_node(iter);
    +    if (ev_type == CMARK_EVENT_EXIT && cur->type == CMARK_NODE_FOOTNOTE_DEFINITION) {
    +      cmark_node_unlink(cur);
    +      cmark_footnote_create(map, cur);
    +    }
    +  }
    +
    +  cmark_iter_free(iter);
    +  iter = cmark_iter_new(parser->root);
    +  unsigned int ix = 0;
    +
    +  while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
    +    cur = cmark_iter_get_node(iter);
    +    if (ev_type == CMARK_EVENT_EXIT && cur->type == CMARK_NODE_FOOTNOTE_REFERENCE) {
    +      cmark_footnote *footnote = (cmark_footnote *)cmark_map_lookup(map, &cur->as.literal);
    +      if (footnote) {
    +        if (!footnote->ix)
    +          footnote->ix = ++ix;
    +
    +        char n[32];
    +        snprintf(n, sizeof(n), "%d", footnote->ix);
    +        cmark_chunk_free(parser->mem, &cur->as.literal);
    +        cmark_strbuf buf = CMARK_BUF_INIT(parser->mem);
    +        cmark_strbuf_puts(&buf, n);
    +
    +        cur->as.literal = cmark_chunk_buf_detach(&buf);
    +      } else {
    +        cmark_node *text = (cmark_node *)parser->mem->calloc(1, sizeof(*text));
    +        cmark_strbuf_init(parser->mem, &text->content, 0);
    +        text->type = (uint16_t) CMARK_NODE_TEXT;
    +
    +        cmark_strbuf buf = CMARK_BUF_INIT(parser->mem);
    +        cmark_strbuf_puts(&buf, "[^");
    +        cmark_strbuf_put(&buf, cur->as.literal.data, cur->as.literal.len);
    +        cmark_strbuf_putc(&buf, ']');
    +
    +        text->as.literal = cmark_chunk_buf_detach(&buf);
    +        cmark_node_insert_after(cur, text);
    +        cmark_node_free(cur);
    +      }
    +    }
    +  }
    +
    +  cmark_iter_free(iter);
    +
    +  if (map->sorted) {
    +    qsort(map->sorted, map->size, sizeof(cmark_map_entry *), sort_footnote_by_ix);
    +    for (unsigned int i = 0; i < map->size; ++i) {
    +      cmark_footnote *footnote = (cmark_footnote *)map->sorted[i];
    +      if (!footnote->ix)
    +        continue;
    +      cmark_node_append_child(parser->root, footnote->node);
    +      footnote->node = NULL;
    +    }
    +  }
    +
    +  cmark_map_free(map);
    +}
    +
     // 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.
    @@ -506,7 +654,9 @@ static cmark_node *finalize_document(cmark_parser *parser) {
       }
     
       finalize(parser, parser->root);
    -  process_inlines(parser->mem, parser->root, parser->refmap, parser->options);
    +  process_inlines(parser, parser->refmap, parser->options);
    +  if (parser->options & CMARK_OPT_FOOTNOTES)
    +    process_footnotes(parser);
     
       return parser->root;
     }
    @@ -545,10 +695,24 @@ void cmark_parser_feed(cmark_parser *parser, const char *buffer, size_t len) {
       S_parser_feed(parser, (const unsigned char *)buffer, len, false);
     }
     
    +void cmark_parser_feed_reentrant(cmark_parser *parser, const char *buffer, size_t len) {
    +  cmark_strbuf saved_linebuf;
    +
    +  cmark_strbuf_init(parser->mem, &saved_linebuf, 0);
    +  cmark_strbuf_puts(&saved_linebuf, cmark_strbuf_cstr(&parser->linebuf));
    +  cmark_strbuf_clear(&parser->linebuf);
    +
    +  S_parser_feed(parser, (const unsigned char *)buffer, len, true);
    +
    +  cmark_strbuf_sets(&parser->linebuf, cmark_strbuf_cstr(&saved_linebuf));
    +  cmark_strbuf_free(&saved_linebuf);
    +}
    +
     static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
                               size_t len, bool eof) {
       const unsigned char *end = buffer + len;
       static const uint8_t repl[] = {239, 191, 189};
    +  bool preserveWhitespace = parser->options & CMARK_OPT_PRESERVE_WHITESPACE;
     
       if (parser->last_buffer_ended_with_cr && *buffer == '\n') {
         // skip NL if last buffer ended with CR ; see #117
    @@ -572,14 +736,14 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
           process = true;
         }
     
    -    chunk_len = (eol - buffer);
    +    chunk_len = (bufsize_t)(eol - buffer);
         if (process) {
           if (parser->linebuf.size > 0) {
             cmark_strbuf_put(&parser->linebuf, buffer, chunk_len);
    -        S_process_line(parser, parser->linebuf.ptr, parser->linebuf.size);
    +        S_process_line(parser, parser->linebuf.ptr, parser->linebuf.size, !preserveWhitespace || !eof || eol < end);
             cmark_strbuf_clear(&parser->linebuf);
           } else {
    -        S_process_line(parser, buffer, chunk_len);
    +        S_process_line(parser, buffer, chunk_len, !preserveWhitespace || !eof || eol < end);
           }
         } else {
           if (eol < end && *eol == '\0') {
    @@ -756,6 +920,18 @@ static bool parse_block_quote_prefix(cmark_parser *parser, cmark_chunk *input) {
       return res;
     }
     
    +static bool parse_footnote_definition_block_prefix(cmark_parser *parser, cmark_chunk *input,
    +                                                   cmark_node *container) {
    +  if (parser->indent >= 4) {
    +    S_advance_offset(parser, input, 4, true);
    +    return true;
    +  } else if (input->len > 0 && (input->data[0] == '\n' || (input->data[0] == '\r' && input->data[1] == '\n'))) {
    +    return true;
    +  }
    +
    +  return false;
    +}
    +
     static bool parse_node_item_prefix(cmark_parser *parser, cmark_chunk *input,
                                        cmark_node *container) {
       bool res = false;
    @@ -844,6 +1020,21 @@ static bool parse_html_block_prefix(cmark_parser *parser,
       return res;
     }
     
    +static bool parse_extension_block(cmark_parser *parser,
    +                                  cmark_node *container,
    +                                  cmark_chunk *input)
    +{
    +  bool res = false;
    +
    +  if (container->extension->last_block_matches) {
    +    if (container->extension->last_block_matches(
    +        container->extension, parser, input->data, input->len, container))
    +      res = true;
    +  }
    +
    +  return res;
    +}
    +
     /**
      * For each containing node, try to parse the associated line start.
      *
    @@ -858,6 +1049,8 @@ static cmark_node *check_open_blocks(cmark_parser *parser, cmark_chunk *input,
       *all_matched = false;
       cmark_node *container = parser->root;
       cmark_node_type cont_type;
    +    
    +    
     
       while (S_last_child_is_open(container)) {
         container = container->last_child;
    @@ -865,6 +1058,12 @@ static cmark_node *check_open_blocks(cmark_parser *parser, cmark_chunk *input,
     
         S_find_first_nonspace(parser, input);
     
    +    if (container->extension) {
    +      if (!parse_extension_block(parser, container, input))
    +        goto done;
    +      continue;
    +    }
    +
         switch (cont_type) {
         case CMARK_NODE_BLOCK_QUOTE:
           if (!parse_block_quote_prefix(parser, input))
    @@ -889,6 +1088,10 @@ static cmark_node *check_open_blocks(cmark_parser *parser, cmark_chunk *input,
           if (parser->blank)
             goto done;
           break;
    +		case CMARK_NODE_FOOTNOTE_DEFINITION:
    +			if (!parse_footnote_definition_block_prefix(parser, input, container))
    +				goto done;
    +			break;
         default:
           break;
         }
    @@ -969,7 +1172,7 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
                                  parser->first_nonspace + 1);
           (*container)->as.code.fenced = true;
           (*container)->as.code.fence_char = peek_at(input, parser->first_nonspace);
    -      (*container)->as.code.fence_length = (matched > 255) ? 255 : matched;
    +      (*container)->as.code.fence_length = (matched > 255) ? 255 : (uint8_t)matched;
           (*container)->as.code.fence_offset =
               (int8_t)(parser->first_nonspace - parser->offset);
           (*container)->as.code.info = cmark_chunk_literal("");
    @@ -1008,6 +1211,21 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
           *container = add_child(parser, *container, CMARK_NODE_THEMATIC_BREAK,
                                  parser->first_nonspace + 1);
           S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
    +    } else if (!indented &&
    +               parser->options & CMARK_OPT_FOOTNOTES &&
    +               (matched = scan_footnote_definition(input, parser->first_nonspace))) {
    +      cmark_chunk c = cmark_chunk_dup(input, parser->first_nonspace + 2, matched - 2);
    +      cmark_chunk_to_cstr(parser->mem, &c);
    +
    +      while (c.data[c.len - 1] != ']')
    +        --c.len;
    +      --c.len;
    +
    +      S_advance_offset(parser, input, parser->first_nonspace + matched - parser->offset, false);
    +      *container = add_child(parser, *container, CMARK_NODE_FOOTNOTE_DEFINITION, parser->first_nonspace + matched + 1);
    +      (*container)->as.literal = c;
    +
    +      (*container)->internal_offset = matched;
         } else if ((!indented || cont_type == CMARK_NODE_LIST) &&
     	       parser->indent < 4 &&
                    (matched = parse_list_marker(
    @@ -1075,9 +1293,27 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
           (*container)->as.code.fence_length = 0;
           (*container)->as.code.fence_offset = 0;
           (*container)->as.code.info = cmark_chunk_literal("");
    -
         } else {
    -      break;
    +      cmark_llist *tmp;
    +      cmark_node *new_container = NULL;
    +
    +      for (tmp = parser->syntax_extensions; tmp; tmp=tmp->next) {
    +        cmark_syntax_extension *ext = (cmark_syntax_extension *) tmp->data;
    +
    +        if (ext->try_opening_block) {
    +          new_container = ext->try_opening_block(
    +              ext, indented, parser, *container, input->data, input->len);
    +
    +          if (new_container) {
    +            *container = new_container;
    +            break;
    +          }
    +        }
    +      }
    +
    +      if (!new_container) {
    +        break;
    +      }
         }
     
         if (accepts_lines(S_type(*container))) {
    @@ -1129,7 +1365,7 @@ static void add_text_to_container(cmark_parser *parser, cmark_node *container,
       // then treat this as a "lazy continuation line" and add it to
       // the open paragraph.
       if (parser->current != last_matched_container &&
    -      container == last_matched_container && !parser->blank &&
    +      container == last_matched_container && (!parser->blank || (parser->options & CMARK_OPT_PRESERVE_WHITESPACE)) &&
           S_type(parser->current) == CMARK_NODE_PARAGRAPH) {
         add_line(parser->current, input, parser);
       } else { // not a lazy continuation
    @@ -1180,22 +1416,28 @@ static void add_text_to_container(cmark_parser *parser, cmark_node *container,
             container = finalize(parser, container);
             assert(parser->current != NULL);
           }
    -    } else if (parser->blank) {
    +    } else if (parser->blank && (parser->options & CMARK_OPT_PRESERVE_WHITESPACE) == 0) {
           // ??? do nothing
         } else if (accepts_lines(S_type(container))) {
           if (S_type(container) == CMARK_NODE_HEADING &&
               container->as.heading.setext == false) {
             chop_trailing_hashtags(input);
           }
    -      S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
    +      if ((parser->options & CMARK_OPT_PRESERVE_WHITESPACE) == 0)
    +        S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
                            false);
           add_line(container, input, parser);
         } else {
           // create paragraph container for line
    -      container = add_child(parser, container, CMARK_NODE_PARAGRAPH,
    -                            parser->first_nonspace + 1);
    -      S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
    -                       false);
    +      if (parser->options & CMARK_OPT_PRESERVE_WHITESPACE) {
    +        container = add_child(parser, container, CMARK_NODE_PARAGRAPH,
    +                              parser->offset + 1);
    +      } else {
    +        container = add_child(parser, container, CMARK_NODE_PARAGRAPH,
    +                              parser->first_nonspace + 1);
    +        S_advance_offset(parser, input, parser->first_nonspace - parser->offset,
    +                           false);
    +      }
           add_line(container, input, parser);
         }
     
    @@ -1205,11 +1447,14 @@ static void add_text_to_container(cmark_parser *parser, cmark_node *container,
     
     /* See http://spec.commonmark.org/0.24/#phase-1-block-structure */
     static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
    -                           bufsize_t bytes) {
    +                           bufsize_t bytes, bool ensureEndsInNewline) {
       cmark_node *last_matched_container;
       bool all_matched = true;
       cmark_node *container;
       cmark_chunk input;
    +  cmark_node *current;
    +
    +  cmark_strbuf_clear(&parser->curline);
     
       if (parser->options & CMARK_OPT_VALIDATE_UTF8)
         cmark_utf8proc_check(&parser->curline, buffer, bytes);
    @@ -1219,7 +1464,7 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
       bytes = parser->curline.size;
     
       // ensure line ends with a newline:
    -  if (bytes == 0 || !S_is_line_end_char(parser->curline.ptr[bytes - 1]))
    +  if (ensureEndsInNewline && (bytes == 0 || !S_is_line_end_char(parser->curline.ptr[bytes - 1])))
         cmark_strbuf_putc(&parser->curline, '\n');
     
       parser->offset = 0;
    @@ -1235,6 +1480,12 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
       input.len = parser->curline.size;
       input.alloc = 0;
     
    +  // Skip UTF-8 BOM.
    +  if (parser->line_number == 0 &&
    +      input.len >= 3 &&
    +      memcmp(input.data, "\xef\xbb\xbf", 3) == 0)
    +    parser->offset += 3;
    +
       parser->line_number++;
     
       last_matched_container = check_open_blocks(parser, &input, &all_matched);
    @@ -1244,8 +1495,14 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
     
       container = last_matched_container;
     
    -  open_new_blocks(parser, &container, &input, all_matched);
    +  current = parser->current;
     
    +  // Only open new blocks if we're not limited to inline
    +  if ((parser->options & CMARK_OPT_INLINE_ONLY) == 0)
    +    open_new_blocks(parser, &container, &input, all_matched);
    +
    +  /* parser->current might have changed if feed_reentrant was called */
    +  if (current == parser->current)
       add_text_to_container(parser, container, last_matched_container, &input);
     
     finished:
    @@ -1261,8 +1518,15 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
     }
     
     cmark_node *cmark_parser_finish(cmark_parser *parser) {
    +  cmark_node *res;
    +  cmark_llist *extensions;
    +
    +  /* Parser was already finished once */
    +  if (parser->root == NULL)
    +    return NULL;
    +
       if (parser->linebuf.size) {
    -    S_process_line(parser, parser->linebuf.ptr, parser->linebuf.size);
    +    S_process_line(parser, parser->linebuf.ptr, parser->linebuf.size, (parser->options & CMARK_OPT_PRESERVE_WHITESPACE) == 0);
         cmark_strbuf_clear(&parser->linebuf);
       }
     
    @@ -1271,11 +1535,88 @@ cmark_node *cmark_parser_finish(cmark_parser *parser) {
       cmark_consolidate_text_nodes(parser->root);
     
       cmark_strbuf_free(&parser->curline);
    +  cmark_strbuf_free(&parser->linebuf);
     
     #if CMARK_DEBUG_NODES
       if (cmark_node_check(parser->root, stderr)) {
         abort();
       }
     #endif
    -  return parser->root;
    +
    +  for (extensions = parser->syntax_extensions; extensions; extensions = extensions->next) {
    +    cmark_syntax_extension *ext = (cmark_syntax_extension *) extensions->data;
    +    if (ext->postprocess_func) {
    +      cmark_node *processed = ext->postprocess_func(ext, parser, parser->root);
    +      if (processed)
    +        parser->root = processed;
    +    }
    +  }
    +
    +  res = parser->root;
    +  parser->root = NULL;
    +
    +  cmark_parser_reset(parser);
    +
    +  return res;
    +}
    +
    +int cmark_parser_get_line_number(cmark_parser *parser) {
    +  return parser->line_number;
    +}
    +
    +bufsize_t cmark_parser_get_offset(cmark_parser *parser) {
    +  return parser->offset;
    +}
    +
    +bufsize_t cmark_parser_get_column(cmark_parser *parser) {
    +  return parser->column;
    +}
    +
    +int cmark_parser_get_first_nonspace(cmark_parser *parser) {
    +  return parser->first_nonspace;
    +}
    +
    +int cmark_parser_get_first_nonspace_column(cmark_parser *parser) {
    +  return parser->first_nonspace_column;
    +}
    +
    +int cmark_parser_get_indent(cmark_parser *parser) {
    +  return parser->indent;
    +}
    +
    +int cmark_parser_is_blank(cmark_parser *parser) {
    +  return parser->blank;
    +}
    +
    +int cmark_parser_has_partially_consumed_tab(cmark_parser *parser) {
    +  return parser->partially_consumed_tab;
    +}
    +
    +int cmark_parser_get_last_line_length(cmark_parser *parser) {
    +  return parser->last_line_length;
    +}
    +
    +cmark_node *cmark_parser_add_child(cmark_parser *parser,
    +                                   cmark_node   *parent,
    +                                   cmark_node_type block_type,
    +                                   int start_column) {
    +  return add_child(parser, parent, block_type, start_column);
    +}
    +
    +void cmark_parser_advance_offset(cmark_parser *parser,
    +                                 const char *input,
    +                                 int count,
    +                                 int columns) {
    +  cmark_chunk input_chunk = cmark_chunk_literal(input);
    +
    +  S_advance_offset(parser, &input_chunk, count, columns != 0);
    +}
    +
    +void cmark_parser_set_backslash_ispunct_func(cmark_parser *parser,
    +                                             cmark_ispunct_func func) {
    +  parser->backslash_ispunct = func;
    +}
    +
    +cmark_llist *cmark_parser_get_syntax_extensions(cmark_parser *parser) {
    +  return parser->syntax_extensions;
     }
    diff --git a/src/buffer.c b/src/buffer.c
    index d94649310..df6873731 100644
    --- a/src/buffer.c
    +++ b/src/buffer.c
    @@ -7,7 +7,7 @@
     #include 
     #include 
     
    -#include "config.h"
    +#include "cmark-gfm_config.h"
     #include "cmark_ctype.h"
     #include "buffer.h"
     
    @@ -95,7 +95,7 @@ void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data,
     
     void cmark_strbuf_sets(cmark_strbuf *buf, const char *string) {
       cmark_strbuf_set(buf, (const unsigned char *)string,
    -                   string ? strlen(string) : 0);
    +                   string ? (bufsize_t)strlen(string) : 0);
     }
     
     void cmark_strbuf_putc(cmark_strbuf *buf, int c) {
    @@ -116,7 +116,7 @@ void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data,
     }
     
     void cmark_strbuf_puts(cmark_strbuf *buf, const char *string) {
    -  cmark_strbuf_put(buf, (const unsigned char *)string, strlen(string));
    +  cmark_strbuf_put(buf, (const unsigned char *)string, (bufsize_t)strlen(string));
     }
     
     void cmark_strbuf_copy_cstr(char *data, bufsize_t datasize,
    diff --git a/src/cmark-gfm_version.h.in b/src/cmark-gfm_version.h.in
    new file mode 100644
    index 000000000..0847d0095
    --- /dev/null
    +++ b/src/cmark-gfm_version.h.in
    @@ -0,0 +1,7 @@
    +#ifndef CMARK_GFM_VERSION_H
    +#define CMARK_GFM_VERSION_H
    +
    +#define CMARK_GFM_VERSION ((@PROJECT_VERSION_MAJOR@ << 24) | (@PROJECT_VERSION_MINOR@ << 16) | (@PROJECT_VERSION_PATCH@ << 8) | @PROJECT_VERSION_GFM@)
    +#define CMARK_GFM_VERSION_STRING "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.gfm.@PROJECT_VERSION_GFM@"
    +
    +#endif
    diff --git a/src/cmark.c b/src/cmark.c
    index d64237f24..08477fa57 100644
    --- a/src/cmark.c
    +++ b/src/cmark.c
    @@ -1,14 +1,18 @@
     #include 
     #include 
     #include 
    +#include "registry.h"
     #include "node.h"
     #include "houdini.h"
    -#include "cmark.h"
    +#include "cmark-gfm.h"
     #include "buffer.h"
     
    -int cmark_version() { return CMARK_VERSION; }
    +cmark_node_type CMARK_NODE_LAST_BLOCK = CMARK_NODE_FOOTNOTE_DEFINITION;
    +cmark_node_type CMARK_NODE_LAST_INLINE = CMARK_NODE_ATTRIBUTE;
     
    -const char *cmark_version_string() { return CMARK_VERSION_STRING; }
    +int cmark_version() { return CMARK_GFM_VERSION; }
    +
    +const char *cmark_version_string() { return CMARK_GFM_VERSION_STRING; }
     
     static void *xcalloc(size_t nmem, size_t size) {
       void *ptr = calloc(nmem, size);
    @@ -28,7 +32,15 @@ static void *xrealloc(void *ptr, size_t size) {
       return new_ptr;
     }
     
    -cmark_mem DEFAULT_MEM_ALLOCATOR = {xcalloc, xrealloc, free};
    +static void xfree(void *ptr) {
    +  free(ptr);
    +}
    +
    +cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR = {xcalloc, xrealloc, xfree};
    +
    +cmark_mem *cmark_get_default_mem_allocator() {
    +  return &CMARK_DEFAULT_MEM_ALLOCATOR;
    +}
     
     char *cmark_markdown_to_html(const char *text, size_t len, int options) {
       cmark_node *doc;
    @@ -36,7 +48,7 @@ char *cmark_markdown_to_html(const char *text, size_t len, int options) {
     
       doc = cmark_parse_document(text, len, options);
     
    -  result = cmark_render_html(doc, options);
    +  result = cmark_render_html(doc, options, NULL);
       cmark_node_free(doc);
     
       return result;
    diff --git a/src/cmark_version.h.in b/src/cmark_version.h.in
    deleted file mode 100644
    index 41de3ac67..000000000
    --- a/src/cmark_version.h.in
    +++ /dev/null
    @@ -1,7 +0,0 @@
    -#ifndef CMARK_VERSION_H
    -#define CMARK_VERSION_H
    -
    -#define CMARK_VERSION ((@PROJECT_VERSION_MAJOR@ << 16) | (@PROJECT_VERSION_MINOR@ << 8)  | @PROJECT_VERSION_PATCH@)
    -#define CMARK_VERSION_STRING "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@"
    -
    -#endif
    diff --git a/src/commonmark.c b/src/commonmark.c
    index 404c2903c..94fd4388f 100644
    --- a/src/commonmark.c
    +++ b/src/commonmark.c
    @@ -4,16 +4,17 @@
     #include 
     #include 
     
    -#include "config.h"
    -#include "cmark.h"
    +#include "cmark-gfm_config.h"
    +#include "cmark-gfm.h"
     #include "node.h"
     #include "buffer.h"
     #include "utf8.h"
     #include "scanners.h"
     #include "render.h"
    +#include "syntax_extension.h"
     
    -#define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping)
    -#define LIT(s) renderer->out(renderer, s, false, LITERAL)
    +#define OUT(s, wrap, escaping) renderer->out(renderer, node, s, wrap, escaping)
    +#define LIT(s) renderer->out(renderer, node, s, false, LITERAL)
     #define CR() renderer->cr(renderer)
     #define BLANKLINE() renderer->blankline(renderer)
     #define ENCODED_SIZE 20
    @@ -21,7 +22,8 @@
     
     // Functions to convert cmark_nodes to commonmark strings.
     
    -static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape,
    +static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_node *node, 
    +                              cmark_escaping escape,
                                   int32_t c, unsigned char nextc) {
       bool needs_escaping = false;
       bool follows_digit =
    @@ -34,8 +36,9 @@ static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape,
           ((escape == NORMAL &&
             (c < 0x20 ||
     	 c == '*' || c == '_' || c == '[' || c == ']' || c == '#' || c == '<' ||
    -         c == '>' || c == '\\' || c == '`' || c == '!' ||
    +         c == '>' || c == '\\' || c == '`' || c == '~' || c == '!' ||
              (c == '&' && cmark_isalpha(nextc)) || (c == '!' && nextc == '[') ||
    +         (c == '^' && nextc == '[') ||
              (renderer->begin_content && (c == '-' || c == '+' || c == '=') &&
               // begin_content doesn't get set to false til we've passed digits
               // at the beginning of line, so...
    @@ -43,24 +46,24 @@ static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape,
              (renderer->begin_content && (c == '.' || c == ')') && follows_digit &&
               (nextc == 0 || cmark_isspace(nextc))))) ||
            (escape == URL &&
    -        (c == '`' || c == '<' || c == '>' || cmark_isspace(c) || c == '\\' ||
    +        (c == '`' || c == '<' || c == '>' || cmark_isspace((char)c) || c == '\\' ||
              c == ')' || c == '(')) ||
            (escape == TITLE &&
             (c == '`' || c == '<' || c == '>' || c == '"' || c == '\\')));
     
       if (needs_escaping) {
    -    if (escape == URL && cmark_isspace(c)) {
    +    if (escape == URL && cmark_isspace((char)c)) {
           // use percent encoding for spaces
           snprintf(encoded, ENCODED_SIZE, "%%%2X", c);
           cmark_strbuf_puts(renderer->buffer, encoded);
           renderer->column += 3;
    -    } else if (cmark_ispunct(c)) {
    +    } else if (cmark_ispunct((char)c)) {
           cmark_render_ascii(renderer, "\\");
           cmark_render_code_point(renderer, c);
         } else { // render as entity
           snprintf(encoded, ENCODED_SIZE, "&#%d;", c);
           cmark_strbuf_puts(renderer->buffer, encoded);
    -      renderer->column += strlen(encoded);
    +      renderer->column += (int)strlen(encoded);
         }
       } else {
         cmark_render_code_point(renderer, c);
    @@ -156,8 +159,7 @@ static bool is_autolink(cmark_node *node) {
     // if there is no block-level ancestor, returns NULL.
     static cmark_node *get_containing_block(cmark_node *node) {
       while (node) {
    -    if (node->type >= CMARK_NODE_FIRST_BLOCK &&
    -        node->type <= CMARK_NODE_LAST_BLOCK) {
    +    if (CMARK_NODE_BLOCK_P(node)) {
           return node;
         } else {
           node = node->parent;
    @@ -198,6 +200,11 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
               cmark_node_get_list_tight(tmp->parent->parent)));
       }
     
    +  if (node->extension && node->extension->commonmark_render_func) {
    +    node->extension->commonmark_render_func(node->extension, renderer, node, ev_type, options);
    +    return 1;
    +  }
    +
       switch (node->type) {
       case CMARK_NODE_DOCUMENT:
         break;
    @@ -241,7 +248,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
           snprintf(listmarker, LISTMARKER_SIZE, "%d%s%s", list_number,
                    list_delim == CMARK_PAREN_DELIM ? ")" : ".",
                    list_number < 10 ? "  " : " ");
    -      marker_width = strlen(listmarker);
    +      marker_width = (bufsize_t)strlen(listmarker);
         }
         if (entering) {
           if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
    @@ -468,6 +475,39 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
         }
         break;
     
    +  case CMARK_NODE_ATTRIBUTE:
    +    if (entering) {
    +      LIT("^[");
    +    } else {
    +      LIT("](");
    +      OUT(cmark_node_get_attributes(node), false, LITERAL);
    +      LIT(")");
    +    }
    +    break;
    +
    +  case CMARK_NODE_FOOTNOTE_REFERENCE:
    +    if (entering) {
    +      LIT("[^");
    +      OUT(cmark_chunk_to_cstr(renderer->mem, &node->as.literal), false, LITERAL);
    +      LIT("]");
    +    }
    +    break;
    +
    +  case CMARK_NODE_FOOTNOTE_DEFINITION:
    +    if (entering) {
    +      renderer->footnote_ix += 1;
    +      LIT("[^");
    +      char n[32];
    +      snprintf(n, sizeof(n), "%d", renderer->footnote_ix);
    +      OUT(n, false, LITERAL);
    +      LIT("]:\n");
    +
    +      cmark_strbuf_puts(renderer->prefix, "    ");
    +    } else {
    +      cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 4);
    +    }
    +    break;
    +
       default:
         assert(false);
         break;
    @@ -477,10 +517,14 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
     }
     
     char *cmark_render_commonmark(cmark_node *root, int options, int width) {
    +  return cmark_render_commonmark_with_mem(root, options, width, cmark_node_mem(root));
    +}
    +
    +char *cmark_render_commonmark_with_mem(cmark_node *root, int options, int width, cmark_mem *mem) {
       if (options & CMARK_OPT_HARDBREAKS) {
         // disable breaking on width, since it has
         // a different meaning with OPT_HARDBREAKS
         width = 0;
       }
    -  return cmark_render(root, options, width, outc, S_render_node);
    +  return cmark_render(mem, root, options, width, outc, S_render_node);
     }
    diff --git a/src/config.h.in b/src/config.h.in
    index de1a4dd49..65702b2e0 100644
    --- a/src/config.h.in
    +++ b/src/config.h.in
    @@ -17,6 +17,8 @@ extern "C" {
     
     #cmakedefine HAVE___ATTRIBUTE__
     
    +#cmakedefine CMARK_THREADING
    +
     #ifdef HAVE___ATTRIBUTE__
       #define CMARK_ATTRIBUTE(list) __attribute__ (list)
     #else
    diff --git a/src/footnotes.c b/src/footnotes.c
    new file mode 100644
    index 000000000..f2d2765f4
    --- /dev/null
    +++ b/src/footnotes.c
    @@ -0,0 +1,40 @@
    +#include "cmark-gfm.h"
    +#include "parser.h"
    +#include "footnotes.h"
    +#include "inlines.h"
    +#include "chunk.h"
    +
    +static void footnote_free(cmark_map *map, cmark_map_entry *_ref) {
    +  cmark_footnote *ref = (cmark_footnote *)_ref;
    +  cmark_mem *mem = map->mem;
    +  if (ref != NULL) {
    +    mem->free(ref->entry.label);
    +    if (ref->node)
    +      cmark_node_free(ref->node);
    +    mem->free(ref);
    +  }
    +}
    +
    +void cmark_footnote_create(cmark_map *map, cmark_node *node) {
    +  cmark_footnote *ref;
    +  unsigned char *reflabel = normalize_map_label(map->mem, &node->as.literal);
    +
    +  /* empty footnote name, or composed from only whitespace */
    +  if (reflabel == NULL)
    +    return;
    +
    +  assert(map->sorted == NULL);
    +
    +  ref = (cmark_footnote *)map->mem->calloc(1, sizeof(*ref));
    +  ref->entry.label = reflabel;
    +  ref->node = node;
    +  ref->entry.age = map->size;
    +  ref->entry.next = map->refs;
    +
    +  map->refs = (cmark_map_entry *)ref;
    +  map->size++;
    +}
    +
    +cmark_map *cmark_footnote_map_new(cmark_mem *mem) {
    +  return cmark_map_new(mem, footnote_free);
    +}
    diff --git a/src/houdini_href_e.c b/src/houdini_href_e.c
    index bfa970485..169389197 100644
    --- a/src/houdini_href_e.c
    +++ b/src/houdini_href_e.c
    @@ -7,7 +7,7 @@
     /*
      * The following characters will not be escaped:
      *
    - *		-_.+!*'(),%#@?=;:/,+&$ alphanum
    + *		-_.+!*'(),%#@?=;:/,+&$~ alphanum
      *
      * Note that this character set is the addition of:
      *
    @@ -35,7 +35,7 @@ static const char HREF_SAFE[] = {
         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,
    +    1, 1, 1, 0, 0, 0, 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,
    diff --git a/src/houdini_html_e.c b/src/houdini_html_e.c
    index 0e539f037..da0b15c53 100644
    --- a/src/houdini_html_e.c
    +++ b/src/houdini_html_e.c
    @@ -48,7 +48,7 @@ int houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src, bufsize_t size,
         if (unlikely(i >= size))
           break;
     
    -    /* The forward slash is only escaped in secure mode */
    +    /* The forward slash and single quote are only escaped in secure mode */
         if ((src[i] == '/' || src[i] == '\'') && !secure) {
           cmark_strbuf_putc(ob, src[i]);
         } else {
    diff --git a/src/html.c b/src/html.c
    index a13d016dc..5959d7a0b 100644
    --- a/src/html.c
    +++ b/src/html.c
    @@ -3,14 +3,13 @@
     #include 
     #include 
     #include "cmark_ctype.h"
    -#include "config.h"
    -#include "cmark.h"
    -#include "node.h"
    -#include "buffer.h"
    +#include "cmark-gfm_config.h"
    +#include "cmark-gfm.h"
     #include "houdini.h"
     #include "scanners.h"
    -
    -#define BUFFER_SIZE 100
    +#include "syntax_extension.h"
    +#include "html.h"
    +#include "render.h"
     
     // Functions to convert cmark_nodes to HTML strings.
     
    @@ -19,44 +18,81 @@ static void escape_html(cmark_strbuf *dest, const unsigned char *source,
       houdini_escape_html0(dest, source, length, 0);
     }
     
    -static CMARK_INLINE void cr(cmark_strbuf *html) {
    -  if (html->size && html->ptr[html->size - 1] != '\n')
    -    cmark_strbuf_putc(html, '\n');
    -}
    +static void filter_html_block(cmark_html_renderer *renderer, uint8_t *data, size_t len) {
    +  cmark_strbuf *html = renderer->html;
    +  cmark_llist *it;
    +  cmark_syntax_extension *ext;
    +  bool filtered;
    +  uint8_t *match;
     
    -struct render_state {
    -  cmark_strbuf *html;
    -  cmark_node *plain;
    -};
    +  while (len) {
    +    match = (uint8_t *) memchr(data, '<', len);
    +    if (!match)
    +      break;
     
    -static void S_render_sourcepos(cmark_node *node, cmark_strbuf *html,
    -                               int options) {
    -  char buffer[BUFFER_SIZE];
    -  if (CMARK_OPT_SOURCEPOS & options) {
    -    snprintf(buffer, BUFFER_SIZE, " data-sourcepos=\"%d:%d-%d:%d\"",
    -             cmark_node_get_start_line(node), cmark_node_get_start_column(node),
    -             cmark_node_get_end_line(node), cmark_node_get_end_column(node));
    -    cmark_strbuf_puts(html, buffer);
    +    if (match != data) {
    +      cmark_strbuf_put(html, data, (bufsize_t)(match - data));
    +      len -= (match - data);
    +      data = match;
    +    }
    +
    +    filtered = false;
    +    for (it = renderer->filter_extensions; it; it = it->next) {
    +      ext = ((cmark_syntax_extension *) it->data);
    +      if (!ext->html_filter_func(ext, data, len)) {
    +        filtered = true;
    +        break;
    +      }
    +    }
    +
    +    if (!filtered) {
    +      cmark_strbuf_putc(html, '<');
    +    } else {
    +      cmark_strbuf_puts(html, "<");
    +    }
    +
    +    ++data;
    +    --len;
       }
    +
    +  if (len)
    +    cmark_strbuf_put(html, data, (bufsize_t)len);
     }
     
    -static int S_render_node(cmark_node *node, cmark_event_type ev_type,
    -                         struct render_state *state, int options) {
    +static bool S_put_footnote_backref(cmark_html_renderer *renderer, cmark_strbuf *html) {
    +  if (renderer->written_footnote_ix >= renderer->footnote_ix)
    +    return false;
    +  renderer->written_footnote_ix = renderer->footnote_ix;
    +
    +  cmark_strbuf_puts(html, "footnote_ix);
    +  cmark_strbuf_puts(html, n);
    +  cmark_strbuf_puts(html, "\" class=\"footnote-backref\">↩");
    +
    +  return true;
    +}
    +
    +static int S_render_node(cmark_html_renderer *renderer, cmark_node *node,
    +                         cmark_event_type ev_type, int options) {
       cmark_node *parent;
       cmark_node *grandparent;
    -  cmark_strbuf *html = state->html;
    +  cmark_strbuf *html = renderer->html;
    +  cmark_llist *it;
    +  cmark_syntax_extension *ext;
       char start_heading[] = "plain == node) { // back at original node
    -    state->plain = NULL;
    +  if (renderer->plain == node) { // back at original node
    +    renderer->plain = NULL;
       }
     
    -  if (state->plain != NULL) {
    +  if (renderer->plain != NULL) {
         switch (node->type) {
         case CMARK_NODE_TEXT:
         case CMARK_NODE_CODE:
    @@ -75,18 +111,23 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type,
         return 1;
       }
     
    +  if (node->extension && node->extension->html_render_func) {
    +    node->extension->html_render_func(node->extension, renderer, node, ev_type, options);
    +    return 1;
    +  }
    +
       switch (node->type) {
       case CMARK_NODE_DOCUMENT:
         break;
     
       case CMARK_NODE_BLOCK_QUOTE:
         if (entering) {
    -      cr(html);
    +      cmark_html_render_cr(html);
           cmark_strbuf_puts(html, "\n");
         } else {
    -      cr(html);
    +      cmark_html_render_cr(html);
           cmark_strbuf_puts(html, "\n");
         }
         break;
    @@ -96,19 +137,19 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type,
         int start = node->as.list.start;
     
         if (entering) {
    -      cr(html);
    +      cmark_html_render_cr(html);
           if (list_type == CMARK_BULLET_LIST) {
             cmark_strbuf_puts(html, "\n");
           } else if (start == 1) {
             cmark_strbuf_puts(html, "\n");
           } else {
             snprintf(buffer, BUFFER_SIZE, "
      \n"); } } else { @@ -120,9 +161,9 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type, case CMARK_NODE_ITEM: if (entering) { - cr(html); + cmark_html_render_cr(html); cmark_strbuf_puts(html, "'); } else { cmark_strbuf_puts(html, "\n"); @@ -131,10 +172,10 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type, case CMARK_NODE_HEADING: if (entering) { - cr(html); + cmark_html_render_cr(html); start_heading[2] = (char)('0' + node->as.heading.level); cmark_strbuf_puts(html, start_heading); - S_render_sourcepos(node, html, options); + cmark_html_render_sourcepos(node, html, options); cmark_strbuf_putc(html, '>'); } else { end_heading[3] = (char)('0' + node->as.heading.level); @@ -144,11 +185,11 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type, break; case CMARK_NODE_CODE_BLOCK: - cr(html); + cmark_html_render_cr(html); if (node->as.code.info.len == 0) { cmark_strbuf_puts(html, ""); } else { bufsize_t first_tag = 0; @@ -157,11 +198,27 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type, first_tag += 1; } - cmark_strbuf_puts(html, "as.code.info.data, first_tag); - cmark_strbuf_puts(html, "\">"); + if (options & CMARK_OPT_GITHUB_PRE_LANG) { + cmark_strbuf_puts(html, "as.code.info.data, first_tag); + if (first_tag < node->as.code.info.len && (options & CMARK_OPT_FULL_INFO_STRING)) { + cmark_strbuf_puts(html, "\" data-meta=\""); + escape_html(html, node->as.code.info.data + first_tag + 1, node->as.code.info.len - first_tag - 1); + } + cmark_strbuf_puts(html, "\">"); + } else { + cmark_strbuf_puts(html, "as.code.info.data, first_tag); + if (first_tag < node->as.code.info.len && (options & CMARK_OPT_FULL_INFO_STRING)) { + cmark_strbuf_puts(html, "\" data-meta=\""); + escape_html(html, node->as.code.info.data + first_tag + 1, node->as.code.info.len - first_tag - 1); + } + cmark_strbuf_puts(html, "\">"); + } } escape_html(html, node->as.code.literal.data, node->as.code.literal.len); @@ -169,17 +226,19 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type, break; case CMARK_NODE_HTML_BLOCK: - cr(html); + cmark_html_render_cr(html); if (!(options & CMARK_OPT_UNSAFE)) { cmark_strbuf_puts(html, ""); + } else if (renderer->filter_extensions) { + filter_html_block(renderer, node->as.literal.data, node->as.literal.len); } else { cmark_strbuf_put(html, node->as.literal.data, node->as.literal.len); } - cr(html); + cmark_html_render_cr(html); break; case CMARK_NODE_CUSTOM_BLOCK: - cr(html); + cmark_html_render_cr(html); if (entering) { cmark_strbuf_put(html, node->as.custom.on_enter.data, node->as.custom.on_enter.len); @@ -187,13 +246,13 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type, cmark_strbuf_put(html, node->as.custom.on_exit.data, node->as.custom.on_exit.len); } - cr(html); + cmark_html_render_cr(html); break; case CMARK_NODE_THEMATIC_BREAK: - cr(html); + cmark_html_render_cr(html); cmark_strbuf_puts(html, "\n"); break; @@ -207,11 +266,15 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type, } if (!tight) { if (entering) { - cr(html); + cmark_html_render_cr(html); cmark_strbuf_puts(html, "'); } else { + if (parent->type == CMARK_NODE_FOOTNOTE_DEFINITION && node->next == NULL) { + cmark_strbuf_putc(html, ' '); + S_put_footnote_backref(renderer, html); + } cmark_strbuf_puts(html, "

      \n"); } } @@ -245,7 +308,20 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type, if (!(options & CMARK_OPT_UNSAFE)) { cmark_strbuf_puts(html, ""); } else { - cmark_strbuf_put(html, node->as.literal.data, node->as.literal.len); + filtered = false; + for (it = renderer->filter_extensions; it; it = it->next) { + ext = (cmark_syntax_extension *) it->data; + if (!ext->html_filter_func(ext, node->as.literal.data, node->as.literal.len)) { + filtered = true; + break; + } + } + if (!filtered) { + cmark_strbuf_put(html, node->as.literal.data, node->as.literal.len); + } else { + cmark_strbuf_puts(html, "<"); + cmark_strbuf_put(html, node->as.literal.data + 1, node->as.literal.len - 1); + } } break; @@ -302,7 +378,7 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type, node->as.link.url.len); } cmark_strbuf_puts(html, "\" alt=\""); - state->plain = node; + renderer->plain = node; } else { if (node->as.link.title.len) { cmark_strbuf_puts(html, "\" title=\""); @@ -313,29 +389,90 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type, } break; + case CMARK_NODE_ATTRIBUTE: + // TODO: Output span, attributes potentially controlling class/id here. For now just output the main string. + /* + if (entering) { + cmark_strbuf_puts(html, "as.attribute.attributes.data, node->as.attribute.attributes.len); + cmark_strbuf_puts(html, "\">"); + } else { + cmark_strbuf_puts(html, ""); + } + */ + break; + + case CMARK_NODE_FOOTNOTE_DEFINITION: + if (entering) { + if (renderer->footnote_ix == 0) { + cmark_strbuf_puts(html, "
      \n
        \n"); + } + ++renderer->footnote_ix; + cmark_strbuf_puts(html, "
      1. footnote_ix); + cmark_strbuf_puts(html, n); + cmark_strbuf_puts(html, "\">\n"); + } else { + if (S_put_footnote_backref(renderer, html)) { + cmark_strbuf_putc(html, '\n'); + } + cmark_strbuf_puts(html, "
      2. \n"); + } + break; + + case CMARK_NODE_FOOTNOTE_REFERENCE: + if (entering) { + cmark_strbuf_puts(html, "as.literal.data, node->as.literal.len); + cmark_strbuf_puts(html, "\" id=\"fnref"); + cmark_strbuf_put(html, node->as.literal.data, node->as.literal.len); + cmark_strbuf_puts(html, "\">"); + cmark_strbuf_put(html, node->as.literal.data, node->as.literal.len); + cmark_strbuf_puts(html, ""); + } + break; + default: assert(false); break; } - // cmark_strbuf_putc(html, 'x'); return 1; } -char *cmark_render_html(cmark_node *root, int options) { +char *cmark_render_html(cmark_node *root, int options, cmark_llist *extensions) { + return cmark_render_html_with_mem(root, options, extensions, cmark_node_mem(root)); +} + +char *cmark_render_html_with_mem(cmark_node *root, int options, cmark_llist *extensions, cmark_mem *mem) { char *result; - cmark_strbuf html = CMARK_BUF_INIT(cmark_node_mem(root)); + cmark_strbuf html = CMARK_BUF_INIT(mem); cmark_event_type ev_type; cmark_node *cur; - struct render_state state = {&html, NULL}; + cmark_html_renderer renderer = {&html, NULL, NULL, 0, 0, NULL}; cmark_iter *iter = cmark_iter_new(root); + for (; extensions; extensions = extensions->next) + if (((cmark_syntax_extension *) extensions->data)->html_filter_func) + renderer.filter_extensions = cmark_llist_append( + mem, + renderer.filter_extensions, + (cmark_syntax_extension *) extensions->data); + while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { cur = cmark_iter_get_node(iter); - S_render_node(cur, ev_type, &state, options); + S_render_node(&renderer, cur, ev_type, options); } + + if (renderer.footnote_ix) { + cmark_strbuf_puts(&html, "
      \n
      \n"); + } + result = (char *)cmark_strbuf_detach(&html); + cmark_llist_free(mem, renderer.filter_extensions); + cmark_iter_free(iter); return result; } diff --git a/src/buffer.h b/src/include/buffer.h similarity index 84% rename from src/buffer.h rename to src/include/buffer.h index e8780753f..96a8ba2fa 100644 --- a/src/buffer.h +++ b/src/include/buffer.h @@ -6,15 +6,13 @@ #include #include #include -#include "config.h" -#include "cmark.h" +#include "cmark-gfm_config.h" +#include "cmark-gfm.h" #ifdef __cplusplus extern "C" { #endif -typedef int32_t bufsize_t; - typedef struct { cmark_mem *mem; unsigned char *ptr; @@ -32,22 +30,32 @@ extern unsigned char cmark_strbuf__initbuf[]; * For the cases where CMARK_BUF_INIT cannot be used to do static * initialization. */ +CMARK_GFM_EXPORT void cmark_strbuf_init(cmark_mem *mem, cmark_strbuf *buf, bufsize_t initial_size); /** * Grow the buffer to hold at least `target_size` bytes. */ +CMARK_GFM_EXPORT void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size); +CMARK_GFM_EXPORT void cmark_strbuf_free(cmark_strbuf *buf); + +CMARK_GFM_EXPORT void cmark_strbuf_swap(cmark_strbuf *buf_a, cmark_strbuf *buf_b); +CMARK_GFM_EXPORT bufsize_t cmark_strbuf_len(const cmark_strbuf *buf); +CMARK_GFM_EXPORT int cmark_strbuf_cmp(const cmark_strbuf *a, const cmark_strbuf *b); +CMARK_GFM_EXPORT unsigned char *cmark_strbuf_detach(cmark_strbuf *buf); + +CMARK_GFM_EXPORT void cmark_strbuf_copy_cstr(char *data, bufsize_t datasize, const cmark_strbuf *buf); @@ -57,22 +65,48 @@ static CMARK_INLINE const char *cmark_strbuf_cstr(const cmark_strbuf *buf) { #define cmark_strbuf_at(buf, n) ((buf)->ptr[n]) +CMARK_GFM_EXPORT void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data, bufsize_t len); + +CMARK_GFM_EXPORT void cmark_strbuf_sets(cmark_strbuf *buf, const char *string); + +CMARK_GFM_EXPORT void cmark_strbuf_putc(cmark_strbuf *buf, int c); + +CMARK_GFM_EXPORT void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data, bufsize_t len); + +CMARK_GFM_EXPORT void cmark_strbuf_puts(cmark_strbuf *buf, const char *string); + +CMARK_GFM_EXPORT void cmark_strbuf_clear(cmark_strbuf *buf); +CMARK_GFM_EXPORT bufsize_t cmark_strbuf_strchr(const cmark_strbuf *buf, int c, bufsize_t pos); + +CMARK_GFM_EXPORT bufsize_t cmark_strbuf_strrchr(const cmark_strbuf *buf, int c, bufsize_t pos); + +CMARK_GFM_EXPORT void cmark_strbuf_drop(cmark_strbuf *buf, bufsize_t n); + +CMARK_GFM_EXPORT void cmark_strbuf_truncate(cmark_strbuf *buf, bufsize_t len); + +CMARK_GFM_EXPORT void cmark_strbuf_rtrim(cmark_strbuf *buf); + +CMARK_GFM_EXPORT void cmark_strbuf_trim(cmark_strbuf *buf); + +CMARK_GFM_EXPORT void cmark_strbuf_normalize_whitespace(cmark_strbuf *s); + +CMARK_GFM_EXPORT void cmark_strbuf_unescape(cmark_strbuf *s); #ifdef __cplusplus diff --git a/src/chunk.h b/src/include/chunk.h similarity index 82% rename from src/chunk.h rename to src/include/chunk.h index 6d1601d24..c411c04a4 100644 --- a/src/chunk.h +++ b/src/include/chunk.h @@ -4,14 +4,14 @@ #include #include #include -#include "cmark.h" +#include "cmark-gfm.h" #include "buffer.h" #include "cmark_ctype.h" #define CMARK_CHUNK_EMPTY \ { NULL, 0, 0 } -typedef struct { +typedef struct cmark_chunk { unsigned char *data; bufsize_t len; bufsize_t alloc; // also implies a NULL-terminated string @@ -116,4 +116,20 @@ static CMARK_INLINE cmark_chunk cmark_chunk_buf_detach(cmark_strbuf *buf) { return c; } +/* trim_new variants are to be used when the source chunk may or may not be + * allocated; forces a newly allocated chunk. */ +static CMARK_INLINE cmark_chunk cmark_chunk_ltrim_new(cmark_mem *mem, cmark_chunk *c) { + cmark_chunk r = cmark_chunk_dup(c, 0, c->len); + cmark_chunk_ltrim(&r); + cmark_chunk_to_cstr(mem, &r); + return r; +} + +static CMARK_INLINE cmark_chunk cmark_chunk_rtrim_new(cmark_mem *mem, cmark_chunk *c) { + cmark_chunk r = cmark_chunk_dup(c, 0, c->len); + cmark_chunk_rtrim(&r); + cmark_chunk_to_cstr(mem, &r); + return r; +} + #endif diff --git a/src/include/cmark-gfm-extension_api.h b/src/include/cmark-gfm-extension_api.h new file mode 100644 index 000000000..104b4d00c --- /dev/null +++ b/src/include/cmark-gfm-extension_api.h @@ -0,0 +1,736 @@ +#ifndef CMARK_GFM_EXTENSION_API_H +#define CMARK_GFM_EXTENSION_API_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "cmark-gfm.h" + +struct cmark_renderer; +struct cmark_html_renderer; +struct cmark_chunk; + +/** + * ## Extension Support + * + * While the "core" of libcmark is strictly compliant with the + * specification, an API is provided for extension writers to + * hook into the parsing process. + * + * It should be noted that the cmark_node API already offers + * room for customization, with methods offered to traverse and + * modify the AST, and even define custom blocks. + * When the desired customization is achievable in an error-proof + * way using that API, it should be the preferred method. + * + * The following API requires a more in-depth understanding + * of libcmark's parsing strategy, which is exposed + * [here](http://spec.commonmark.org/0.24/#appendix-a-parsing-strategy). + * + * It should be used when "a posteriori" modification of the AST + * proves to be too difficult / impossible to implement correctly. + * + * It can also serve as an intermediary step before extending + * the specification, as an extension implemented using this API + * will be trivially integrated in the core if it proves to be + * desirable. + */ + +typedef struct cmark_plugin cmark_plugin; + +/** A syntax extension that can be attached to a cmark_parser + * with cmark_parser_attach_syntax_extension(). + * + * Extension writers should assign functions matching + * the signature of the following 'virtual methods' to + * implement new functionality. + * + * Their calling order and expected behaviour match the procedure outlined + * at : + * + * During step 1, cmark will call the function provided through + * 'cmark_syntax_extension_set_match_block_func' when it + * iterates over an open block created by this extension, + * to determine whether it could contain the new line. + * If no function was provided, cmark will close the block. + * + * During step 2, if and only if the new line doesn't match any + * of the standard syntax rules, cmark will call the function + * provided through 'cmark_syntax_extension_set_open_block_func' + * to let the extension determine whether that new line matches + * one of its syntax rules. + * It is the responsibility of the parser to create and add the + * new block with cmark_parser_make_block and cmark_parser_add_child. + * If no function was provided is NULL, the extension will have + * no effect at all on the final block structure of the AST. + * + * #### Inline parsing phase hooks + * + * For each character provided by the extension through + * 'cmark_syntax_extension_set_special_inline_chars', + * the function provided by the extension through + * 'cmark_syntax_extension_set_match_inline_func' + * will get called, it is the responsibility of the extension + * to scan the characters located at the current inline parsing offset + * with the cmark_inline_parser API. + * + * Depending on the type of the extension, it can either: + * + * * Scan forward, determine that the syntax matches and return + * a newly-created inline node with the appropriate type. + * This is the technique that would be used if inline code + * (with backticks) was implemented as an extension. + * * Scan only the character(s) that its syntax rules require + * for opening and closing nodes, push a delimiter on the + * delimiter stack, and return a simple text node with its + * contents set to the character(s) consumed. + * This is the technique that would be used if emphasis + * inlines were implemented as an extension. + * + * When an extension has pushed delimiters on the stack, + * the function provided through + * 'cmark_syntax_extension_set_inline_from_delim_func' + * will get called in a latter phase, + * when the inline parser has matched opener and closer delimiters + * created by the extension together. + * + * It is then the responsibility of the extension to modify + * and populate the opener inline text node, and to remove + * the necessary delimiters from the delimiter stack. + * + * Finally, the extension should return NULL if its scan didn't + * match its syntax rules. + * + * The extension can store whatever private data it might need + * with 'cmark_syntax_extension_set_private', + * and optionally define a free function for this data. + */ +typedef struct subject cmark_inline_parser; + +/** Exposed raw for now */ + +typedef struct delimiter { + struct delimiter *previous; + struct delimiter *next; + cmark_node *inl_text; + bufsize_t length; + unsigned char delim_char; + int can_open; + int can_close; +} delimiter; + +/** + * ### Plugin API. + * + * Extensions should be distributed as dynamic libraries, + * with a single exported function named after the distributed + * filename. + * + * When discovering extensions (see cmark_init), cmark will + * try to load a symbol named "init_{{filename}}" in all the + * dynamic libraries it encounters. + * + * For example, given a dynamic library named myextension.so + * (or myextension.dll), cmark will try to load the symbol + * named "init_myextension". This means that the filename + * must lend itself to forming a valid C identifier, with + * the notable exception of dashes, which will be translated + * to underscores, which means cmark will look for a function + * named "init_my_extension" if it encounters a dynamic library + * named "my-extension.so". + * + * See the 'cmark_plugin_init_func' typedef for the exact prototype + * this function should follow. + * + * For now the extensibility of cmark is not complete, as + * it only offers API to hook into the block parsing phase + * (). + * + * See 'cmark_plugin_register_syntax_extension' for more information. + */ + +/** The prototype plugins' init function should follow. + */ +typedef int (*cmark_plugin_init_func)(cmark_plugin *plugin); + +/** Register a syntax 'extension' with the 'plugin', it will be made + * available as an extension and, if attached to a cmark_parser + * with 'cmark_parser_attach_syntax_extension', it will contribute + * to the block parsing process. + * + * See the documentation for 'cmark_syntax_extension' for information + * on how to implement one. + * + * This function will typically be called from the init function + * of external modules. + * + * This takes ownership of 'extension', one should not call + * 'cmark_syntax_extension_free' on a registered extension. + */ +CMARK_GFM_EXPORT +int cmark_plugin_register_syntax_extension(cmark_plugin *plugin, + cmark_syntax_extension *extension); + +/** This will search for the syntax extension named 'name' among the + * registered syntax extensions. + * + * It can then be attached to a cmark_parser + * with the cmark_parser_attach_syntax_extension method. + */ +CMARK_GFM_EXPORT +cmark_syntax_extension *cmark_find_syntax_extension(const char *name); + +/** Should create and add a new open block to 'parent_container' if + * 'input' matches a syntax rule for that block type. It is allowed + * to modify the type of 'parent_container'. + * + * Should return the newly created block if there is one, or + * 'parent_container' if its type was modified, or NULL. + */ +typedef cmark_node * (*cmark_open_block_func) (cmark_syntax_extension *extension, + int indented, + cmark_parser *parser, + cmark_node *parent_container, + unsigned char *input, + int len); + +typedef cmark_node *(*cmark_match_inline_func)(cmark_syntax_extension *extension, + cmark_parser *parser, + cmark_node *parent, + unsigned char character, + cmark_inline_parser *inline_parser); + +typedef delimiter *(*cmark_inline_from_delim_func)(cmark_syntax_extension *extension, + cmark_parser *parser, + cmark_inline_parser *inline_parser, + delimiter *opener, + delimiter *closer); + +/** Should return 'true' if 'input' can be contained in 'container', + * 'false' otherwise. + */ +typedef int (*cmark_match_block_func) (cmark_syntax_extension *extension, + cmark_parser *parser, + unsigned char *input, + int len, + cmark_node *container); + +typedef const char *(*cmark_get_type_string_func) (cmark_syntax_extension *extension, + cmark_node *node); + +typedef int (*cmark_can_contain_func) (cmark_syntax_extension *extension, + cmark_node *node, + cmark_node_type child); + +typedef int (*cmark_contains_inlines_func) (cmark_syntax_extension *extension, + cmark_node *node); + +typedef void (*cmark_common_render_func) (cmark_syntax_extension *extension, + struct cmark_renderer *renderer, + cmark_node *node, + cmark_event_type ev_type, + int options); + +typedef int (*cmark_commonmark_escape_func) (cmark_syntax_extension *extension, + cmark_node *node, + int c); + +typedef const char* (*cmark_xml_attr_func) (cmark_syntax_extension *extension, + cmark_node *node); + +typedef void (*cmark_html_render_func) (cmark_syntax_extension *extension, + struct cmark_html_renderer *renderer, + cmark_node *node, + cmark_event_type ev_type, + int options); + +typedef int (*cmark_html_filter_func) (cmark_syntax_extension *extension, + const unsigned char *tag, + size_t tag_len); + +typedef cmark_node *(*cmark_postprocess_func) (cmark_syntax_extension *extension, + cmark_parser *parser, + cmark_node *root); + +typedef int (*cmark_ispunct_func) (char c); + +typedef void (*cmark_opaque_alloc_func) (cmark_syntax_extension *extension, + cmark_mem *mem, + cmark_node *node); + +typedef void (*cmark_opaque_free_func) (cmark_syntax_extension *extension, + cmark_mem *mem, + cmark_node *node); + +/** Free a cmark_syntax_extension. + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_free (cmark_mem *mem, cmark_syntax_extension *extension); + +/** Return a newly-constructed cmark_syntax_extension, named 'name'. + */ +CMARK_GFM_EXPORT +cmark_syntax_extension *cmark_syntax_extension_new (const char *name); + +CMARK_GFM_EXPORT +cmark_node_type cmark_syntax_extension_add_node(int is_inline); + +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_emphasis(cmark_syntax_extension *extension, int emphasis); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_open_block_func(cmark_syntax_extension *extension, + cmark_open_block_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_match_block_func(cmark_syntax_extension *extension, + cmark_match_block_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_match_inline_func(cmark_syntax_extension *extension, + cmark_match_inline_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_inline_from_delim_func(cmark_syntax_extension *extension, + cmark_inline_from_delim_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_special_inline_chars(cmark_syntax_extension *extension, + cmark_llist *special_chars); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_get_type_string_func(cmark_syntax_extension *extension, + cmark_get_type_string_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_can_contain_func(cmark_syntax_extension *extension, + cmark_can_contain_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_contains_inlines_func(cmark_syntax_extension *extension, + cmark_contains_inlines_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_commonmark_render_func(cmark_syntax_extension *extension, + cmark_common_render_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_plaintext_render_func(cmark_syntax_extension *extension, + cmark_common_render_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_latex_render_func(cmark_syntax_extension *extension, + cmark_common_render_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_xml_attr_func(cmark_syntax_extension *extension, + cmark_xml_attr_func func); + + /** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_man_render_func(cmark_syntax_extension *extension, + cmark_common_render_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_html_render_func(cmark_syntax_extension *extension, + cmark_html_render_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_html_filter_func(cmark_syntax_extension *extension, + cmark_html_filter_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_commonmark_escape_func(cmark_syntax_extension *extension, + cmark_commonmark_escape_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_private(cmark_syntax_extension *extension, + void *priv, + cmark_free_func free_func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void *cmark_syntax_extension_get_private(cmark_syntax_extension *extension); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_postprocess_func(cmark_syntax_extension *extension, + cmark_postprocess_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_opaque_alloc_func(cmark_syntax_extension *extension, + cmark_opaque_alloc_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_syntax_extension_set_opaque_free_func(cmark_syntax_extension *extension, + cmark_opaque_free_func func); + +/** See the documentation for 'cmark_syntax_extension' + */ +CMARK_GFM_EXPORT +void cmark_parser_set_backslash_ispunct_func(cmark_parser *parser, + cmark_ispunct_func func); + +/** Return the index of the line currently being parsed, starting with 1. + */ +CMARK_GFM_EXPORT +int cmark_parser_get_line_number(cmark_parser *parser); + +/** Return the offset in bytes in the line being processed. + * + * Example: + * + * ### foo + * + * Here, offset will first be 0, then 5 (the index of the 'f' character). + */ +CMARK_GFM_EXPORT +int cmark_parser_get_offset(cmark_parser *parser); + +/** + * Return the offset in 'columns' in the line being processed. + * + * This value may differ from the value returned by + * cmark_parser_get_offset() in that it accounts for tabs, + * and as such should not be used as an index in the current line's + * buffer. + * + * Example: + * + * cmark_parser_advance_offset() can be called to advance the + * offset by a number of columns, instead of a number of bytes. + * + * In that case, if offset falls "in the middle" of a tab + * character, 'column' and offset will differ. + * + * ``` + * foo \t bar + * ^ ^^ + * offset (0) 20 + * ``` + * + * If cmark_parser_advance_offset is called here with 'columns' + * set to 'true' and 'offset' set to 22, cmark_parser_get_offset() + * will return 20, whereas cmark_parser_get_column() will return + * 22. + * + * Additionally, as tabs expand to the next multiple of 4 column, + * cmark_parser_has_partially_consumed_tab() will now return + * 'true'. + */ +CMARK_GFM_EXPORT +int cmark_parser_get_column(cmark_parser *parser); + +/** Return the absolute index in bytes of the first nonspace + * character coming after the offset as returned by + * cmark_parser_get_offset() in the line currently being processed. + * + * Example: + * + * ``` + * foo bar baz \n + * ^ ^ ^ + * 0 offset (16) first_nonspace (28) + * ``` + */ +CMARK_GFM_EXPORT +int cmark_parser_get_first_nonspace(cmark_parser *parser); + +/** Return the absolute index of the first nonspace column coming after 'offset' + * in the line currently being processed, counting tabs as multiple + * columns as appropriate. + * + * See the documentation for cmark_parser_get_first_nonspace() and + * cmark_parser_get_column() for more information. + */ +CMARK_GFM_EXPORT +int cmark_parser_get_first_nonspace_column(cmark_parser *parser); + +/** Return the difference between the values returned by + * cmark_parser_get_first_nonspace_column() and + * cmark_parser_get_column(). + * + * This is not a byte offset, as it can count one tab as multiple + * characters. + */ +CMARK_GFM_EXPORT +int cmark_parser_get_indent(cmark_parser *parser); + +/** Return 'true' if the line currently being processed has been entirely + * consumed, 'false' otherwise. + * + * Example: + * + * ``` + * foo bar baz \n + * ^ + * offset + * ``` + * + * This function will return 'false' here. + * + * ``` + * foo bar baz \n + * ^ + * offset + * ``` + * This function will still return 'false'. + * + * ``` + * foo bar baz \n + * ^ + * offset + * ``` + * + * At this point, this function will now return 'true'. + */ +CMARK_GFM_EXPORT +int cmark_parser_is_blank(cmark_parser *parser); + +/** Return 'true' if the value returned by cmark_parser_get_offset() + * is 'inside' an expanded tab. + * + * See the documentation for cmark_parser_get_column() for more + * information. + */ +CMARK_GFM_EXPORT +int cmark_parser_has_partially_consumed_tab(cmark_parser *parser); + +/** Return the length in bytes of the previously processed line, excluding potential + * newline (\n) and carriage return (\r) trailing characters. + */ +CMARK_GFM_EXPORT +int cmark_parser_get_last_line_length(cmark_parser *parser); + +/** Add a child to 'parent' during the parsing process. + * + * If 'parent' isn't the kind of node that can accept this child, + * this function will back up till it hits a node that can, closing + * blocks as appropriate. + */ +CMARK_GFM_EXPORT +cmark_node*cmark_parser_add_child(cmark_parser *parser, + cmark_node *parent, + cmark_node_type block_type, + int start_column); + +/** Advance the 'offset' of the parser in the current line. + * + * See the documentation of cmark_parser_get_offset() and + * cmark_parser_get_column() for more information. + */ +CMARK_GFM_EXPORT +void cmark_parser_advance_offset(cmark_parser *parser, + const char *input, + int count, + int columns); + + +CMARK_GFM_EXPORT +void cmark_parser_feed_reentrant(cmark_parser *parser, const char *buffer, size_t len); + +/** Attach the syntax 'extension' to the 'parser', to provide extra syntax + * rules. + * See the documentation for cmark_syntax_extension for more information. + * + * Returns 'true' if the 'extension' was successfully attached, + * 'false' otherwise. + */ +CMARK_GFM_EXPORT +int cmark_parser_attach_syntax_extension(cmark_parser *parser, cmark_syntax_extension *extension); + +/** Change the type of 'node'. + * + * Return 0 if the type could be changed, 1 otherwise. + */ +CMARK_GFM_EXPORT int cmark_node_set_type(cmark_node *node, cmark_node_type type); + +/** Return the string content for all types of 'node'. + * The pointer stays valid as long as 'node' isn't freed. + */ +CMARK_GFM_EXPORT const char *cmark_node_get_string_content(cmark_node *node); + +/** Set the string 'content' for all types of 'node'. + * Copies 'content'. + */ +CMARK_GFM_EXPORT int cmark_node_set_string_content(cmark_node *node, const char *content); + +/** Get the syntax extension responsible for the creation of 'node'. + * Return NULL if 'node' was created because it matched standard syntax rules. + */ +CMARK_GFM_EXPORT cmark_syntax_extension *cmark_node_get_syntax_extension(cmark_node *node); + +/** Set the syntax extension responsible for creating 'node'. + */ +CMARK_GFM_EXPORT int cmark_node_set_syntax_extension(cmark_node *node, + cmark_syntax_extension *extension); + +/** + * ## Inline syntax extension helpers + * + * The inline parsing process is described in detail at + * + */ + +/** Should return 'true' if the predicate matches 'c', 'false' otherwise + */ +typedef int (*cmark_inline_predicate)(int c); + +/** Advance the current inline parsing offset */ +CMARK_GFM_EXPORT +void cmark_inline_parser_advance_offset(cmark_inline_parser *parser); + +/** Get the current inline parsing offset */ +CMARK_GFM_EXPORT +int cmark_inline_parser_get_offset(cmark_inline_parser *parser); + +/** Set the offset in bytes in the chunk being processed by the given inline parser. + */ +CMARK_GFM_EXPORT +void cmark_inline_parser_set_offset(cmark_inline_parser *parser, int offset); + +/** Gets the cmark_chunk being operated on by the given inline parser. + * Use cmark_inline_parser_get_offset to get our current position in the chunk. + */ +CMARK_GFM_EXPORT +struct cmark_chunk *cmark_inline_parser_get_chunk(cmark_inline_parser *parser); + +/** Returns 1 if the inline parser is currently in a bracket; pass 2 for attribute, + * 1 for 'image' if you want to know about an image-type bracket, 0 for link-type. */ +CMARK_GFM_EXPORT +int cmark_inline_parser_in_bracket(cmark_inline_parser *parser, int type); + +/** Remove the last n characters from the last child of the given node. + * This only works where all n characters are in the single last child, and the last + * child is CMARK_NODE_TEXT. + */ +CMARK_GFM_EXPORT +void cmark_node_unput(cmark_node *node, int n); + + +/** Get the character located at the current inline parsing offset + */ +CMARK_GFM_EXPORT +unsigned char cmark_inline_parser_peek_char(cmark_inline_parser *parser); + +/** Get the character located 'pos' bytes in the current line. + */ +CMARK_GFM_EXPORT +unsigned char cmark_inline_parser_peek_at(cmark_inline_parser *parser, int pos); + +/** Whether the inline parser has reached the end of the current line + */ +CMARK_GFM_EXPORT +int cmark_inline_parser_is_eof(cmark_inline_parser *parser); + +/** Get the characters located after the current inline parsing offset + * while 'pred' matches. Free after usage. + */ +CMARK_GFM_EXPORT +char *cmark_inline_parser_take_while(cmark_inline_parser *parser, cmark_inline_predicate pred); + +/** Push a delimiter on the delimiter stack. + * See < for + * more information on the parameters + */ +CMARK_GFM_EXPORT +void cmark_inline_parser_push_delimiter(cmark_inline_parser *parser, + unsigned char c, + int can_open, + int can_close, + cmark_node *inl_text); + +/** Remove 'delim' from the delimiter stack + */ +CMARK_GFM_EXPORT +void cmark_inline_parser_remove_delimiter(cmark_inline_parser *parser, delimiter *delim); + +CMARK_GFM_EXPORT +delimiter *cmark_inline_parser_get_last_delimiter(cmark_inline_parser *parser); + +CMARK_GFM_EXPORT +int cmark_inline_parser_get_line(cmark_inline_parser *parser); + +CMARK_GFM_EXPORT +int cmark_inline_parser_get_column(cmark_inline_parser *parser); + +/** Convenience function to scan a given delimiter. + * + * 'left_flanking' and 'right_flanking' will be set to true if they + * respectively precede and follow a non-space, non-punctuation + * character. + * + * Additionally, 'punct_before' and 'punct_after' will respectively be set + * if the preceding or following character is a punctuation character. + * + * Note that 'left_flanking' and 'right_flanking' can both be 'true'. + * + * Returns the number of delimiters encountered, in the limit + * of 'max_delims', and advances the inline parsing offset. + */ +CMARK_GFM_EXPORT +int cmark_inline_parser_scan_delimiters(cmark_inline_parser *parser, + int max_delims, + unsigned char c, + int *left_flanking, + int *right_flanking, + int *punct_before, + int *punct_after); + +CMARK_GFM_EXPORT +void cmark_manage_extensions_special_characters(cmark_parser *parser, int add); + +CMARK_GFM_EXPORT +cmark_llist *cmark_parser_get_syntax_extensions(cmark_parser *parser); + +CMARK_GFM_EXPORT +void cmark_arena_push(void); + +CMARK_GFM_EXPORT +int cmark_arena_pop(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cmark.h b/src/include/cmark-gfm.h similarity index 56% rename from src/cmark.h rename to src/include/cmark-gfm.h index 102aa6f8f..14ab95f4a 100644 --- a/src/cmark.h +++ b/src/include/cmark-gfm.h @@ -1,9 +1,10 @@ -#ifndef CMARK_H -#define CMARK_H +#ifndef CMARK_GFM_H +#define CMARK_GFM_H #include -#include -#include +#include +#include "cmark-gfm_export.h" +#include "cmark-gfm_version.h" #ifdef __cplusplus extern "C" { @@ -11,7 +12,7 @@ extern "C" { /** # NAME * - * **cmark** - CommonMark parsing, manipulating, and rendering + * **cmark-gfm** - CommonMark parsing, manipulating, and rendering */ /** # DESCRIPTION @@ -24,47 +25,53 @@ extern "C" { * UTF-8-encoded string. It is the caller's responsibility * to free the returned buffer. */ -CMARK_EXPORT +CMARK_GFM_EXPORT char *cmark_markdown_to_html(const char *text, size_t len, int options); /** ## Node Structure */ +#define CMARK_NODE_TYPE_PRESENT (0x8000) +#define CMARK_NODE_TYPE_BLOCK (CMARK_NODE_TYPE_PRESENT | 0x0000) +#define CMARK_NODE_TYPE_INLINE (CMARK_NODE_TYPE_PRESENT | 0x4000) +#define CMARK_NODE_TYPE_MASK (0xc000) +#define CMARK_NODE_VALUE_MASK (0x3fff) + typedef enum { /* Error status */ - CMARK_NODE_NONE, + CMARK_NODE_NONE = 0x0000, /* Block */ - CMARK_NODE_DOCUMENT, - CMARK_NODE_BLOCK_QUOTE, - CMARK_NODE_LIST, - CMARK_NODE_ITEM, - CMARK_NODE_CODE_BLOCK, - CMARK_NODE_HTML_BLOCK, - CMARK_NODE_CUSTOM_BLOCK, - CMARK_NODE_PARAGRAPH, - CMARK_NODE_HEADING, - CMARK_NODE_THEMATIC_BREAK, - - CMARK_NODE_FIRST_BLOCK = CMARK_NODE_DOCUMENT, - CMARK_NODE_LAST_BLOCK = CMARK_NODE_THEMATIC_BREAK, + CMARK_NODE_DOCUMENT = CMARK_NODE_TYPE_BLOCK | 0x0001, + CMARK_NODE_BLOCK_QUOTE = CMARK_NODE_TYPE_BLOCK | 0x0002, + CMARK_NODE_LIST = CMARK_NODE_TYPE_BLOCK | 0x0003, + CMARK_NODE_ITEM = CMARK_NODE_TYPE_BLOCK | 0x0004, + CMARK_NODE_CODE_BLOCK = CMARK_NODE_TYPE_BLOCK | 0x0005, + CMARK_NODE_HTML_BLOCK = CMARK_NODE_TYPE_BLOCK | 0x0006, + CMARK_NODE_CUSTOM_BLOCK = CMARK_NODE_TYPE_BLOCK | 0x0007, + CMARK_NODE_PARAGRAPH = CMARK_NODE_TYPE_BLOCK | 0x0008, + CMARK_NODE_HEADING = CMARK_NODE_TYPE_BLOCK | 0x0009, + CMARK_NODE_THEMATIC_BREAK = CMARK_NODE_TYPE_BLOCK | 0x000a, + CMARK_NODE_FOOTNOTE_DEFINITION = CMARK_NODE_TYPE_BLOCK | 0x000b, /* Inline */ - CMARK_NODE_TEXT, - CMARK_NODE_SOFTBREAK, - CMARK_NODE_LINEBREAK, - CMARK_NODE_CODE, - CMARK_NODE_HTML_INLINE, - CMARK_NODE_CUSTOM_INLINE, - CMARK_NODE_EMPH, - CMARK_NODE_STRONG, - CMARK_NODE_LINK, - CMARK_NODE_IMAGE, - - CMARK_NODE_FIRST_INLINE = CMARK_NODE_TEXT, - CMARK_NODE_LAST_INLINE = CMARK_NODE_IMAGE, + CMARK_NODE_TEXT = CMARK_NODE_TYPE_INLINE | 0x0001, + CMARK_NODE_SOFTBREAK = CMARK_NODE_TYPE_INLINE | 0x0002, + CMARK_NODE_LINEBREAK = CMARK_NODE_TYPE_INLINE | 0x0003, + CMARK_NODE_CODE = CMARK_NODE_TYPE_INLINE | 0x0004, + CMARK_NODE_HTML_INLINE = CMARK_NODE_TYPE_INLINE | 0x0005, + CMARK_NODE_CUSTOM_INLINE = CMARK_NODE_TYPE_INLINE | 0x0006, + CMARK_NODE_EMPH = CMARK_NODE_TYPE_INLINE | 0x0007, + CMARK_NODE_STRONG = CMARK_NODE_TYPE_INLINE | 0x0008, + CMARK_NODE_LINK = CMARK_NODE_TYPE_INLINE | 0x0009, + CMARK_NODE_IMAGE = CMARK_NODE_TYPE_INLINE | 0x000a, + CMARK_NODE_FOOTNOTE_REFERENCE = CMARK_NODE_TYPE_INLINE | 0x000b, + CMARK_NODE_ATTRIBUTE = CMARK_NODE_TYPE_INLINE | 0x000c, } cmark_node_type; +extern cmark_node_type CMARK_NODE_LAST_BLOCK; +extern cmark_node_type CMARK_NODE_LAST_INLINE; + /* For backwards compatibility: */ #define CMARK_NODE_HEADER CMARK_NODE_HEADING #define CMARK_NODE_HRULE CMARK_NODE_THEMATIC_BREAK @@ -86,6 +93,7 @@ typedef enum { typedef struct cmark_node cmark_node; typedef struct cmark_parser cmark_parser; typedef struct cmark_iter cmark_iter; +typedef struct cmark_syntax_extension cmark_syntax_extension; /** * ## Custom memory allocator support @@ -100,6 +108,70 @@ typedef struct cmark_mem { void (*free)(void *); } cmark_mem; +/** The default memory allocator; uses the system's calloc, + * realloc and free. + */ +CMARK_GFM_EXPORT +cmark_mem *cmark_get_default_mem_allocator(void); + +/** An arena allocator; uses system calloc to allocate large + * slabs of memory. Memory in these slabs is not reused at all. + */ +CMARK_GFM_EXPORT +cmark_mem *cmark_get_arena_mem_allocator(void); + +/** Resets the arena allocator, quickly returning all used memory + * to the operating system. + */ +CMARK_GFM_EXPORT +void cmark_arena_reset(void); + +/** Callback for freeing user data with a 'cmark_mem' context. + */ +typedef void (*cmark_free_func) (cmark_mem *mem, void *user_data); + + +/* + * ## Basic data structures + * + * To keep dependencies to the strict minimum, libcmark implements + * its own versions of "classic" data structures. + */ + +/** + * ### Linked list + */ + +/** A generic singly linked list. + */ +typedef struct _cmark_llist +{ + struct _cmark_llist *next; + void *data; +} cmark_llist; + +/** Append an element to the linked list, return the possibly modified + * head of the list. + */ +CMARK_GFM_EXPORT +cmark_llist * cmark_llist_append (cmark_mem * mem, + cmark_llist * head, + void * data); + +/** Free the list starting with 'head', calling 'free_func' with the + * data pointer of each of its elements + */ +CMARK_GFM_EXPORT +void cmark_llist_free_full (cmark_mem * mem, + cmark_llist * head, + cmark_free_func free_func); + +/** Free the list starting with 'head' + */ +CMARK_GFM_EXPORT +void cmark_llist_free (cmark_mem * mem, + cmark_llist * head); + /** * ## Creating and Destroying Nodes */ @@ -108,18 +180,25 @@ typedef struct cmark_mem { * other required properties, which it is the caller's responsibility * to assign. */ -CMARK_EXPORT cmark_node *cmark_node_new(cmark_node_type type); +CMARK_GFM_EXPORT cmark_node *cmark_node_new(cmark_node_type type); /** Same as `cmark_node_new`, but explicitly listing the memory * allocator used to allocate the node. Note: be sure to use the same * allocator for every node in a tree, or bad things can happen. */ -CMARK_EXPORT cmark_node *cmark_node_new_with_mem(cmark_node_type type, +CMARK_GFM_EXPORT cmark_node *cmark_node_new_with_mem(cmark_node_type type, cmark_mem *mem); +CMARK_GFM_EXPORT cmark_node *cmark_node_new_with_ext(cmark_node_type type, + cmark_syntax_extension *extension); + +CMARK_GFM_EXPORT cmark_node *cmark_node_new_with_mem_and_ext(cmark_node_type type, + cmark_mem *mem, + cmark_syntax_extension *extension); + /** Frees the memory allocated for a node and any children. */ -CMARK_EXPORT void cmark_node_free(cmark_node *node); +CMARK_GFM_EXPORT void cmark_node_free(cmark_node *node); /** * ## Tree Traversal @@ -128,24 +207,24 @@ CMARK_EXPORT void cmark_node_free(cmark_node *node); /** Returns the next node in the sequence after 'node', or NULL if * there is none. */ -CMARK_EXPORT cmark_node *cmark_node_next(cmark_node *node); +CMARK_GFM_EXPORT cmark_node *cmark_node_next(cmark_node *node); /** Returns the previous node in the sequence after 'node', or NULL if * there is none. */ -CMARK_EXPORT cmark_node *cmark_node_previous(cmark_node *node); +CMARK_GFM_EXPORT cmark_node *cmark_node_previous(cmark_node *node); /** Returns the parent of 'node', or NULL if there is none. */ -CMARK_EXPORT cmark_node *cmark_node_parent(cmark_node *node); +CMARK_GFM_EXPORT cmark_node *cmark_node_parent(cmark_node *node); /** Returns the first child of 'node', or NULL if 'node' has no children. */ -CMARK_EXPORT cmark_node *cmark_node_first_child(cmark_node *node); +CMARK_GFM_EXPORT cmark_node *cmark_node_first_child(cmark_node *node); /** Returns the last child of 'node', or NULL if 'node' has no children. */ -CMARK_EXPORT cmark_node *cmark_node_last_child(cmark_node *node); +CMARK_GFM_EXPORT cmark_node *cmark_node_last_child(cmark_node *node); /** * ## Iterator @@ -204,40 +283,40 @@ typedef enum { * The memory allocated for the iterator should be released using * 'cmark_iter_free' when it is no longer needed. */ -CMARK_EXPORT +CMARK_GFM_EXPORT cmark_iter *cmark_iter_new(cmark_node *root); /** Frees the memory allocated for an iterator. */ -CMARK_EXPORT +CMARK_GFM_EXPORT void cmark_iter_free(cmark_iter *iter); /** Advances to the next node and returns the event type (`CMARK_EVENT_ENTER`, * `CMARK_EVENT_EXIT` or `CMARK_EVENT_DONE`). */ -CMARK_EXPORT +CMARK_GFM_EXPORT cmark_event_type cmark_iter_next(cmark_iter *iter); /** Returns the current node. */ -CMARK_EXPORT +CMARK_GFM_EXPORT cmark_node *cmark_iter_get_node(cmark_iter *iter); /** Returns the current event type. */ -CMARK_EXPORT +CMARK_GFM_EXPORT cmark_event_type cmark_iter_get_event_type(cmark_iter *iter); /** Returns the root node. */ -CMARK_EXPORT +CMARK_GFM_EXPORT cmark_node *cmark_iter_get_root(cmark_iter *iter); /** Resets the iterator so that the current node is 'current' and * the event type is 'event_type'. The new current node must be a * descendant of the root node or the root node itself. */ -CMARK_EXPORT +CMARK_GFM_EXPORT void cmark_iter_reset(cmark_iter *iter, cmark_node *current, cmark_event_type event_type); @@ -247,37 +326,47 @@ void cmark_iter_reset(cmark_iter *iter, cmark_node *current, /** Returns the user data of 'node'. */ -CMARK_EXPORT void *cmark_node_get_user_data(cmark_node *node); +CMARK_GFM_EXPORT void *cmark_node_get_user_data(cmark_node *node); /** Sets arbitrary user data for 'node'. Returns 1 on success, * 0 on failure. */ -CMARK_EXPORT int cmark_node_set_user_data(cmark_node *node, void *user_data); +CMARK_GFM_EXPORT int cmark_node_set_user_data(cmark_node *node, void *user_data); + +/** Set free function for user data */ +CMARK_GFM_EXPORT +int cmark_node_set_user_data_free_func(cmark_node *node, + cmark_free_func free_func); /** Returns the type of 'node', or `CMARK_NODE_NONE` on error. */ -CMARK_EXPORT cmark_node_type cmark_node_get_type(cmark_node *node); +CMARK_GFM_EXPORT cmark_node_type cmark_node_get_type(cmark_node *node); /** Like 'cmark_node_get_type', but returns a string representation of the type, or `""`. */ -CMARK_EXPORT +CMARK_GFM_EXPORT const char *cmark_node_get_type_string(cmark_node *node); /** Returns the string contents of 'node', or an empty string if none is set. Returns NULL if called on a node that does not have string content. */ -CMARK_EXPORT const char *cmark_node_get_literal(cmark_node *node); +CMARK_GFM_EXPORT const char *cmark_node_get_literal(cmark_node *node); + +/** Returns the number of backtick characters used to open the + node if it is an inline code span, otherwise returns 0. + */ +CMARK_GFM_EXPORT int cmark_node_get_backtick_count(cmark_node *node); /** Sets the string contents of 'node'. Returns 1 on success, * 0 on failure. */ -CMARK_EXPORT int cmark_node_set_literal(cmark_node *node, const char *content); +CMARK_GFM_EXPORT int cmark_node_set_literal(cmark_node *node, const char *content); /** Returns the heading level of 'node', or 0 if 'node' is not a heading. */ -CMARK_EXPORT int cmark_node_get_heading_level(cmark_node *node); +CMARK_GFM_EXPORT int cmark_node_get_heading_level(cmark_node *node); /* For backwards compatibility */ #define cmark_node_get_header_level cmark_node_get_heading_level @@ -285,117 +374,137 @@ CMARK_EXPORT int cmark_node_get_heading_level(cmark_node *node); /** Sets the heading level of 'node', returning 1 on success and 0 on error. */ -CMARK_EXPORT int cmark_node_set_heading_level(cmark_node *node, int level); +CMARK_GFM_EXPORT int cmark_node_set_heading_level(cmark_node *node, int level); /** Returns the list type of 'node', or `CMARK_NO_LIST` if 'node' * is not a list. */ -CMARK_EXPORT cmark_list_type cmark_node_get_list_type(cmark_node *node); +CMARK_GFM_EXPORT cmark_list_type cmark_node_get_list_type(cmark_node *node); /** Sets the list type of 'node', returning 1 on success and 0 on error. */ -CMARK_EXPORT int cmark_node_set_list_type(cmark_node *node, +CMARK_GFM_EXPORT int cmark_node_set_list_type(cmark_node *node, cmark_list_type type); /** Returns the list delimiter type of 'node', or `CMARK_NO_DELIM` if 'node' * is not a list. */ -CMARK_EXPORT cmark_delim_type cmark_node_get_list_delim(cmark_node *node); +CMARK_GFM_EXPORT cmark_delim_type cmark_node_get_list_delim(cmark_node *node); /** Sets the list delimiter type of 'node', returning 1 on success and 0 * on error. */ -CMARK_EXPORT int cmark_node_set_list_delim(cmark_node *node, +CMARK_GFM_EXPORT int cmark_node_set_list_delim(cmark_node *node, cmark_delim_type delim); /** Returns starting number of 'node', if it is an ordered list, otherwise 0. */ -CMARK_EXPORT int cmark_node_get_list_start(cmark_node *node); +CMARK_GFM_EXPORT int cmark_node_get_list_start(cmark_node *node); /** Sets starting number of 'node', if it is an ordered list. Returns 1 * on success, 0 on failure. */ -CMARK_EXPORT int cmark_node_set_list_start(cmark_node *node, int start); +CMARK_GFM_EXPORT int cmark_node_set_list_start(cmark_node *node, int start); /** Returns 1 if 'node' is a tight list, 0 otherwise. */ -CMARK_EXPORT int cmark_node_get_list_tight(cmark_node *node); +CMARK_GFM_EXPORT int cmark_node_get_list_tight(cmark_node *node); /** Sets the "tightness" of a list. Returns 1 on success, 0 on failure. */ -CMARK_EXPORT int cmark_node_set_list_tight(cmark_node *node, int tight); +CMARK_GFM_EXPORT int cmark_node_set_list_tight(cmark_node *node, int tight); /** Returns the info string from a fenced code block. */ -CMARK_EXPORT const char *cmark_node_get_fence_info(cmark_node *node); +CMARK_GFM_EXPORT const char *cmark_node_get_fence_info(cmark_node *node); /** Sets the info string in a fenced code block, returning 1 on * success and 0 on failure. */ -CMARK_EXPORT int cmark_node_set_fence_info(cmark_node *node, const char *info); +CMARK_GFM_EXPORT int cmark_node_set_fence_info(cmark_node *node, const char *info); + +/** Sets code blocks fencing details + */ +CMARK_GFM_EXPORT int cmark_node_set_fenced(cmark_node * node, int fenced, + int length, int offset, char character); + +/** Returns code blocks fencing details + */ +CMARK_GFM_EXPORT int cmark_node_get_fenced(cmark_node *node, int *length, int *offset, char *character); /** Returns the URL of a link or image 'node', or an empty string if no URL is set. Returns NULL if called on a node that is not a link or image. */ -CMARK_EXPORT const char *cmark_node_get_url(cmark_node *node); +CMARK_GFM_EXPORT const char *cmark_node_get_url(cmark_node *node); /** Sets the URL of a link or image 'node'. Returns 1 on success, * 0 on failure. */ -CMARK_EXPORT int cmark_node_set_url(cmark_node *node, const char *url); +CMARK_GFM_EXPORT int cmark_node_set_url(cmark_node *node, const char *url); /** Returns the title of a link or image 'node', or an empty string if no title is set. Returns NULL if called on a node that is not a link or image. */ -CMARK_EXPORT const char *cmark_node_get_title(cmark_node *node); +CMARK_GFM_EXPORT const char *cmark_node_get_title(cmark_node *node); /** Sets the title of a link or image 'node'. Returns 1 on success, * 0 on failure. */ -CMARK_EXPORT int cmark_node_set_title(cmark_node *node, const char *title); +CMARK_GFM_EXPORT int cmark_node_set_title(cmark_node *node, const char *title); + +/** Returns the attributes of an attribute 'node', or an empty string + if no attributes are set. Returns NULL if called on a node that is + not an attribute. + */ +CMARK_GFM_EXPORT const char *cmark_node_get_attributes(cmark_node *node); + +/** Sets the attributes of an attribute 'node'. Returns 1 on success, + * 0 on failure. + */ +CMARK_GFM_EXPORT int cmark_node_set_attributes(cmark_node *node, const char *attributes); /** Returns the literal "on enter" text for a custom 'node', or an empty string if no on_enter is set. Returns NULL if called on a non-custom node. */ -CMARK_EXPORT const char *cmark_node_get_on_enter(cmark_node *node); +CMARK_GFM_EXPORT const char *cmark_node_get_on_enter(cmark_node *node); /** Sets the literal text to render "on enter" for a custom 'node'. Any children of the node will be rendered after this text. Returns 1 on success 0 on failure. */ -CMARK_EXPORT int cmark_node_set_on_enter(cmark_node *node, +CMARK_GFM_EXPORT int cmark_node_set_on_enter(cmark_node *node, const char *on_enter); /** Returns the literal "on exit" text for a custom 'node', or an empty string if no on_exit is set. Returns NULL if called on a non-custom node. */ -CMARK_EXPORT const char *cmark_node_get_on_exit(cmark_node *node); +CMARK_GFM_EXPORT const char *cmark_node_get_on_exit(cmark_node *node); /** Sets the literal text to render "on exit" for a custom 'node'. Any children of the node will be rendered before this text. Returns 1 on success 0 on failure. */ -CMARK_EXPORT int cmark_node_set_on_exit(cmark_node *node, const char *on_exit); +CMARK_GFM_EXPORT int cmark_node_set_on_exit(cmark_node *node, const char *on_exit); /** Returns the line on which 'node' begins. */ -CMARK_EXPORT int cmark_node_get_start_line(cmark_node *node); +CMARK_GFM_EXPORT int cmark_node_get_start_line(cmark_node *node); /** Returns the column at which 'node' begins. */ -CMARK_EXPORT int cmark_node_get_start_column(cmark_node *node); +CMARK_GFM_EXPORT int cmark_node_get_start_column(cmark_node *node); /** Returns the line on which 'node' ends. */ -CMARK_EXPORT int cmark_node_get_end_line(cmark_node *node); +CMARK_GFM_EXPORT int cmark_node_get_end_line(cmark_node *node); /** Returns the column at which 'node' ends. */ -CMARK_EXPORT int cmark_node_get_end_column(cmark_node *node); +CMARK_GFM_EXPORT int cmark_node_get_end_column(cmark_node *node); /** * ## Tree Manipulation @@ -404,36 +513,40 @@ CMARK_EXPORT int cmark_node_get_end_column(cmark_node *node); /** Unlinks a 'node', removing it from the tree, but not freeing its * memory. (Use 'cmark_node_free' for that.) */ -CMARK_EXPORT void cmark_node_unlink(cmark_node *node); +CMARK_GFM_EXPORT void cmark_node_unlink(cmark_node *node); /** Inserts 'sibling' before 'node'. Returns 1 on success, 0 on failure. */ -CMARK_EXPORT int cmark_node_insert_before(cmark_node *node, +CMARK_GFM_EXPORT int cmark_node_insert_before(cmark_node *node, cmark_node *sibling); /** Inserts 'sibling' after 'node'. Returns 1 on success, 0 on failure. */ -CMARK_EXPORT int cmark_node_insert_after(cmark_node *node, cmark_node *sibling); +CMARK_GFM_EXPORT int cmark_node_insert_after(cmark_node *node, cmark_node *sibling); /** Replaces 'oldnode' with 'newnode' and unlinks 'oldnode' (but does * not free its memory). * Returns 1 on success, 0 on failure. */ -CMARK_EXPORT int cmark_node_replace(cmark_node *oldnode, cmark_node *newnode); +CMARK_GFM_EXPORT int cmark_node_replace(cmark_node *oldnode, cmark_node *newnode); /** Adds 'child' to the beginning of the children of 'node'. * Returns 1 on success, 0 on failure. */ -CMARK_EXPORT int cmark_node_prepend_child(cmark_node *node, cmark_node *child); +CMARK_GFM_EXPORT int cmark_node_prepend_child(cmark_node *node, cmark_node *child); /** Adds 'child' to the end of the children of 'node'. * Returns 1 on success, 0 on failure. */ -CMARK_EXPORT int cmark_node_append_child(cmark_node *node, cmark_node *child); +CMARK_GFM_EXPORT int cmark_node_append_child(cmark_node *node, cmark_node *child); /** Consolidates adjacent text nodes. */ -CMARK_EXPORT void cmark_consolidate_text_nodes(cmark_node *root); +CMARK_GFM_EXPORT void cmark_consolidate_text_nodes(cmark_node *root); + +/** Ensures a node and all its children own their own chunk memory. + */ +CMARK_GFM_EXPORT void cmark_node_own(cmark_node *root); /** * ## Parsing @@ -459,27 +572,27 @@ CMARK_EXPORT void cmark_consolidate_text_nodes(cmark_node *root); /** Creates a new parser object. */ -CMARK_EXPORT +CMARK_GFM_EXPORT cmark_parser *cmark_parser_new(int options); /** Creates a new parser object with the given memory allocator */ -CMARK_EXPORT +CMARK_GFM_EXPORT cmark_parser *cmark_parser_new_with_mem(int options, cmark_mem *mem); /** Frees memory allocated for a parser object. */ -CMARK_EXPORT +CMARK_GFM_EXPORT void cmark_parser_free(cmark_parser *parser); /** Feeds a string of length 'len' to 'parser'. */ -CMARK_EXPORT +CMARK_GFM_EXPORT void cmark_parser_feed(cmark_parser *parser, const char *buffer, size_t len); /** Finish parsing and return a pointer to a tree of nodes. */ -CMARK_EXPORT +CMARK_GFM_EXPORT cmark_node *cmark_parser_finish(cmark_parser *parser); /** Parse a CommonMark document in 'buffer' of length 'len'. @@ -487,14 +600,14 @@ cmark_node *cmark_parser_finish(cmark_parser *parser); * the node tree should be released using 'cmark_node_free' * when it is no longer needed. */ -CMARK_EXPORT +CMARK_GFM_EXPORT cmark_node *cmark_parse_document(const char *buffer, size_t len, int options); /** Parse a CommonMark document in file 'f', returning a pointer to * a tree of nodes. The memory allocated for the node tree should be * released using 'cmark_node_free' when it is no longer needed. */ -CMARK_EXPORT +CMARK_GFM_EXPORT cmark_node *cmark_parse_file(FILE *f, int options); /** @@ -504,34 +617,76 @@ cmark_node *cmark_parse_file(FILE *f, int options); /** Render a 'node' tree as XML. It is the caller's responsibility * to free the returned buffer. */ -CMARK_EXPORT +CMARK_GFM_EXPORT char *cmark_render_xml(cmark_node *root, int options); +/** As for 'cmark_render_xml', but specifying the allocator to use for + * the resulting string. + */ +CMARK_GFM_EXPORT +char *cmark_render_xml_with_mem(cmark_node *root, int options, cmark_mem *mem); + /** Render a 'node' tree as an HTML fragment. It is up to the user * to add an appropriate header and footer. It is the caller's * responsibility to free the returned buffer. */ -CMARK_EXPORT -char *cmark_render_html(cmark_node *root, int options); +CMARK_GFM_EXPORT +char *cmark_render_html(cmark_node *root, int options, cmark_llist *extensions); + +/** As for 'cmark_render_html', but specifying the allocator to use for + * the resulting string. + */ +CMARK_GFM_EXPORT +char *cmark_render_html_with_mem(cmark_node *root, int options, cmark_llist *extensions, cmark_mem *mem); /** Render a 'node' tree as a groff man page, without the header. * It is the caller's responsibility to free the returned buffer. */ -CMARK_EXPORT +CMARK_GFM_EXPORT char *cmark_render_man(cmark_node *root, int options, int width); +/** As for 'cmark_render_man', but specifying the allocator to use for + * the resulting string. + */ +CMARK_GFM_EXPORT +char *cmark_render_man_with_mem(cmark_node *root, int options, int width, cmark_mem *mem); + /** Render a 'node' tree as a commonmark document. * It is the caller's responsibility to free the returned buffer. */ -CMARK_EXPORT +CMARK_GFM_EXPORT char *cmark_render_commonmark(cmark_node *root, int options, int width); +/** As for 'cmark_render_commonmark', but specifying the allocator to use for + * the resulting string. + */ +CMARK_GFM_EXPORT +char *cmark_render_commonmark_with_mem(cmark_node *root, int options, int width, cmark_mem *mem); + +/** Render a 'node' tree as a plain text document. + * It is the caller's responsibility to free the returned buffer. + */ +CMARK_GFM_EXPORT +char *cmark_render_plaintext(cmark_node *root, int options, int width); + +/** As for 'cmark_render_plaintext', but specifying the allocator to use for + * the resulting string. + */ +CMARK_GFM_EXPORT +char *cmark_render_plaintext_with_mem(cmark_node *root, int options, int width, cmark_mem *mem); + /** Render a 'node' tree as a LaTeX document. * It is the caller's responsibility to free the returned buffer. */ -CMARK_EXPORT +CMARK_GFM_EXPORT char *cmark_render_latex(cmark_node *root, int options, int width); +/** As for 'cmark_render_latex', but specifying the allocator to use for + * the resulting string. + */ +CMARK_GFM_EXPORT +char *cmark_render_latex_with_mem(cmark_node *root, int options, int width, cmark_mem *mem); + /** * ## Options */ @@ -587,6 +742,44 @@ char *cmark_render_latex(cmark_node *root, int options, int width); */ #define CMARK_OPT_SMART (1 << 10) +/** Use GitHub-style
       tags for code blocks instead of 
      .
      + */
      +#define CMARK_OPT_GITHUB_PRE_LANG (1 << 11)
      +
      +/** Be liberal in interpreting inline HTML tags.
      + */
      +#define CMARK_OPT_LIBERAL_HTML_TAG (1 << 12)
      +
      +/** Parse footnotes.
      + */
      +#define CMARK_OPT_FOOTNOTES (1 << 13)
      +
      +/** Only parse strikethroughs if surrounded by exactly 2 tildes.
      + * Gives some compatibility with redcarpet.
      + */
      +#define CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE (1 << 14)
      +
      +/** Use style attributes to align table cells instead of align attributes.
      + */
      +#define CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES (1 << 15)
      +
      +/** Include the remainder of the info string in code blocks in
      + * a separate attribute.
      + */
      +#define CMARK_OPT_FULL_INFO_STRING (1 << 16)
      +
      +/** Parse only inline markdown directives. Block directives will not be
      + * parsed (their literal representations will remain in the output).
      + */
      +#define CMARK_OPT_INLINE_ONLY (1 << 18)
      +
      +/** Parse the markdown input without removing preceding/trailing whitespace and
      + * without converting newline characters to breaks. Using this option also
      + * enables the CMARK_OPT_INLINE_ONLY option.
      + */
      +#define CMARK_OPT_PRESERVE_WHITESPACE ((1 << 19) | CMARK_OPT_INLINE_ONLY)
      +
       /**
        * ## Version information
        */
      @@ -600,13 +793,13 @@ char *cmark_render_latex(cmark_node *root, int options, int width);
        *
        * In hexadecimal format, the number 0x010203 represents version 1.2.3.
        */
      -CMARK_EXPORT
      +CMARK_GFM_EXPORT
       int cmark_version(void);
       
       /** The library version string for runtime checks. Also available as
        * macro CMARK_VERSION_STRING for compile time checks.
        */
      -CMARK_EXPORT
      +CMARK_GFM_EXPORT
       const char *cmark_version_string(void);
       
       /** # AUTHORS
      @@ -643,6 +836,8 @@ const char *cmark_version_string(void);
       #define PAREN_DELIM CMARK_PAREN_DELIM
       #endif
       
      +typedef int32_t bufsize_t;
      +
       #ifdef __cplusplus
       }
       #endif
      diff --git a/src/include/cmark-gfm_config.h b/src/include/cmark-gfm_config.h
      new file mode 100644
      index 000000000..1f96cc558
      --- /dev/null
      +++ b/src/include/cmark-gfm_config.h
      @@ -0,0 +1,78 @@
      +#ifndef CMARK_CONFIG_H
      +#define CMARK_CONFIG_H
      +
      +#ifdef __cplusplus
      +extern "C" {
      +#endif
      +
      +#define HAVE_STDBOOL_H
      +
      +#ifdef HAVE_STDBOOL_H
      +  #include 
      +#elif !defined(__cplusplus)
      +  typedef char bool;
      +#endif
      +
      +#define HAVE___BUILTIN_EXPECT
      +
      +#define HAVE___ATTRIBUTE__
      +
      +#define CMARK_THREADING
      +
      +#ifdef HAVE___ATTRIBUTE__
      +  #define CMARK_ATTRIBUTE(list) __attribute__ (list)
      +#else
      +  #define CMARK_ATTRIBUTE(list)
      +#endif
      +
      +#ifndef CMARK_INLINE
      +  #if defined(_MSC_VER) && !defined(__cplusplus)
      +    #define CMARK_INLINE __inline
      +  #else
      +    #define CMARK_INLINE inline
      +  #endif
      +#endif
      +
      +/* snprintf and vsnprintf fallbacks for MSVC before 2015,
      +   due to Valentin Milea http://stackoverflow.com/questions/2915672/
      +*/
      +
      +#if defined(_MSC_VER) && _MSC_VER < 1900
      +
      +#include 
      +#include 
      +
      +#define snprintf c99_snprintf
      +#define vsnprintf c99_vsnprintf
      +
      +CMARK_INLINE int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
      +{
      +    int count = -1;
      +
      +    if (size != 0)
      +        count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
      +    if (count == -1)
      +        count = _vscprintf(format, ap);
      +
      +    return count;
      +}
      +
      +CMARK_INLINE int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
      +{
      +    int count;
      +    va_list ap;
      +
      +    va_start(ap, format);
      +    count = c99_vsnprintf(outBuf, size, format, ap);
      +    va_end(ap);
      +
      +    return count;
      +}
      +
      +#endif
      +
      +#ifdef __cplusplus
      +}
      +#endif
      +
      +#endif
      diff --git a/src/include/cmark-gfm_export.h b/src/include/cmark-gfm_export.h
      new file mode 100644
      index 000000000..699d737f7
      --- /dev/null
      +++ b/src/include/cmark-gfm_export.h
      @@ -0,0 +1,42 @@
      +
      +#ifndef CMARK_GFM_EXPORT_H
      +#define CMARK_GFM_EXPORT_H
      +
      +#ifdef CMARK_GFM_STATIC_DEFINE
      +#  define CMARK_GFM_EXPORT
      +#  define CMARK_GFM_NO_EXPORT
      +#else
      +#  ifndef CMARK_GFM_EXPORT
      +#    ifdef libcmark_gfm_EXPORTS
      +        /* We are building this library */
      +#      define CMARK_GFM_EXPORT __attribute__((visibility("default")))
      +#    else
      +        /* We are using this library */
      +#      define CMARK_GFM_EXPORT __attribute__((visibility("default")))
      +#    endif
      +#  endif
      +
      +#  ifndef CMARK_GFM_NO_EXPORT
      +#    define CMARK_GFM_NO_EXPORT __attribute__((visibility("hidden")))
      +#  endif
      +#endif
      +
      +#ifndef CMARK_GFM_DEPRECATED
      +#  define CMARK_GFM_DEPRECATED __attribute__ ((__deprecated__))
      +#endif
      +
      +#ifndef CMARK_GFM_DEPRECATED_EXPORT
      +#  define CMARK_GFM_DEPRECATED_EXPORT CMARK_GFM_EXPORT CMARK_GFM_DEPRECATED
      +#endif
      +
      +#ifndef CMARK_GFM_DEPRECATED_NO_EXPORT
      +#  define CMARK_GFM_DEPRECATED_NO_EXPORT CMARK_GFM_NO_EXPORT CMARK_GFM_DEPRECATED
      +#endif
      +
      +#if 0 /* DEFINE_NO_DEPRECATED */
      +#  ifndef CMARK_GFM_NO_DEPRECATED
      +#    define CMARK_GFM_NO_DEPRECATED
      +#  endif
      +#endif
      +
      +#endif /* CMARK_GFM_EXPORT_H */
      diff --git a/src/include/cmark-gfm_version.h b/src/include/cmark-gfm_version.h
      new file mode 100644
      index 000000000..7e7bd823d
      --- /dev/null
      +++ b/src/include/cmark-gfm_version.h
      @@ -0,0 +1,7 @@
      +#ifndef CMARK_GFM_VERSION_H
      +#define CMARK_GFM_VERSION_H
      +
      +#define CMARK_GFM_VERSION ((0 << 24) | (29 << 16) | (0 << 8) | 0)
      +#define CMARK_GFM_VERSION_STRING "0.29.0.gfm.0"
      +
      +#endif
      diff --git a/src/cmark_ctype.h b/src/include/cmark_ctype.h
      similarity index 77%
      rename from src/cmark_ctype.h
      rename to src/include/cmark_ctype.h
      index 9a0761851..67c1cb037 100644
      --- a/src/cmark_ctype.h
      +++ b/src/include/cmark_ctype.h
      @@ -5,18 +5,25 @@
       extern "C" {
       #endif
       
      +#include "cmark-gfm_export.h"
      +
       /** Locale-independent versions of functions from ctype.h.
        * We want cmark to behave the same no matter what the system locale.
        */
       
      +CMARK_GFM_EXPORT
       int cmark_isspace(char c);
       
      +CMARK_GFM_EXPORT
       int cmark_ispunct(char c);
       
      +CMARK_GFM_EXPORT
       int cmark_isalnum(char c);
       
      +CMARK_GFM_EXPORT
       int cmark_isdigit(char c);
       
      +CMARK_GFM_EXPORT
       int cmark_isalpha(char c);
       
       #ifdef __cplusplus
      diff --git a/src/include/footnotes.h b/src/include/footnotes.h
      new file mode 100644
      index 000000000..43dd64ff6
      --- /dev/null
      +++ b/src/include/footnotes.h
      @@ -0,0 +1,25 @@
      +#ifndef CMARK_FOOTNOTES_H
      +#define CMARK_FOOTNOTES_H
      +
      +#include "map.h"
      +
      +#ifdef __cplusplus
      +extern "C" {
      +#endif
      +
      +struct cmark_footnote {
      +  cmark_map_entry entry;
      +  cmark_node *node;
      +  unsigned int ix;
      +};
      +
      +typedef struct cmark_footnote cmark_footnote;
      +
      +void cmark_footnote_create(cmark_map *map, cmark_node *node);
      +cmark_map *cmark_footnote_map_new(cmark_mem *mem);
      +
      +#ifdef __cplusplus
      +}
      +#endif
      +
      +#endif
      diff --git a/src/houdini.h b/src/include/houdini.h
      similarity index 66%
      rename from src/houdini.h
      rename to src/include/houdini.h
      index f738e8243..ff3c0887a 100644
      --- a/src/houdini.h
      +++ b/src/include/houdini.h
      @@ -6,7 +6,7 @@ extern "C" {
       #endif
       
       #include 
      -#include "config.h"
      +#include "cmark-gfm_config.h"
       #include "buffer.h"
       
       #ifdef HAVE___BUILTIN_EXPECT
      @@ -31,17 +31,23 @@ extern "C" {
       #define HOUDINI_ESCAPED_SIZE(x) (((x)*12) / 10)
       #define HOUDINI_UNESCAPED_SIZE(x) (x)
       
      -extern bufsize_t houdini_unescape_ent(cmark_strbuf *ob, const uint8_t *src,
      +CMARK_GFM_EXPORT
      +bufsize_t houdini_unescape_ent(cmark_strbuf *ob, const uint8_t *src,
                                             bufsize_t size);
      -extern int houdini_escape_html(cmark_strbuf *ob, const uint8_t *src,
      +CMARK_GFM_EXPORT
      +int houdini_escape_html(cmark_strbuf *ob, const uint8_t *src,
                                      bufsize_t size);
      -extern int houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src,
      +CMARK_GFM_EXPORT
      +int houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src,
                                       bufsize_t size, int secure);
      -extern int houdini_unescape_html(cmark_strbuf *ob, const uint8_t *src,
      +CMARK_GFM_EXPORT
      +int houdini_unescape_html(cmark_strbuf *ob, const uint8_t *src,
                                        bufsize_t size);
      -extern void houdini_unescape_html_f(cmark_strbuf *ob, const uint8_t *src,
      +CMARK_GFM_EXPORT
      +void houdini_unescape_html_f(cmark_strbuf *ob, const uint8_t *src,
                                           bufsize_t size);
      -extern int houdini_escape_href(cmark_strbuf *ob, const uint8_t *src,
      +CMARK_GFM_EXPORT
      +int houdini_escape_href(cmark_strbuf *ob, const uint8_t *src,
                                      bufsize_t size);
       
       #ifdef __cplusplus
      diff --git a/src/include/html.h b/src/include/html.h
      new file mode 100644
      index 000000000..aeba7bcda
      --- /dev/null
      +++ b/src/include/html.h
      @@ -0,0 +1,27 @@
      +#ifndef CMARK_HTML_H
      +#define CMARK_HTML_H
      +
      +#include "buffer.h"
      +#include "node.h"
      +
      +CMARK_INLINE
      +static void cmark_html_render_cr(cmark_strbuf *html) {
      +  if (html->size && html->ptr[html->size - 1] != '\n')
      +    cmark_strbuf_putc(html, '\n');
      +}
      +
      +#define BUFFER_SIZE 100
      +
      +CMARK_INLINE 
      +static void cmark_html_render_sourcepos(cmark_node *node, cmark_strbuf *html, int options) {
      +  char buffer[BUFFER_SIZE];
      +  if (CMARK_OPT_SOURCEPOS & options) {
      +    snprintf(buffer, BUFFER_SIZE, " data-sourcepos=\"%d:%d-%d:%d\"",
      +             cmark_node_get_start_line(node), cmark_node_get_start_column(node),
      +             cmark_node_get_end_line(node), cmark_node_get_end_column(node));
      +    cmark_strbuf_puts(html, buffer);
      +  }
      +}
      +
      +
      +#endif
      diff --git a/src/include/inlines.h b/src/include/inlines.h
      new file mode 100644
      index 000000000..d323af994
      --- /dev/null
      +++ b/src/include/inlines.h
      @@ -0,0 +1,38 @@
      +#ifndef CMARK_INLINES_H
      +#define CMARK_INLINES_H
      +
      +#ifdef __cplusplus
      +extern "C" {
      +#endif
      +
      +#include 
      +#include "cmark-gfm_config.h"
      +#include "references.h"
      +
      +cmark_chunk cmark_clean_url(cmark_mem *mem, cmark_chunk *url);
      +cmark_chunk cmark_clean_title(cmark_mem *mem, cmark_chunk *title);
      +cmark_chunk cmark_clean_attributes(cmark_mem *mem, cmark_chunk *attributes);
      +
      +CMARK_GFM_EXPORT
      +void cmark_parse_inlines(cmark_parser *parser,
      +                         cmark_node *parent,
      +                         cmark_map *refmap,
      +                         int options);
      +
      +bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input,
      +                                       cmark_map *refmap);
      +
      +bufsize_t cmark_parse_reference_attributes_inline(cmark_mem *mem, cmark_chunk *input,
      +                                                  cmark_map *refmap);
      +
      +void cmark_inlines_add_special_character(cmark_parser *parser, unsigned char c, bool emphasis);
      +void cmark_inlines_remove_special_character(cmark_parser *parser, unsigned char c, bool emphasis);
      +
      +void cmark_set_default_skip_chars(int8_t **skip_chars, bool use_memcpy);
      +void cmark_set_default_special_chars(int8_t **special_chars, bool use_memcpy);
      +
      +#ifdef __cplusplus
      +}
      +#endif
      +
      +#endif
      diff --git a/src/iterator.h b/src/include/iterator.h
      similarity index 93%
      rename from src/iterator.h
      rename to src/include/iterator.h
      index 30ce76f51..47e10e57b 100644
      --- a/src/iterator.h
      +++ b/src/include/iterator.h
      @@ -5,7 +5,7 @@
       extern "C" {
       #endif
       
      -#include "cmark.h"
      +#include "cmark-gfm.h"
       
       typedef struct {
         cmark_event_type ev_type;
      diff --git a/src/include/map.h b/src/include/map.h
      new file mode 100644
      index 000000000..aa4c06e56
      --- /dev/null
      +++ b/src/include/map.h
      @@ -0,0 +1,41 @@
      +#ifndef CMARK_MAP_H
      +#define CMARK_MAP_H
      +
      +#include "chunk.h"
      +
      +#ifdef __cplusplus
      +extern "C" {
      +#endif
      +
      +struct cmark_map_entry {
      +  struct cmark_map_entry *next;
      +  unsigned char *label;
      +  unsigned int age;
      +};
      +
      +typedef struct cmark_map_entry cmark_map_entry;
      +
      +struct cmark_map;
      +
      +typedef void (*cmark_map_free_f)(struct cmark_map *, cmark_map_entry *);
      +
      +struct cmark_map {
      +  cmark_mem *mem;
      +  cmark_map_entry *refs;
      +  cmark_map_entry **sorted;
      +  unsigned int size;
      +  cmark_map_free_f free;
      +};
      +
      +typedef struct cmark_map cmark_map;
      +
      +unsigned char *normalize_map_label(cmark_mem *mem, cmark_chunk *ref);
      +cmark_map *cmark_map_new(cmark_mem *mem, cmark_map_free_f free);
      +void cmark_map_free(cmark_map *map);
      +cmark_map_entry *cmark_map_lookup(cmark_map *map, cmark_chunk *label);
      +
      +#ifdef __cplusplus
      +}
      +#endif
      +
      +#endif
      diff --git a/src/include/module.modulemap b/src/include/module.modulemap
      new file mode 100644
      index 000000000..1fc033abb
      --- /dev/null
      +++ b/src/include/module.modulemap
      @@ -0,0 +1,25 @@
      +module cmark_gfm {
      +    umbrella header "cmark-gfm.h"
      +    header "cmark-gfm_config.h"
      +    header "cmark-gfm-extension_api.h"
      +    header "buffer.h"
      +    header "chunk.h"
      +    header "cmark_ctype.h"
      +    header "footnotes.h"
      +    header "houdini.h"
      +    header "html.h"
      +    header "inlines.h"
      +    header "iterator.h"
      +    header "map.h"
      +    header "mutex.h"
      +    header "node.h"
      +    header "parser.h"
      +    header "plugin.h"
      +    header "references.h"
      +    header "registry.h"
      +    header "render.h"
      +    header "scanners.h"
      +    header "syntax_extension.h"
      +    header "utf8.h"
      +    export *
      +}
      diff --git a/src/include/mutex.h b/src/include/mutex.h
      new file mode 100644
      index 000000000..7415e76de
      --- /dev/null
      +++ b/src/include/mutex.h
      @@ -0,0 +1,46 @@
      +#ifndef CMARK_MUTEX_H
      +#define CMARK_MUTEX_H
      +
      +#include "cmark-gfm_config.h"
      +
      +#ifdef CMARK_THREADING
      +
      +#include 
      +
      +#define CMARK_DEFINE_ONCE(NAME) static pthread_once_t NAME##_once = PTHREAD_ONCE_INIT;
      +
      +#define CMARK_RUN_ONCE(NAME, FUNC) pthread_once(&NAME##_once, FUNC)
      +
      +#define CMARK_DEFINE_LOCK(NAME) \
      +static pthread_mutex_t NAME##_lock; \
      +CMARK_DEFINE_ONCE(NAME); \
      +static void initialize_##NAME() { pthread_mutex_init(&NAME##_lock, NULL); }
      +
      +#define CMARK_INITIALIZE_AND_LOCK(NAME) \
      +CMARK_RUN_ONCE(NAME, initialize_##NAME); \
      +pthread_mutex_lock(&NAME##_lock);
      +
      +#define CMARK_UNLOCK(NAME) pthread_mutex_unlock(&NAME##_lock);
      +
      +#else // no threading support
      +
      +static CMARK_INLINE bool check_latch(int *latch) {
      +  if (!*latch) {
      +    *latch = 1;
      +    return true;
      +  } else {
      +    return false;
      +  }
      +}
      +
      +#define CMARK_DEFINE_LOCK(NAME)
      +#define CMARK_INITIALIZE_AND_LOCK(NAME)
      +#define CMARK_UNLOCK(NAME)
      +
      +#define CMARK_DEFINE_ONCE(NAME) static int NAME = 0;
      +
      +#define CMARK_RUN_ONCE(NAME, FUNC) if (check_latch(&NAME)) FUNC();
      +
      +#endif // CMARK_THREADING
      +
      +#endif // CMARK_MUTEX_H
      diff --git a/src/node.h b/src/include/node.h
      similarity index 59%
      rename from src/node.h
      rename to src/include/node.h
      index 216323060..e2c0216d1 100644
      --- a/src/node.h
      +++ b/src/include/node.h
      @@ -8,7 +8,8 @@ extern "C" {
       #include 
       #include 
       
      -#include "cmark.h"
      +#include "cmark-gfm.h"
      +#include "cmark-gfm-extension_api.h"
       #include "buffer.h"
       #include "chunk.h"
       
      @@ -20,6 +21,7 @@ typedef struct {
         cmark_delim_type delimiter;
         unsigned char bullet_char;
         bool tight;
      +  bool checked; // For task list extension
       } cmark_list;
       
       typedef struct {
      @@ -41,6 +43,10 @@ typedef struct {
         cmark_chunk title;
       } cmark_link;
       
      +typedef struct {
      +  cmark_chunk attributes;
      +} cmark_attribute;
      +
       typedef struct {
         cmark_chunk on_enter;
         cmark_chunk on_exit;
      @@ -62,6 +68,7 @@ struct cmark_node {
         struct cmark_node *last_child;
       
         void *user_data;
      +  cmark_free_func user_data_free_func;
       
         int start_line;
         int start_column;
      @@ -70,6 +77,9 @@ struct cmark_node {
         int internal_offset;
         uint16_t type;
         uint16_t flags;
      +  int backtick_count;
      +
      +  cmark_syntax_extension *extension;
       
         union {
           cmark_chunk literal;
      @@ -77,15 +87,35 @@ struct cmark_node {
           cmark_code code;
           cmark_heading heading;
           cmark_link link;
      +    cmark_attribute attribute;
           cmark_custom custom;
           int html_block_type;
      +    void *opaque;
         } as;
       };
       
       static CMARK_INLINE cmark_mem *cmark_node_mem(cmark_node *node) {
         return node->content.mem;
       }
      -CMARK_EXPORT int cmark_node_check(cmark_node *node, FILE *out);
      +CMARK_GFM_EXPORT int cmark_node_check(cmark_node *node, FILE *out);
      +
      +static CMARK_INLINE bool CMARK_NODE_TYPE_BLOCK_P(cmark_node_type node_type) {
      +	return (node_type & CMARK_NODE_TYPE_MASK) == CMARK_NODE_TYPE_BLOCK;
      +}
      +
      +static CMARK_INLINE bool CMARK_NODE_BLOCK_P(cmark_node *node) {
      +	return node != NULL && CMARK_NODE_TYPE_BLOCK_P((cmark_node_type) node->type);
      +}
      +
      +static CMARK_INLINE bool CMARK_NODE_TYPE_INLINE_P(cmark_node_type node_type) {
      +	return (node_type & CMARK_NODE_TYPE_MASK) == CMARK_NODE_TYPE_INLINE;
      +}
      +
      +static CMARK_INLINE bool CMARK_NODE_INLINE_P(cmark_node *node) {
      +	return node != NULL && CMARK_NODE_TYPE_INLINE_P((cmark_node_type) node->type);
      +}
      +
      +CMARK_GFM_EXPORT bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type);
       
       #ifdef __cplusplus
       }
      diff --git a/src/include/parser.h b/src/include/parser.h
      new file mode 100644
      index 000000000..ff24157d9
      --- /dev/null
      +++ b/src/include/parser.h
      @@ -0,0 +1,62 @@
      +#ifndef CMARK_PARSER_H
      +#define CMARK_PARSER_H
      +
      +#include 
      +#include 
      +#include "references.h"
      +#include "node.h"
      +#include "buffer.h"
      +
      +#ifdef __cplusplus
      +extern "C" {
      +#endif
      +
      +#define MAX_LINK_LABEL_LENGTH 1000
      +
      +struct cmark_parser {
      +  struct cmark_mem *mem;
      +  /* A hashtable of urls in the current document for cross-references */
      +  struct cmark_map *refmap;
      +  /* The root node of the parser, always a CMARK_NODE_DOCUMENT */
      +  struct cmark_node *root;
      +  /* The last open block after a line is fully processed */
      +  struct cmark_node *current;
      +  /* See the documentation for cmark_parser_get_line_number() in cmark.h */
      +  int line_number;
      +  /* See the documentation for cmark_parser_get_offset() in cmark.h */
      +  bufsize_t offset;
      +  /* See the documentation for cmark_parser_get_column() in cmark.h */
      +  bufsize_t column;
      +  /* See the documentation for cmark_parser_get_first_nonspace() in cmark.h */
      +  bufsize_t first_nonspace;
      +  /* See the documentation for cmark_parser_get_first_nonspace_column() in cmark.h */
      +  bufsize_t first_nonspace_column;
      +  bufsize_t thematic_break_kill_pos;
      +  /* See the documentation for cmark_parser_get_indent() in cmark.h */
      +  int indent;
      +  /* See the documentation for cmark_parser_is_blank() in cmark.h */
      +  bool blank;
      +  /* See the documentation for cmark_parser_has_partially_consumed_tab() in cmark.h */
      +  bool partially_consumed_tab;
      +  /* Contains the currently processed line */
      +  cmark_strbuf curline;
      +  /* See the documentation for cmark_parser_get_last_line_length() in cmark.h */
      +  bufsize_t last_line_length;
      +  /* FIXME: not sure about the difference with curline */
      +  cmark_strbuf linebuf;
      +  /* Options set by the user, see the Options section in cmark.h */
      +  int options;
      +  bool last_buffer_ended_with_cr;
      +  cmark_llist *syntax_extensions;
      +  cmark_llist *inline_syntax_extensions;
      +  cmark_ispunct_func backslash_ispunct;
      +  /* used when parsing inlines, can be populated by extensions if any are loaded */
      +  int8_t *skip_chars;
      +  int8_t *special_chars;
      +};
      +
      +#ifdef __cplusplus
      +}
      +#endif
      +
      +#endif
      diff --git a/src/include/plugin.h b/src/include/plugin.h
      new file mode 100644
      index 000000000..7bcbd19a2
      --- /dev/null
      +++ b/src/include/plugin.h
      @@ -0,0 +1,34 @@
      +#ifndef CMARK_PLUGIN_H
      +#define CMARK_PLUGIN_H
      +
      +#ifdef __cplusplus
      +extern "C" {
      +#endif
      +
      +#include "cmark-gfm.h"
      +#include "cmark-gfm-extension_api.h"
      +
      +/**
      + * cmark_plugin:
      + *
      + * A plugin structure, which should be filled by plugin's
      + * init functions.
      + */
      +struct cmark_plugin {
      +  cmark_llist *syntax_extensions;
      +};
      +
      +cmark_llist *
      +cmark_plugin_steal_syntax_extensions(cmark_plugin *plugin);
      +
      +cmark_plugin *
      +cmark_plugin_new(void);
      +
      +void
      +cmark_plugin_free(cmark_plugin *plugin);
      +
      +#ifdef __cplusplus
      +}
      +#endif
      +
      +#endif
      diff --git a/src/include/references.h b/src/include/references.h
      new file mode 100644
      index 000000000..81330ae7a
      --- /dev/null
      +++ b/src/include/references.h
      @@ -0,0 +1,30 @@
      +#ifndef CMARK_REFERENCES_H
      +#define CMARK_REFERENCES_H
      +
      +#include "map.h"
      +
      +#ifdef __cplusplus
      +extern "C" {
      +#endif
      +
      +struct cmark_reference {
      +  cmark_map_entry entry;
      +  bool is_attributes_reference;
      +  cmark_chunk url;
      +  cmark_chunk title;
      +  cmark_chunk attributes;
      +};
      +
      +typedef struct cmark_reference cmark_reference;
      +
      +void cmark_reference_create(cmark_map *map, cmark_chunk *label,
      +                            cmark_chunk *url, cmark_chunk *title);
      +void cmark_reference_create_attributes(cmark_map *map, cmark_chunk *label,
      +                                       cmark_chunk *attributes);
      +cmark_map *cmark_reference_map_new(cmark_mem *mem);
      +
      +#ifdef __cplusplus
      +}
      +#endif
      +
      +#endif
      diff --git a/src/include/registry.h b/src/include/registry.h
      new file mode 100644
      index 000000000..ade02b9c0
      --- /dev/null
      +++ b/src/include/registry.h
      @@ -0,0 +1,24 @@
      +#ifndef CMARK_REGISTRY_H
      +#define CMARK_REGISTRY_H
      +
      +#ifdef __cplusplus
      +extern "C" {
      +#endif
      +
      +#include "cmark-gfm.h"
      +#include "cmark-gfm-extension_api.h"
      +
      +CMARK_GFM_EXPORT
      +void cmark_register_plugin(cmark_plugin_init_func reg_fn);
      +
      +CMARK_GFM_EXPORT
      +void cmark_release_plugins(void);
      +
      +CMARK_GFM_EXPORT
      +cmark_llist *cmark_list_syntax_extensions(cmark_mem *mem);
      +
      +#ifdef __cplusplus
      +}
      +#endif
      +
      +#endif
      diff --git a/src/render.h b/src/include/render.h
      similarity index 60%
      rename from src/render.h
      rename to src/include/render.h
      index ab1103982..4a68d1e07 100644
      --- a/src/render.h
      +++ b/src/include/render.h
      @@ -23,20 +23,33 @@ struct cmark_renderer {
         bool begin_content;
         bool no_linebreaks;
         bool in_tight_list_item;
      -  void (*outc)(struct cmark_renderer *, cmark_escaping, int32_t, unsigned char);
      +  void (*outc)(struct cmark_renderer *, cmark_node *, cmark_escaping, int32_t, unsigned char);
         void (*cr)(struct cmark_renderer *);
         void (*blankline)(struct cmark_renderer *);
      -  void (*out)(struct cmark_renderer *, const char *, bool, cmark_escaping);
      +  void (*out)(struct cmark_renderer *, cmark_node *, const char *, bool, cmark_escaping);
      +  unsigned int footnote_ix;
       };
       
       typedef struct cmark_renderer cmark_renderer;
       
      +struct cmark_html_renderer {
      +  cmark_strbuf *html;
      +  cmark_node *plain;
      +  cmark_llist *filter_extensions;
      +  unsigned int footnote_ix;
      +  unsigned int written_footnote_ix;
      +  void *opaque;
      +};
      +
      +typedef struct cmark_html_renderer cmark_html_renderer;
      +
       void cmark_render_ascii(cmark_renderer *renderer, const char *s);
       
       void cmark_render_code_point(cmark_renderer *renderer, uint32_t c);
       
      -char *cmark_render(cmark_node *root, int options, int width,
      -                   void (*outc)(cmark_renderer *, cmark_escaping, int32_t,
      +char *cmark_render(cmark_mem *mem, cmark_node *root, int options, int width,
      +                   void (*outc)(cmark_renderer *, cmark_node *,
      +                                cmark_escaping, int32_t,
                                       unsigned char),
                          int (*render_node)(cmark_renderer *renderer,
                                             cmark_node *node,
      diff --git a/src/scanners.h b/src/include/scanners.h
      similarity index 88%
      rename from src/scanners.h
      rename to src/include/scanners.h
      index bcb5fe8c3..8861f8dd3 100644
      --- a/src/scanners.h
      +++ b/src/include/scanners.h
      @@ -1,4 +1,7 @@
      -#include "cmark.h"
      +#ifndef CMARK_SCANNERS_H
      +#define CMARK_SCANNERS_H
      +
      +#include "cmark-gfm.h"
       #include "chunk.h"
       
       #ifdef __cplusplus
      @@ -11,6 +14,7 @@ bufsize_t _scan_scheme(const unsigned char *p);
       bufsize_t _scan_autolink_uri(const unsigned char *p);
       bufsize_t _scan_autolink_email(const unsigned char *p);
       bufsize_t _scan_html_tag(const unsigned char *p);
      +bufsize_t _scan_liberal_html_tag(const unsigned char *p);
       bufsize_t _scan_html_block_start(const unsigned char *p);
       bufsize_t _scan_html_block_start_7(const unsigned char *p);
       bufsize_t _scan_html_block_end_1(const unsigned char *p);
      @@ -26,11 +30,13 @@ bufsize_t _scan_open_code_fence(const unsigned char *p);
       bufsize_t _scan_close_code_fence(const unsigned char *p);
       bufsize_t _scan_entity(const unsigned char *p);
       bufsize_t _scan_dangerous_url(const unsigned char *p);
      +bufsize_t _scan_footnote_definition(const unsigned char *p);
       
       #define scan_scheme(c, n) _scan_at(&_scan_scheme, c, n)
       #define scan_autolink_uri(c, n) _scan_at(&_scan_autolink_uri, c, n)
       #define scan_autolink_email(c, n) _scan_at(&_scan_autolink_email, c, n)
       #define scan_html_tag(c, n) _scan_at(&_scan_html_tag, c, n)
      +#define scan_liberal_html_tag(c, n) _scan_at(&_scan_liberal_html_tag, c, n)
       #define scan_html_block_start(c, n) _scan_at(&_scan_html_block_start, c, n)
       #define scan_html_block_start_7(c, n) _scan_at(&_scan_html_block_start_7, c, n)
       #define scan_html_block_end_1(c, n) _scan_at(&_scan_html_block_end_1, c, n)
      @@ -47,7 +53,10 @@ bufsize_t _scan_dangerous_url(const unsigned char *p);
       #define scan_close_code_fence(c, n) _scan_at(&_scan_close_code_fence, c, n)
       #define scan_entity(c, n) _scan_at(&_scan_entity, c, n)
       #define scan_dangerous_url(c, n) _scan_at(&_scan_dangerous_url, c, n)
      +#define scan_footnote_definition(c, n) _scan_at(&_scan_footnote_definition, c, n)
       
       #ifdef __cplusplus
       }
       #endif
      +
      +#endif
      diff --git a/src/include/syntax_extension.h b/src/include/syntax_extension.h
      new file mode 100644
      index 000000000..081a54c9a
      --- /dev/null
      +++ b/src/include/syntax_extension.h
      @@ -0,0 +1,34 @@
      +#ifndef CMARK_SYNTAX_EXTENSION_H
      +#define CMARK_SYNTAX_EXTENSION_H
      +
      +#include "cmark-gfm.h"
      +#include "cmark-gfm-extension_api.h"
      +#include "cmark-gfm_config.h"
      +
      +struct cmark_syntax_extension {
      +  cmark_match_block_func          last_block_matches;
      +  cmark_open_block_func           try_opening_block;
      +  cmark_match_inline_func         match_inline;
      +  cmark_inline_from_delim_func    insert_inline_from_delim;
      +  cmark_llist                   * special_inline_chars;
      +  char                          * name;
      +  void                          * priv;
      +  bool                            emphasis;
      +  cmark_free_func                 free_function;
      +  cmark_get_type_string_func      get_type_string_func;
      +  cmark_can_contain_func          can_contain_func;
      +  cmark_contains_inlines_func     contains_inlines_func;
      +  cmark_common_render_func        commonmark_render_func;
      +  cmark_common_render_func        plaintext_render_func;
      +  cmark_common_render_func        latex_render_func;
      +  cmark_xml_attr_func             xml_attr_func;
      +  cmark_common_render_func        man_render_func;
      +  cmark_html_render_func          html_render_func;
      +  cmark_html_filter_func          html_filter_func;
      +  cmark_postprocess_func          postprocess_func;
      +  cmark_opaque_alloc_func         opaque_alloc_func;
      +  cmark_opaque_free_func          opaque_free_func;
      +  cmark_commonmark_escape_func    commonmark_escape_func;
      +};
      +
      +#endif
      diff --git a/src/utf8.h b/src/include/utf8.h
      similarity index 85%
      rename from src/utf8.h
      rename to src/include/utf8.h
      index 8e45714d4..04ec1611b 100644
      --- a/src/utf8.h
      +++ b/src/include/utf8.h
      @@ -8,13 +8,24 @@
       extern "C" {
       #endif
       
      +CMARK_GFM_EXPORT
       void cmark_utf8proc_case_fold(cmark_strbuf *dest, const uint8_t *str,
                                     bufsize_t len);
      +
      +CMARK_GFM_EXPORT
       void cmark_utf8proc_encode_char(int32_t uc, cmark_strbuf *buf);
      +
      +CMARK_GFM_EXPORT
       int cmark_utf8proc_iterate(const uint8_t *str, bufsize_t str_len, int32_t *dst);
      +
      +CMARK_GFM_EXPORT
       void cmark_utf8proc_check(cmark_strbuf *dest, const uint8_t *line,
                                 bufsize_t size);
      +
      +CMARK_GFM_EXPORT
       int cmark_utf8proc_is_space(int32_t uc);
      +
      +CMARK_GFM_EXPORT
       int cmark_utf8proc_is_punctuation(int32_t uc);
       
       #ifdef __cplusplus
      diff --git a/src/inlines.c b/src/inlines.c
      index e6b491ffa..75cd11016 100644
      --- a/src/inlines.c
      +++ b/src/inlines.c
      @@ -3,15 +3,16 @@
       #include 
       
       #include "cmark_ctype.h"
      -#include "config.h"
      +#include "cmark-gfm_config.h"
       #include "node.h"
       #include "parser.h"
       #include "references.h"
      -#include "cmark.h"
      +#include "cmark-gfm.h"
       #include "houdini.h"
       #include "utf8.h"
       #include "scanners.h"
       #include "inlines.h"
      +#include "syntax_extension.h"
       
       static const char *EMDASH = "\xE2\x80\x94";
       static const char *ENDASH = "\xE2\x80\x93";
      @@ -30,42 +31,47 @@ static const char *RIGHTSINGLEQUOTE = "\xE2\x80\x99";
       #define make_emph(mem) make_simple(mem, CMARK_NODE_EMPH)
       #define make_strong(mem) make_simple(mem, CMARK_NODE_STRONG)
       
      -#define MAXBACKTICKS 1000
      +#define MAXBACKTICKS 80
       
      -typedef struct delimiter {
      -  struct delimiter *previous;
      -  struct delimiter *next;
      -  cmark_node *inl_text;
      -  bufsize_t length;
      -  unsigned char delim_char;
      -  bool can_open;
      -  bool can_close;
      -} delimiter;
      +typedef enum {
      +  LINK,
      +  IMAGE,
      +  ATTRIBUTE
      +} bracket_type;
       
       typedef struct bracket {
         struct bracket *previous;
         struct delimiter *previous_delimiter;
         cmark_node *inl_text;
         bufsize_t position;
      -  bool image;
      +  bracket_type type;
         bool active;
         bool bracket_after;
       } bracket;
       
      -typedef struct {
      +typedef struct subject{
         cmark_mem *mem;
         cmark_chunk input;
         int line;
         bufsize_t pos;
         int block_offset;
         int column_offset;
      -  cmark_reference_map *refmap;
      +  cmark_map *refmap;
         delimiter *last_delim;
         bracket *last_bracket;
         bufsize_t backticks[MAXBACKTICKS + 1];
         bool scanned_for_backticks;
       } subject;
       
      +void cmark_set_default_skip_chars(int8_t **skip_chars, bool use_memcpy) {
      +  static int8_t default_skip_chars[256];
      +
      +  if (use_memcpy)
      +    memcpy(*skip_chars, &default_skip_chars, 256);
      +  else
      +    *skip_chars = default_skip_chars;
      +}
      +
       static CMARK_INLINE bool S_is_line_end_char(char c) {
         return (c == '\n' || c == '\r');
       }
      @@ -73,11 +79,11 @@ static CMARK_INLINE bool S_is_line_end_char(char c) {
       static delimiter *S_insert_emph(subject *subj, delimiter *opener,
                                       delimiter *closer);
       
      -static int parse_inline(subject *subj, cmark_node *parent, int options);
      +static int parse_inline(cmark_parser *parser, subject *subj, cmark_node *parent, int options);
       
       static void subject_from_buf(cmark_mem *mem, int line_number, int block_offset, subject *e,
      -                             cmark_chunk *chunk, cmark_reference_map *refmap);
      -static bufsize_t subject_find_special_char(subject *subj, int options);
      +                             cmark_chunk *buffer, cmark_map *refmap);
      +static bufsize_t subject_find_special_char(cmark_parser *parser, subject *subj, int options);
       
       // Create an inline with a literal string value.
       static CMARK_INLINE cmark_node *make_literal(subject *subj, cmark_node_type t,
      @@ -98,7 +104,7 @@ static CMARK_INLINE cmark_node *make_literal(subject *subj, cmark_node_type t,
       static CMARK_INLINE cmark_node *make_simple(cmark_mem *mem, cmark_node_type t) {
         cmark_node *e = (cmark_node *)mem->calloc(1, sizeof(*e));
         cmark_strbuf_init(mem, &e->content, 0);
      -  e->type = t;
      +  e->type = (uint16_t)t;
         return e;
       }
       
      @@ -156,14 +162,14 @@ static CMARK_INLINE cmark_node *make_autolink(subject *subj,
         link->as.link.url = cmark_clean_autolink(subj->mem, &url, is_email);
         link->as.link.title = cmark_chunk_literal("");
         link->start_line = link->end_line = subj->line;
      -  link->start_column = start_column + 1;
      -  link->end_column = end_column + 1;
      +  link->start_column = start_column + 1 + subj->column_offset + subj->block_offset;
      +  link->end_column = end_column + 1 + subj->column_offset + subj->block_offset;
         cmark_node_append_child(link, make_str_with_entities(subj, start_column + 1, end_column - 1, &url));
         return link;
       }
       
       static void subject_from_buf(cmark_mem *mem, int line_number, int block_offset, subject *e,
      -                             cmark_chunk *chunk, cmark_reference_map *refmap) {
      +                             cmark_chunk *chunk, cmark_map *refmap) {
         int i;
         e->mem = mem;
         e->input = *chunk;
      @@ -182,11 +188,15 @@ static void subject_from_buf(cmark_mem *mem, int line_number, int block_offset,
       
       static CMARK_INLINE int isbacktick(int c) { return (c == '`'); }
       
      -static CMARK_INLINE unsigned char peek_char(subject *subj) {
      +static CMARK_INLINE unsigned char peek_char_n(subject *subj, bufsize_t n) {
         // NULL bytes should have been stripped out by now.  If they're
         // present, it's a programming error:
      -  assert(!(subj->pos < subj->input.len && subj->input.data[subj->pos] == 0));
      -  return (subj->pos < subj->input.len) ? subj->input.data[subj->pos] : 0;
      +  assert(!(subj->pos + n < subj->input.len && subj->input.data[subj->pos + n] == 0));
      +  return (subj->pos + n < subj->input.len) ? subj->input.data[subj->pos + n] : 0;
      +}
      +
      +static CMARK_INLINE unsigned char peek_char(subject *subj) {
      +  return peek_char_n(subj, 0);
       }
       
       static CMARK_INLINE unsigned char peek_at(subject *subj, bufsize_t pos) {
      @@ -363,13 +373,14 @@ static void S_normalize_code(cmark_strbuf *s) {
       // Parse backtick code section or raw backticks, return an inline.
       // Assumes that the subject has a backtick at the current position.
       static cmark_node *handle_backticks(subject *subj, int options) {
      +  bufsize_t initPos = subj->pos;
         cmark_chunk openticks = take_while(subj, isbacktick);
         bufsize_t startpos = subj->pos;
         bufsize_t endpos = scan_to_closing_backticks(subj, openticks.len);
       
         if (endpos == 0) {      // not found
           subj->pos = startpos; // rewind
      -    return make_str(subj, subj->pos, subj->pos, openticks);
      +    return make_str(subj, initPos, initPos + openticks.len - 1, openticks);
         } else {
           cmark_strbuf buf = CMARK_BUF_INIT(subj->mem);
       
      @@ -378,6 +389,7 @@ static cmark_node *handle_backticks(subject *subj, int options) {
           S_normalize_code(&buf);
       
           cmark_node *node = make_code(subj, startpos, endpos - openticks.len - 1, cmark_chunk_buf_detach(&buf));
      +    node->backtick_count = openticks.len;
           adjust_subj_node_newlines(subj, node, endpos - startpos, openticks.len, options);
           return node;
         }
      @@ -386,10 +398,10 @@ static cmark_node *handle_backticks(subject *subj, int options) {
       
       // Scan ***, **, or * and return number scanned, or 0.
       // Advances position.
      -static int scan_delims(subject *subj, unsigned char c, bool *can_open,
      -                       bool *can_close) {
      +static int scan_delims(cmark_parser *parser, subject *subj, unsigned char c,
      +                       bool *can_open, bool *can_close) {
         int numdelims = 0;
      -  bufsize_t before_char_pos;
      +  bufsize_t before_char_pos, after_char_pos;
         int32_t after_char = 0;
         int32_t before_char = 0;
         int len;
      @@ -399,13 +411,14 @@ static int scan_delims(subject *subj, unsigned char c, bool *can_open,
           before_char = 10;
         } else {
           before_char_pos = subj->pos - 1;
      +    
           // walk back to the beginning of the UTF_8 sequence:
      -    while (peek_at(subj, before_char_pos) >> 6 == 2 && before_char_pos > 0) {
      +    while ((peek_at(subj, before_char_pos) >> 6 == 2 || parser->skip_chars[peek_at(subj, before_char_pos)]) && before_char_pos > 0) {
             before_char_pos -= 1;
           }
           len = cmark_utf8proc_iterate(subj->input.data + before_char_pos,
                                        subj->pos - before_char_pos, &before_char);
      -    if (len == -1) {
      +    if (len == -1 || (before_char < 256 && parser->skip_chars[(unsigned char) before_char])) {
             before_char = 10;
           }
         }
      @@ -420,11 +433,21 @@ static int scan_delims(subject *subj, unsigned char c, bool *can_open,
           }
         }
       
      -  len = cmark_utf8proc_iterate(subj->input.data + subj->pos,
      -                               subj->input.len - subj->pos, &after_char);
      -  if (len == -1) {
      +  if (subj->pos == subj->input.len) {
           after_char = 10;
      +  } else {
      +    after_char_pos = subj->pos;
      +    
      +    while (parser->skip_chars[peek_at(subj, after_char_pos)] && after_char_pos < subj->input.len) {
      +      after_char_pos += 1;
      +    }
      +    len = cmark_utf8proc_iterate(subj->input.data + after_char_pos,
      +                                 subj->input.len - after_char_pos, &after_char);
      +    if (len == -1 || (after_char < 256 && parser->skip_chars[(unsigned char) after_char])) {
      +      after_char = 10;
      +    }
         }
      +
         left_flanking = numdelims > 0 && !cmark_utf8proc_is_space(after_char) &&
                         (!cmark_utf8proc_is_punctuation(after_char) ||
                          cmark_utf8proc_is_space(before_char) ||
      @@ -505,12 +528,12 @@ static void push_delimiter(subject *subj, unsigned char c, bool can_open,
         subj->last_delim = delim;
       }
       
      -static void push_bracket(subject *subj, bool image, cmark_node *inl_text) {
      +static void push_bracket(subject *subj, bracket_type type, cmark_node *inl_text) {
         bracket *b = (bracket *)subj->mem->calloc(1, sizeof(bracket));
         if (subj->last_bracket != NULL) {
           subj->last_bracket->bracket_after = true;
         }
      -  b->image = image;
      +  b->type = type;
         b->active = true;
         b->inl_text = inl_text;
         b->previous = subj->last_bracket;
      @@ -521,13 +544,13 @@ static void push_bracket(subject *subj, bool image, cmark_node *inl_text) {
       }
       
       // Assumes the subject has a c at the current position.
      -static cmark_node *handle_delim(subject *subj, unsigned char c, bool smart) {
      +static cmark_node *handle_delim(cmark_parser *parser, subject *subj, unsigned char c, bool smart) {
         bufsize_t numdelims;
         cmark_node *inl_text;
         bool can_open, can_close;
         cmark_chunk contents;
       
      -  numdelims = scan_delims(subj, c, &can_open, &can_close);
      +  numdelims = scan_delims(parser, subj, c, &can_open, &can_close);
       
         if (c == '\'' && smart) {
           contents = cmark_chunk_literal(RIGHTSINGLEQUOTE);
      @@ -606,14 +629,40 @@ static cmark_node *handle_period(subject *subj, bool smart) {
         }
       }
       
      -static void process_emphasis(subject *subj, delimiter *stack_bottom) {
      +static cmark_syntax_extension *get_extension_for_special_char(cmark_parser *parser, unsigned char c) {
      +  cmark_llist *tmp_ext;
      +
      +  for (tmp_ext = parser->inline_syntax_extensions; tmp_ext; tmp_ext=tmp_ext->next) {
      +    cmark_syntax_extension *ext = (cmark_syntax_extension *) tmp_ext->data;
      +    cmark_llist *tmp_char;
      +    for (tmp_char = ext->special_inline_chars; tmp_char; tmp_char=tmp_char->next) {
      +      unsigned char tmp_c = (unsigned char)(size_t)tmp_char->data;
      +
      +      if (tmp_c == c) {
      +        return ext;
      +      }
      +    }
      +  }
      +
      +  return NULL;
      +}
      +
      +static void process_emphasis(cmark_parser *parser, subject *subj, delimiter *stack_bottom) {
         delimiter *closer = subj->last_delim;
         delimiter *opener;
         delimiter *old_closer;
         bool opener_found;
      -  int openers_bottom_index = 0;
      -  delimiter *openers_bottom[6] = {stack_bottom, stack_bottom, stack_bottom,
      -                                  stack_bottom, stack_bottom, stack_bottom};
      +  delimiter *openers_bottom[3][128];
      +  int i;
      +
      +  // initialize openers_bottom:
      +  memset(&openers_bottom, 0, sizeof(openers_bottom));
      +  for (i=0; i < 3; i++) {
      +    openers_bottom[i]['*'] = stack_bottom;
      +    openers_bottom[i]['_'] = stack_bottom;
      +    openers_bottom[i]['\''] = stack_bottom;
      +    openers_bottom[i]['"'] = stack_bottom;
      +  }
       
         // move back to first relevant delim.
         while (closer != NULL && closer->previous != stack_bottom) {
      @@ -622,28 +671,13 @@ static void process_emphasis(subject *subj, delimiter *stack_bottom) {
       
         // now move forward, looking for closers, and handling each
         while (closer != NULL) {
      +    cmark_syntax_extension *extension = get_extension_for_special_char(parser, closer->delim_char);
           if (closer->can_close) {
      -      switch (closer->delim_char) {
      -      case '"':
      -        openers_bottom_index = 0;
      -        break;
      -      case '\'':
      -        openers_bottom_index = 1;
      -        break;
      -      case '_':
      -        openers_bottom_index = 2;
      -        break;
      -      case '*':
      -        openers_bottom_index = 3 + (closer->length % 3);
      -        break;
      -      default:
      -        assert(false);
      -      }
      -
             // Now look backwards for first matching opener:
             opener = closer->previous;
             opener_found = false;
      -      while (opener != NULL && opener != openers_bottom[openers_bottom_index]) {
      +      while (opener != NULL && opener != stack_bottom &&
      +             opener != openers_bottom[closer->length % 3][closer->delim_char]) {
               if (opener->can_open && opener->delim_char == closer->delim_char) {
                 // interior closer of size 2 can't match opener of size 1
                 // or of size 1 can't match 2
      @@ -657,7 +691,13 @@ static void process_emphasis(subject *subj, delimiter *stack_bottom) {
               opener = opener->previous;
             }
             old_closer = closer;
      -      if (closer->delim_char == '*' || closer->delim_char == '_') {
      +
      +      if (extension) {
      +        if (opener_found)
      +          closer = extension->insert_inline_from_delim(extension, parser, subj, opener, closer);
      +        else
      +          closer = closer->next;
      +      } else if (closer->delim_char == '*' || closer->delim_char == '_') {
               if (opener_found) {
                 closer = S_insert_emph(subj, opener, closer);
               } else {
      @@ -682,7 +722,8 @@ static void process_emphasis(subject *subj, delimiter *stack_bottom) {
             }
             if (!opener_found) {
               // set lower bound for future searches for openers
      -        openers_bottom[openers_bottom_index] = old_closer->previous;
      +        openers_bottom[old_closer->length % 3][old_closer->delim_char] =
      +		old_closer->previous;
               if (!old_closer->can_open) {
                 // we can remove a closer that can't be an
                 // opener, once we've seen there's no
      @@ -764,11 +805,11 @@ static delimiter *S_insert_emph(subject *subj, delimiter *opener,
       }
       
       // Parse backslash-escape or just a backslash, returning an inline.
      -static cmark_node *handle_backslash(subject *subj) {
      +static cmark_node *handle_backslash(cmark_parser *parser, subject *subj) {
         advance(subj);
         unsigned char nextchar = peek_char(subj);
      -  if (cmark_ispunct(
      -          nextchar)) { // only ascii symbols and newline can be escaped
      +  if ((parser->backslash_ispunct ? parser->backslash_ispunct : cmark_ispunct)(nextchar)) {
      +    // only ascii symbols and newline can be escaped
           advance(subj);
           return make_str(subj, subj->pos - 2, subj->pos - 1, cmark_chunk_dup(&subj->input, subj->pos - 1, 1));
         } else if (!is_eof(subj) && skip_line_end(subj)) {
      @@ -808,7 +849,7 @@ cmark_chunk cmark_clean_url(cmark_mem *mem, cmark_chunk *url) {
           return result;
         }
       
      -    houdini_unescape_html_f(&buf, url->data, url->len);
      +  houdini_unescape_html_f(&buf, url->data, url->len);
       
         cmark_strbuf_unescape(&buf);
         return cmark_chunk_buf_detach(&buf);
      @@ -838,6 +879,12 @@ cmark_chunk cmark_clean_title(cmark_mem *mem, cmark_chunk *title) {
         return cmark_chunk_buf_detach(&buf);
       }
       
      +// Clean custom attributes. This function uses `cmark_clean_url` internaly
      +// because the requirements are the same
      +cmark_chunk cmark_clean_attributes(cmark_mem *mem, cmark_chunk *attributes) {
      +  return cmark_clean_url(mem, attributes);
      +}
      +
       // Parse an autolink or HTML tag.
       // Assumes the subject has a '<' character at the current position.
       static cmark_node *handle_pointy_brace(subject *subj, int options) {
      @@ -874,6 +921,17 @@ static cmark_node *handle_pointy_brace(subject *subj, int options) {
           return node;
         }
       
      +  if (options & CMARK_OPT_LIBERAL_HTML_TAG) {
      +    matchlen = scan_liberal_html_tag(&subj->input, subj->pos);
      +    if (matchlen > 0) {
      +      contents = cmark_chunk_dup(&subj->input, subj->pos - 1, matchlen + 1);
      +      subj->pos += matchlen;
      +      cmark_node *node = make_raw_html(subj, subj->pos - matchlen - 1, subj->pos - 1, contents);
      +      adjust_subj_node_newlines(subj, node, matchlen, 1, options);
      +      return node;
      +    }
      +  }
      +
         // if nothing matches, just return the opening <:
         return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("<"));
       }
      @@ -882,10 +940,19 @@ static cmark_node *handle_pointy_brace(subject *subj, int options) {
       // Note:  unescaped brackets are not allowed in labels.
       // The label begins with `[` and ends with the first `]` character
       // encountered.  Backticks in labels do not start code spans.
      -static int link_label(subject *subj, cmark_chunk *raw_label) {
      +static int link_label(subject *subj, cmark_chunk *raw_label, bool parse_attribute_label) {
         bufsize_t startpos = subj->pos;
         int length = 0;
         unsigned char c;
      +  
      +  // If we are parsing attribute label, advance past ^
      +  if (parse_attribute_label) {
      +    if (peek_char(subj) == '^') {
      +      advance(subj);
      +    } else {
      +      return 0;
      +    }
      +  }
       
         // advance past [
         if (peek_char(subj) == '[') {
      @@ -912,8 +979,9 @@ static int link_label(subject *subj, cmark_chunk *raw_label) {
         }
       
         if (c == ']') { // match found
      +    bufsize_t position = parse_attribute_label ? startpos + 2 : startpos + 1;
           *raw_label =
      -        cmark_chunk_dup(&subj->input, startpos + 1, subj->pos - (startpos + 1));
      +        cmark_chunk_dup(&subj->input, position, subj->pos - position);
           cmark_chunk_trim(raw_label);
           advance(subj); // advance past ]
           return 1;
      @@ -929,30 +997,30 @@ static bufsize_t manual_scan_link_url_2(cmark_chunk *input, bufsize_t offset,
         bufsize_t i = offset;
         size_t nb_p = 0;
       
      -    while (i < input->len) {
      -      if (input->data[i] == '\\' &&
      -	  i + 1 < input-> len &&
      -          cmark_ispunct(input->data[i+1]))
      -        i += 2;
      -      else if (input->data[i] == '(') {
      -        ++nb_p;
      -        ++i;
      -        if (nb_p > 32)
      -          return -1;
      -      } else if (input->data[i] == ')') {
      -        if (nb_p == 0)
      -          break;
      -        --nb_p;
      -        ++i;
      -      } else if (cmark_isspace(input->data[i])) {
      -        if (i == offset) {
      -	  return -1;
      -	}
      +  while (i < input->len) {
      +    if (input->data[i] == '\\' &&
      +        i + 1 < input-> len &&
      +        cmark_ispunct(input->data[i+1]))
      +      i += 2;
      +    else if (input->data[i] == '(') {
      +      ++nb_p;
      +      ++i;
      +      if (nb_p > 32)
      +        return -1;
      +    } else if (input->data[i] == ')') {
      +      if (nb_p == 0)
               break;
      -      } else {
      -        ++i;
      +      --nb_p;
      +      ++i;
      +    } else if (cmark_isspace(input->data[i])) {
      +      if (i == offset) {
      +        return -1;
             }
      +      break;
      +    } else {
      +      ++i;
           }
      +  }
       
         if (i >= input->len)
           return -1;
      @@ -995,8 +1063,118 @@ static bufsize_t manual_scan_link_url(cmark_chunk *input, bufsize_t offset,
         return i - offset;
       }
       
      -// Return a link, an image, or a literal close bracket.
      -static cmark_node *handle_close_bracket(subject *subj) {
      +static bufsize_t manual_scan_attribute_attributes(cmark_chunk *input, bufsize_t offset,
      +                                                cmark_chunk *output) {
      +  bufsize_t i = offset;
      +  size_t nb_p = 0;
      +
      +  while (i < input->len) {
      +    if (input->data[i] == '\\' &&
      +        i + 1 < input->len &&
      +        cmark_ispunct(input->data[i+1]))
      +      i += 2;
      +    else if (input->data[i] == '(') {
      +      ++nb_p;
      +      ++i;
      +      if (nb_p > 32)
      +        return -1;
      +    } else if (input->data[i] == ')') {
      +      if (nb_p == 0)
      +        break;
      +      --nb_p;
      +      ++i;
      +    } else {
      +      ++i;
      +    }
      +  }
      +
      +  if (i >= input->len)
      +    return -1;
      +
      +  {
      +    cmark_chunk result = {input->data + offset, i - offset, 0};
      +    *output = result;
      +  }
      +  return i - offset;
      +}
      +
      +static cmark_node *handle_close_bracket_attribute(cmark_parser *parser, subject *subj, bracket *opener) {
      +  bufsize_t startattributes, endattributes;
      +  cmark_chunk attributes;
      +  bufsize_t n;
      +  cmark_node *inl;
      +  cmark_chunk raw_label;
      +  int found_label;
      +  cmark_node *tmp, *tmpnext;
      +  cmark_reference *ref = NULL;
      +  bool isAttributesNode = false;
      +
      +  // ^name[content](attributes)
      +  // TODO: support name. we will not even enter this with a name because we fail the match first
      +
      +  startattributes = subj->pos + 1;
      +
      +  if (peek_char(subj) == '(' &&
      +      ((n = manual_scan_attribute_attributes(&subj->input, subj->pos + 1,
      +                                 &attributes)) > -1)) {
      +
      +    endattributes = subj->pos + 1 + n;
      +
      +    if (peek_at(subj, endattributes) == ')') {
      +      subj->pos = endattributes + 1;
      +      isAttributesNode = true;
      +      if (endattributes - startattributes == 0) {
      +        attributes = cmark_chunk_literal(NULL);
      +      } else {
      +        attributes = cmark_chunk_dup(&subj->input, startattributes, endattributes - startattributes);
      +      }
      +    }
      +  }
      +  
      +  // If we can't match direct link, look for [link label] that matches in refmap
      +  raw_label = cmark_chunk_literal("");
      +  found_label = link_label(subj, &raw_label, false);
      +  if (found_label) {
      +    ref = (cmark_reference *)cmark_map_lookup(subj->refmap, &raw_label);
      +    cmark_chunk_free(subj->mem, &raw_label);
      +    
      +    if (ref && ref->is_attributes_reference) {
      +      isAttributesNode = true;
      +      attributes = chunk_clone(subj->mem, &ref->attributes);
      +    }
      +  }
      +
      +  if (!isAttributesNode) {
      +    // The current node can't be parsed as attribute node, turn it to a TEXT node instead.
      +    pop_bracket(subj);
      +    return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]"));
      +  }
      +  
      +  inl = make_simple(subj->mem, CMARK_NODE_ATTRIBUTE);
      +  inl->as.attribute.attributes = attributes;
      +  inl->start_line = inl->end_line = subj->line;
      +  inl->start_column = opener->inl_text->start_column;
      +  inl->end_column = subj->pos + subj->column_offset + subj->block_offset;
      +  cmark_node_insert_before(opener->inl_text, inl);
      +  // Add content text:
      +  tmp = opener->inl_text->next;
      +  while (tmp) {
      +    tmpnext = tmp->next;
      +    cmark_node_append_child(inl, tmp);
      +    tmp = tmpnext;
      +  }
      +
      +  // Free the bracket ^[:
      +  cmark_node_free(opener->inl_text);
      +
      +  process_emphasis(parser, subj, opener->previous_delimiter);
      +  pop_bracket(subj);
      +
      +  return NULL;
      +}
      +
      +// Return a link, an image, an attribute, or a literal close bracket.
      +static cmark_node *handle_close_bracket(cmark_parser *parser, subject *subj) {
         bufsize_t initial_pos, after_link_text_pos;
         bufsize_t endurl, starttitle, endtitle, endall;
         bufsize_t sps, n;
      @@ -1013,7 +1191,7 @@ static cmark_node *handle_close_bracket(subject *subj) {
         advance(subj); // advance past ]
         initial_pos = subj->pos;
       
      -  // get last [ or ![
      +  // get last [ or ![ or ^[
         opener = subj->last_bracket;
       
         if (opener == NULL) {
      @@ -1026,9 +1204,13 @@ static cmark_node *handle_close_bracket(subject *subj) {
           return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]"));
         }
       
      +  if (opener->type == ATTRIBUTE) {
      +    return handle_close_bracket_attribute(parser, subj, opener);
      +  }
      +
         // If we got here, we matched a potential link/image text.
         // Now we check to see if it's a link/image.
      -  is_image = opener->image;
      +  is_image = opener->type == IMAGE;
       
         after_link_text_pos = subj->pos;
       
      @@ -1069,7 +1251,7 @@ static cmark_node *handle_close_bracket(subject *subj) {
         // Next, look for a following [link label] that matches in refmap.
         // skip spaces
         raw_label = cmark_chunk_literal("");
      -  found_label = link_label(subj, &raw_label);
      +  found_label = link_label(subj, &raw_label, false);
         if (!found_label) {
           // If we have a shortcut reference link, back up
           // to before the spacse we skipped.
      @@ -1084,11 +1266,11 @@ static cmark_node *handle_close_bracket(subject *subj) {
         }
       
         if (found_label) {
      -    ref = cmark_reference_lookup(subj->refmap, &raw_label);
      +    ref = (cmark_reference *)cmark_map_lookup(subj->refmap, &raw_label);
           cmark_chunk_free(subj->mem, &raw_label);
         }
       
      -  if (ref != NULL) { // found
      +  if (ref != NULL && !ref->is_attributes_reference) { // found
           url = chunk_clone(subj->mem, &ref->url);
           title = chunk_clone(subj->mem, &ref->title);
           goto match;
      @@ -1097,7 +1279,28 @@ static cmark_node *handle_close_bracket(subject *subj) {
         }
       
       noMatch:
      -  // If we fall through to here, it means we didn't match a link:
      +  // If we fall through to here, it means we didn't match a link.
      +  // What if we're a footnote link?
      +  if (parser->options & CMARK_OPT_FOOTNOTES &&
      +      opener->inl_text->next &&
      +      opener->inl_text->next->type == CMARK_NODE_TEXT &&
      +      !opener->inl_text->next->next) {
      +    cmark_chunk *literal = &opener->inl_text->next->as.literal;
      +    if (literal->len > 1 && literal->data[0] == '^') {
      +      inl = make_simple(subj->mem, CMARK_NODE_FOOTNOTE_REFERENCE);
      +      inl->as.literal = cmark_chunk_dup(literal, 1, literal->len - 1);
      +      inl->start_line = inl->end_line = subj->line;
      +      inl->start_column = opener->inl_text->start_column;
      +      inl->end_column = subj->pos + subj->column_offset + subj->block_offset;
      +      cmark_node_insert_before(opener->inl_text, inl);
      +      cmark_node_free(opener->inl_text->next);
      +      cmark_node_free(opener->inl_text);
      +      process_emphasis(parser, subj, opener->previous_delimiter);
      +      pop_bracket(subj);
      +      return NULL;
      +    }
      +  }
      +
         pop_bracket(subj); // remove this opener from delimiter list
         subj->pos = initial_pos;
         return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]"));
      @@ -1106,8 +1309,9 @@ static cmark_node *handle_close_bracket(subject *subj) {
         inl = make_simple(subj->mem, is_image ? CMARK_NODE_IMAGE : CMARK_NODE_LINK);
         inl->as.link.url = url;
         inl->as.link.title = title;
      -  inl->start_line = inl->end_line = subj->line;
      +  inl->start_line = opener->inl_text->start_line;
         inl->start_column = opener->inl_text->start_column;
      +  inl->end_line = subj->line;
         inl->end_column = subj->pos + subj->column_offset + subj->block_offset;
         cmark_node_insert_before(opener->inl_text, inl);
         // Add link text:
      @@ -1121,7 +1325,7 @@ static cmark_node *handle_close_bracket(subject *subj) {
         // Free the bracket [:
         cmark_node_free(opener->inl_text);
       
      -  process_emphasis(subj, opener->previous_delimiter);
      +  process_emphasis(parser, subj, opener->previous_delimiter);
         pop_bracket(subj);
       
         // Now, if we have a link, we also want to deactivate earlier link
      @@ -1130,7 +1334,7 @@ static cmark_node *handle_close_bracket(subject *subj) {
         if (!is_image) {
           opener = subj->last_bracket;
           while (opener != NULL) {
      -      if (!opener->image) {
      +      if (opener->type == LINK) {
               if (!opener->active) {
                 break;
               } else {
      @@ -1167,23 +1371,29 @@ static cmark_node *handle_newline(subject *subj) {
         }
       }
       
      -static bufsize_t subject_find_special_char(subject *subj, int options) {
      -  // "\r\n\\`&_*[]pos + 1;
       
         while (n < subj->input.len) {
      -    if (SPECIAL_CHARS[subj->input.data[n]])
      +    if (parser->special_chars[subj->input.data[n]])
             return n;
           if (options & CMARK_OPT_SMART && SMART_PUNCT_CHARS[subj->input.data[n]])
             return n;
      @@ -1210,9 +1421,39 @@ static bufsize_t subject_find_special_char(subject *subj, int options) {
         return subj->input.len;
       }
       
      +void cmark_inlines_add_special_character(cmark_parser *parser, unsigned char c, bool emphasis) {
      +  parser->special_chars[c] = 1;
      +  if (emphasis)
      +    parser->skip_chars[c] = 1;
      +}
      +
      +void cmark_inlines_remove_special_character(cmark_parser *parser, unsigned char c, bool emphasis) {
      +  parser->special_chars[c] = 0;
      +  if (emphasis)
      +    parser->skip_chars[c] = 0;
      +}
      +
      +static cmark_node *try_extensions(cmark_parser *parser,
      +                                  cmark_node *parent,
      +                                  unsigned char c,
      +                                  subject *subj) {
      +  cmark_node *res = NULL;
      +  cmark_llist *tmp;
      +
      +  for (tmp = parser->inline_syntax_extensions; tmp; tmp = tmp->next) {
      +    cmark_syntax_extension *ext = (cmark_syntax_extension *) tmp->data;
      +    res = ext->match_inline(ext, parser, parent, c, subj);
      +
      +    if (res)
      +      break;
      +  }
      +
      +  return res;
      +}
      +
       // Parse an inline, advancing subject, and add it as a child of parent.
       // Return 0 if no inline can be parsed, 1 otherwise.
      -static int parse_inline(subject *subj, cmark_node *parent, int options) {
      +static int parse_inline(cmark_parser *parser, subject *subj, cmark_node *parent, int options) {
         cmark_node *new_inl = NULL;
         cmark_chunk contents;
         unsigned char c;
      @@ -1224,13 +1465,18 @@ static int parse_inline(subject *subj, cmark_node *parent, int options) {
         switch (c) {
         case '\r':
         case '\n':
      -    new_inl = handle_newline(subj);
      +    if (options & CMARK_OPT_PRESERVE_WHITESPACE) {
      +      advance(subj);
      +      new_inl = make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_dup(&subj->input, subj->pos - 1, 1));
      +    } else {
      +      new_inl = handle_newline(subj);
      +    }
           break;
         case '`':
           new_inl = handle_backticks(subj, options);
           break;
         case '\\':
      -    new_inl = handle_backslash(subj);
      +    new_inl = handle_backslash(parser, subj);
           break;
         case '&':
           new_inl = handle_entity(subj);
      @@ -1242,7 +1488,7 @@ static int parse_inline(subject *subj, cmark_node *parent, int options) {
         case '_':
         case '\'':
         case '"':
      -    new_inl = handle_delim(subj, c, (options & CMARK_OPT_SMART) != 0);
      +    new_inl = handle_delim(parser, subj, c, (options & CMARK_OPT_SMART) != 0);
           break;
         case '-':
           new_inl = handle_hyphen(subj, (options & CMARK_OPT_SMART) != 0);
      @@ -1253,29 +1499,44 @@ static int parse_inline(subject *subj, cmark_node *parent, int options) {
         case '[':
           advance(subj);
           new_inl = make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("["));
      -    push_bracket(subj, false, new_inl);
      +    push_bracket(subj, LINK, new_inl);
           break;
         case ']':
      -    new_inl = handle_close_bracket(subj);
      +    new_inl = handle_close_bracket(parser, subj);
           break;
         case '!':
           advance(subj);
      -    if (peek_char(subj) == '[') {
      +    if (peek_char(subj) == '[' && peek_char_n(subj, 1) != '^') {
             advance(subj);
             new_inl = make_str(subj, subj->pos - 2, subj->pos - 1, cmark_chunk_literal("!["));
      -      push_bracket(subj, true, new_inl);
      +      push_bracket(subj, IMAGE, new_inl);
           } else {
             new_inl = make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("!"));
           }
           break;
      +  case '^':
      +    advance(subj);
      +    // TODO: Support a name between ^ and [
      +    if (peek_char(subj) == '[') {
      +      advance(subj);
      +      new_inl = make_str(subj, subj->pos - 2, subj->pos - 1, cmark_chunk_literal("^["));
      +      push_bracket(subj, ATTRIBUTE, new_inl);
      +    } else {
      +      new_inl = make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("^"));
      +    }
      +    break;
         default:
      -    endpos = subject_find_special_char(subj, options);
      +    new_inl = try_extensions(parser, parent, c, subj);
      +    if (new_inl != NULL)
      +      break;
      +
      +    endpos = subject_find_special_char(parser, subj, options);
           contents = cmark_chunk_dup(&subj->input, subj->pos, endpos - subj->pos);
           startpos = subj->pos;
           subj->pos = endpos;
       
           // if we're at a newline, strip trailing spaces.
      -    if (S_is_line_end_char(peek_char(subj))) {
      +    if ((options & CMARK_OPT_PRESERVE_WHITESPACE) == 0 && S_is_line_end_char(peek_char(subj))) {
             cmark_chunk_rtrim(&contents);
           }
       
      @@ -1289,17 +1550,20 @@ static int parse_inline(subject *subj, cmark_node *parent, int options) {
       }
       
       // Parse inlines from parent's string_content, adding as children of parent.
      -extern void cmark_parse_inlines(cmark_mem *mem, cmark_node *parent,
      -                                cmark_reference_map *refmap, int options) {
      +void cmark_parse_inlines(cmark_parser *parser,
      +                         cmark_node *parent,
      +                         cmark_map *refmap,
      +                         int options) {
         subject subj;
         cmark_chunk content = {parent->content.ptr, parent->content.size, 0};
      -  subject_from_buf(mem, parent->start_line, parent->start_column - 1 + parent->internal_offset, &subj, &content, refmap);
      -  cmark_chunk_rtrim(&subj.input);
      +  subject_from_buf(parser->mem, parent->start_line, parent->start_column - 1 + parent->internal_offset, &subj, &content, refmap);
      +  if ((options & CMARK_OPT_PRESERVE_WHITESPACE) == 0)
      +    cmark_chunk_rtrim(&subj.input);
       
      -  while (!is_eof(&subj) && parse_inline(&subj, parent, options))
      +  while (!is_eof(&subj) && parse_inline(parser, &subj, parent, options))
           ;
       
      -  process_emphasis(&subj, NULL);
      +  process_emphasis(parser, &subj, NULL);
         // free bracket and delim stack
         while (subj.last_delim) {
           remove_delimiter(&subj, subj.last_delim);
      @@ -1322,7 +1586,7 @@ static void spnl(subject *subj) {
       // Return 0 if no reference found, otherwise position of subject
       // after reference is parsed.
       bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input,
      -                                       cmark_reference_map *refmap) {
      +                                       cmark_map *refmap) {
         subject subj;
       
         cmark_chunk lab;
      @@ -1335,7 +1599,7 @@ bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input,
         subject_from_buf(mem, -1, 0, &subj, input, NULL);
       
         // parse label:
      -  if (!link_label(&subj, &lab) || lab.len == 0)
      +  if (!link_label(&subj, &lab, false) || lab.len == 0)
           return 0;
       
         // colon:
      @@ -1382,3 +1646,218 @@ bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input,
         cmark_reference_create(refmap, &lab, &url, &title);
         return subj.pos;
       }
      +
      +bufsize_t cmark_parse_reference_attributes_inline(cmark_mem *mem, cmark_chunk *input,
      +                                                  cmark_map *refmap) {
      +  subject subj;
      +  
      +  cmark_chunk lab;
      +  cmark_chunk attributes;
      +  
      +  bufsize_t matchlen = 0;
      +  unsigned char c;
      +  
      +  subject_from_buf(mem, -1, 0, &subj, input, NULL);
      +  
      +  // parse attribute label:
      +  if (!link_label(&subj, &lab, true) || lab.len == 0) {
      +    return 0;
      +  }
      +  
      +  // Colon:
      +  if (peek_char(&subj) == ':') {
      +    advance(&subj);
      +  } else {
      +    return 0;
      +  }
      +  
      +  // parse attributes
      +  spnl(&subj);
      +  // read until next newline
      +  bufsize_t startpos = subj.pos;
      +  while ((c = peek_char(&subj)) && !S_is_line_end_char(c)) {
      +    advance(&subj);
      +    matchlen++;
      +  }
      +  
      +  if (matchlen == 0) {
      +    return 0;
      +  }
      +  
      +  attributes = cmark_chunk_dup(&subj.input, startpos, matchlen);
      +  
      +  // parse final spaces and newline:
      +  skip_spaces(&subj);
      +  if (!skip_line_end(&subj)) {
      +    return 0;
      +  }
      +  
      +  // insert reference into refmap
      +  cmark_reference_create_attributes(refmap, &lab, &attributes);
      +  return subj.pos;
      +}
      +
      +unsigned char cmark_inline_parser_peek_char(cmark_inline_parser *parser) {
      +  return peek_char(parser);
      +}
      +
      +unsigned char cmark_inline_parser_peek_at(cmark_inline_parser *parser, bufsize_t pos) {
      +  return peek_at(parser, pos);
      +}
      +
      +int cmark_inline_parser_is_eof(cmark_inline_parser *parser) {
      +  return is_eof(parser);
      +}
      +
      +static char *
      +my_strndup (const char *s, size_t n)
      +{
      +  char *result;
      +  size_t len = strlen (s);
      +
      +  if (n < len)
      +    len = n;
      +
      +  result = (char *) malloc (len + 1);
      +  if (!result)
      +    return 0;
      +
      +  result[len] = '\0';
      +  return (char *) memcpy (result, s, len);
      +}
      +
      +char *cmark_inline_parser_take_while(cmark_inline_parser *parser, cmark_inline_predicate pred) {
      +  unsigned char c;
      +  bufsize_t startpos = parser->pos;
      +  bufsize_t len = 0;
      +
      +  while ((c = peek_char(parser)) && (*pred)(c)) {
      +    advance(parser);
      +    len++;
      +  }
      +
      +  return my_strndup((const char *) parser->input.data + startpos, len);
      +}
      +
      +void cmark_inline_parser_push_delimiter(cmark_inline_parser *parser,
      +                                  unsigned char c,
      +                                  int can_open,
      +                                  int can_close,
      +                                  cmark_node *inl_text) {
      +  push_delimiter(parser, c, can_open != 0, can_close != 0, inl_text);
      +}
      +
      +void cmark_inline_parser_remove_delimiter(cmark_inline_parser *parser, delimiter *delim) {
      +  remove_delimiter(parser, delim);
      +}
      +
      +int cmark_inline_parser_scan_delimiters(cmark_inline_parser *parser,
      +                                  int max_delims,
      +                                  unsigned char c,
      +                                  int *left_flanking,
      +                                  int *right_flanking,
      +                                  int *punct_before,
      +                                  int *punct_after) {
      +  int numdelims = 0;
      +  bufsize_t before_char_pos;
      +  int32_t after_char = 0;
      +  int32_t before_char = 0;
      +  int len;
      +  bool space_before, space_after;
      +
      +  if (parser->pos == 0) {
      +    before_char = 10;
      +  } else {
      +    before_char_pos = parser->pos - 1;
      +    // walk back to the beginning of the UTF_8 sequence:
      +    while (peek_at(parser, before_char_pos) >> 6 == 2 && before_char_pos > 0) {
      +      before_char_pos -= 1;
      +    }
      +    len = cmark_utf8proc_iterate(parser->input.data + before_char_pos,
      +                                 parser->pos - before_char_pos, &before_char);
      +    if (len == -1) {
      +      before_char = 10;
      +    }
      +  }
      +
      +  while (peek_char(parser) == c && numdelims < max_delims) {
      +    numdelims++;
      +    advance(parser);
      +  }
      +
      +  len = cmark_utf8proc_iterate(parser->input.data + parser->pos,
      +                               parser->input.len - parser->pos, &after_char);
      +  if (len == -1) {
      +    after_char = 10;
      +  }
      +
      +  *punct_before = cmark_utf8proc_is_punctuation(before_char);
      +  *punct_after = cmark_utf8proc_is_punctuation(after_char);
      +  space_before = cmark_utf8proc_is_space(before_char) != 0;
      +  space_after = cmark_utf8proc_is_space(after_char) != 0;
      +
      +  *left_flanking = numdelims > 0 && !cmark_utf8proc_is_space(after_char) &&
      +                  !(*punct_after && !space_before && !*punct_before);
      +  *right_flanking = numdelims > 0 && !cmark_utf8proc_is_space(before_char) &&
      +                  !(*punct_before && !space_after && !*punct_after);
      +
      +  return numdelims;
      +}
      +
      +void cmark_inline_parser_advance_offset(cmark_inline_parser *parser) {
      +  advance(parser);
      +}
      +
      +int cmark_inline_parser_get_offset(cmark_inline_parser *parser) {
      +  return parser->pos;
      +}
      +
      +void cmark_inline_parser_set_offset(cmark_inline_parser *parser, int offset) {
      +  parser->pos = offset;
      +}
      +
      +int cmark_inline_parser_get_column(cmark_inline_parser *parser) {
      +  return parser->pos + 1 + parser->column_offset + parser->block_offset;
      +}
      +
      +cmark_chunk *cmark_inline_parser_get_chunk(cmark_inline_parser *parser) {
      +  return &parser->input;
      +}
      +
      +int cmark_inline_parser_in_bracket(cmark_inline_parser *parser, int type) {
      +  for (bracket *b = parser->last_bracket; b; b = b->previous) {
      +    if (b->active) {
      +      switch (type) {
      +        case 0:
      +          return b->type == LINK;
      +        case 1:
      +          return b->type == IMAGE;
      +        case 2:
      +          return b->type == ATTRIBUTE;
      +      }
      +    }
      +  }
      +  return 0;
      +}
      +
      +void cmark_node_unput(cmark_node *node, int n) {
      +	node = node->last_child;
      +	while (n > 0 && node && node->type == CMARK_NODE_TEXT) {
      +		if (node->as.literal.len < n) {
      +			n -= node->as.literal.len;
      +			node->as.literal.len = 0;
      +		} else {
      +			node->as.literal.len -= n;
      +			n = 0;
      +		}
      +		node = node->prev;
      +	}
      +}
      +
      +delimiter *cmark_inline_parser_get_last_delimiter(cmark_inline_parser *parser) {
      +  return parser->last_delim;
      +}
      +
      +int cmark_inline_parser_get_line(cmark_inline_parser *parser) {
      +  return parser->line;
      +}
      diff --git a/src/inlines.h b/src/inlines.h
      deleted file mode 100644
      index 39d3363ac..000000000
      --- a/src/inlines.h
      +++ /dev/null
      @@ -1,21 +0,0 @@
      -#ifndef CMARK_INLINES_H
      -#define CMARK_INLINES_H
      -
      -#ifdef __cplusplus
      -extern "C" {
      -#endif
      -
      -cmark_chunk cmark_clean_url(cmark_mem *mem, cmark_chunk *url);
      -cmark_chunk cmark_clean_title(cmark_mem *mem, cmark_chunk *title);
      -
      -void cmark_parse_inlines(cmark_mem *mem, cmark_node *parent,
      -                         cmark_reference_map *refmap, int options);
      -
      -bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input,
      -                                       cmark_reference_map *refmap);
      -
      -#ifdef __cplusplus
      -}
      -#endif
      -
      -#endif
      diff --git a/src/iterator.c b/src/iterator.c
      index f5cd80205..f107454df 100644
      --- a/src/iterator.c
      +++ b/src/iterator.c
      @@ -1,17 +1,11 @@
       #include 
       #include 
       
      -#include "config.h"
      +#include "cmark-gfm_config.h"
       #include "node.h"
      -#include "cmark.h"
      +#include "cmark-gfm.h"
       #include "iterator.h"
       
      -static const int S_leaf_mask =
      -    (1 << CMARK_NODE_HTML_BLOCK) | (1 << CMARK_NODE_THEMATIC_BREAK) |
      -    (1 << CMARK_NODE_CODE_BLOCK) | (1 << CMARK_NODE_TEXT) |
      -    (1 << CMARK_NODE_SOFTBREAK) | (1 << CMARK_NODE_LINEBREAK) |
      -    (1 << CMARK_NODE_CODE) | (1 << CMARK_NODE_HTML_INLINE);
      -
       cmark_iter *cmark_iter_new(cmark_node *root) {
         if (root == NULL) {
           return NULL;
      @@ -30,7 +24,18 @@ cmark_iter *cmark_iter_new(cmark_node *root) {
       void cmark_iter_free(cmark_iter *iter) { iter->mem->free(iter); }
       
       static bool S_is_leaf(cmark_node *node) {
      -  return ((1 << node->type) & S_leaf_mask) != 0;
      +  switch (node->type) {
      +  case CMARK_NODE_HTML_BLOCK:
      +  case CMARK_NODE_THEMATIC_BREAK:
      +  case CMARK_NODE_CODE_BLOCK:
      +  case CMARK_NODE_TEXT:
      +  case CMARK_NODE_SOFTBREAK:
      +  case CMARK_NODE_LINEBREAK:
      +  case CMARK_NODE_CODE:
      +  case CMARK_NODE_HTML_INLINE:
      +    return 1;
      +  }
      +  return 0;
       }
       
       cmark_event_type cmark_iter_next(cmark_iter *iter) {
      @@ -119,3 +124,36 @@ void cmark_consolidate_text_nodes(cmark_node *root) {
         cmark_strbuf_free(&buf);
         cmark_iter_free(iter);
       }
      +
      +void cmark_node_own(cmark_node *root) {
      +  if (root == NULL) {
      +    return;
      +  }
      +  cmark_iter *iter = cmark_iter_new(root);
      +  cmark_event_type ev_type;
      +  cmark_node *cur;
      +
      +  while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
      +    cur = cmark_iter_get_node(iter);
      +    if (ev_type == CMARK_EVENT_ENTER) {
      +      switch (cur->type) {
      +      case CMARK_NODE_TEXT:
      +      case CMARK_NODE_HTML_INLINE:
      +      case CMARK_NODE_CODE:
      +      case CMARK_NODE_HTML_BLOCK:
      +        cmark_chunk_to_cstr(iter->mem, &cur->as.literal);
      +        break;
      +      case CMARK_NODE_LINK:
      +        cmark_chunk_to_cstr(iter->mem, &cur->as.link.url);
      +        cmark_chunk_to_cstr(iter->mem, &cur->as.link.title);
      +        break;
      +      case CMARK_NODE_CUSTOM_INLINE:
      +        cmark_chunk_to_cstr(iter->mem, &cur->as.custom.on_enter);
      +        cmark_chunk_to_cstr(iter->mem, &cur->as.custom.on_exit);
      +        break;
      +      }
      +    }
      +  }
      +
      +  cmark_iter_free(iter);
      +}
      diff --git a/src/latex.c b/src/latex.c
      index 0d9517d19..c204f6003 100644
      --- a/src/latex.c
      +++ b/src/latex.c
      @@ -3,21 +3,23 @@
       #include 
       #include 
       
      -#include "config.h"
      -#include "cmark.h"
      +#include "cmark-gfm_config.h"
      +#include "cmark-gfm.h"
       #include "node.h"
       #include "buffer.h"
       #include "utf8.h"
       #include "scanners.h"
       #include "render.h"
      +#include "syntax_extension.h"
       
      -#define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping)
      -#define LIT(s) renderer->out(renderer, s, false, LITERAL)
      +#define OUT(s, wrap, escaping) renderer->out(renderer, node, s, wrap, escaping)
      +#define LIT(s) renderer->out(renderer, node, s, false, LITERAL)
       #define CR() renderer->cr(renderer)
       #define BLANKLINE() renderer->blankline(renderer)
       #define LIST_NUMBER_STRING_SIZE 20
       
      -static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_escaping escape,
      +static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_node *node,
      +                              cmark_escaping escape,
                                     int32_t c, unsigned char nextc) {
         if (escape == LITERAL) {
           cmark_render_code_point(renderer, c);
      @@ -226,8 +228,10 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
         cmark_list_type list_type;
         bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);
       
      -  // avoid warning about unused parameter:
      -  (void)(options);
      +  if (node->extension && node->extension->latex_render_func) {
      +    node->extension->latex_render_func(node->extension, renderer, node, ev_type, options);
      +    return 1;
      +  }
       
         switch (node->type) {
         case CMARK_NODE_DOCUMENT:
      @@ -440,6 +444,12 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
           }
           break;
       
      +  case CMARK_NODE_FOOTNOTE_DEFINITION:
      +  case CMARK_NODE_FOOTNOTE_REFERENCE:
      +  case CMARK_NODE_ATTRIBUTE:
      +    // TODO
      +    break;
      +
         default:
           assert(false);
           break;
      @@ -449,5 +459,9 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
       }
       
       char *cmark_render_latex(cmark_node *root, int options, int width) {
      -  return cmark_render(root, options, width, outc, S_render_node);
      +  return cmark_render_latex_with_mem(root, options, width, cmark_node_mem(root));
      +}
      +
      +char *cmark_render_latex_with_mem(cmark_node *root, int options, int width, cmark_mem *mem) {
      +  return cmark_render(mem, root, options, width, outc, S_render_node);
       }
      diff --git a/src/libcmark.pc.in b/src/libcmark-gfm.pc.in
      similarity index 53%
      rename from src/libcmark.pc.in
      rename to src/libcmark-gfm.pc.in
      index 0f87c309b..46fff31a2 100644
      --- a/src/libcmark.pc.in
      +++ b/src/libcmark-gfm.pc.in
      @@ -3,8 +3,8 @@ exec_prefix=@CMAKE_INSTALL_PREFIX@
       libdir=@CMAKE_INSTALL_PREFIX@/@libdir@
       includedir=@CMAKE_INSTALL_PREFIX@/include
       
      -Name: libcmark
      -Description: CommonMark parsing, rendering, and manipulation
      +Name: libcmark-gfm
      +Description: CommonMark parsing, rendering, and manipulation with GitHub Flavored Markdown extensions
       Version: @PROJECT_VERSION@
      -Libs: -L${libdir} -lcmark
      +Libs: -L${libdir} -lcmark-gfm -lcmark-gfm-extensions
       Cflags: -I${includedir}
      diff --git a/src/linked_list.c b/src/linked_list.c
      new file mode 100644
      index 000000000..8c26dc557
      --- /dev/null
      +++ b/src/linked_list.c
      @@ -0,0 +1,37 @@
      +#include 
      +
      +#include "cmark-gfm.h"
      +
      +cmark_llist *cmark_llist_append(cmark_mem *mem, cmark_llist *head, void *data) {
      +  cmark_llist *tmp;
      +  cmark_llist *new_node = (cmark_llist *) mem->calloc(1, sizeof(cmark_llist));
      +
      +  new_node->data = data;
      +  new_node->next = NULL;
      +
      +  if (!head)
      +    return new_node;
      +
      +  for (tmp = head; tmp->next; tmp=tmp->next);
      +
      +  tmp->next = new_node;
      +
      +  return head;
      +}
      +
      +void cmark_llist_free_full(cmark_mem *mem, cmark_llist *head, cmark_free_func free_func) {
      +  cmark_llist *tmp, *prev;
      +
      +  for (tmp = head; tmp;) {
      +    if (free_func)
      +      free_func(mem, tmp->data);
      +
      +    prev = tmp;
      +    tmp = tmp->next;
      +    mem->free(prev);
      +  }
      +}
      +
      +void cmark_llist_free(cmark_mem *mem, cmark_llist *head) {
      +  cmark_llist_free_full(mem, head, NULL);
      +}
      diff --git a/src/main.c b/src/main.c
      deleted file mode 100644
      index ab0d93c3d..000000000
      --- a/src/main.c
      +++ /dev/null
      @@ -1,210 +0,0 @@
      -#include 
      -#include 
      -#include 
      -#include 
      -#include "config.h"
      -#include "cmark.h"
      -#include "node.h"
      -
      -#if defined(__OpenBSD__)
      -#  include 
      -#  if OpenBSD >= 201605
      -#    define USE_PLEDGE
      -#    include 
      -#  endif
      -#endif
      -
      -#if defined(_WIN32) && !defined(__CYGWIN__)
      -#include 
      -#include 
      -#endif
      -
      -typedef enum {
      -  FORMAT_NONE,
      -  FORMAT_HTML,
      -  FORMAT_XML,
      -  FORMAT_MAN,
      -  FORMAT_COMMONMARK,
      -  FORMAT_LATEX
      -} writer_format;
      -
      -void print_usage() {
      -  printf("Usage:   cmark [FILE*]\n");
      -  printf("Options:\n");
      -  printf("  --to, -t FORMAT  Specify output format (html, xml, man, "
      -         "commonmark, latex)\n");
      -  printf("  --width WIDTH    Specify wrap width (default 0 = nowrap)\n");
      -  printf("  --sourcepos      Include source position attribute\n");
      -  printf("  --hardbreaks     Treat newlines as hard line breaks\n");
      -  printf("  --nobreaks       Render soft line breaks as spaces\n");
      -  printf("  --unsafe         Render raw HTML and dangerous URLs\n");
      -  printf("  --smart          Use smart punctuation\n");
      -  printf("  --validate-utf8  Replace UTF-8 invalid sequences with U+FFFD\n");
      -  printf("  --help, -h       Print usage information\n");
      -  printf("  --version        Print version\n");
      -}
      -
      -static void print_document(cmark_node *document, writer_format writer,
      -                           int options, int width) {
      -  char *result;
      -
      -  switch (writer) {
      -  case FORMAT_HTML:
      -    result = cmark_render_html(document, options);
      -    break;
      -  case FORMAT_XML:
      -    result = cmark_render_xml(document, options);
      -    break;
      -  case FORMAT_MAN:
      -    result = cmark_render_man(document, options, width);
      -    break;
      -  case FORMAT_COMMONMARK:
      -    result = cmark_render_commonmark(document, options, width);
      -    break;
      -  case FORMAT_LATEX:
      -    result = cmark_render_latex(document, options, width);
      -    break;
      -  default:
      -    fprintf(stderr, "Unknown format %d\n", writer);
      -    exit(1);
      -  }
      -  printf("%s", result);
      -  cmark_node_mem(document)->free(result);
      -}
      -
      -int main(int argc, char *argv[]) {
      -  int i, numfps = 0;
      -  int *files;
      -  char buffer[4096];
      -  cmark_parser *parser;
      -  size_t bytes;
      -  cmark_node *document;
      -  int width = 0;
      -  char *unparsed;
      -  writer_format writer = FORMAT_HTML;
      -  int options = CMARK_OPT_DEFAULT;
      -
      -#ifdef USE_PLEDGE
      -  if (pledge("stdio rpath", NULL) != 0) {
      -    perror("pledge");
      -    return 1;
      -  }
      -#endif
      -
      -#if defined(_WIN32) && !defined(__CYGWIN__)
      -  _setmode(_fileno(stdin), _O_BINARY);
      -  _setmode(_fileno(stdout), _O_BINARY);
      -#endif
      -
      -  files = (int *)calloc(argc, sizeof(*files));
      -
      -  for (i = 1; i < argc; i++) {
      -    if (strcmp(argv[i], "--version") == 0) {
      -      printf("cmark %s", CMARK_VERSION_STRING);
      -      printf(" - CommonMark converter\n(C) 2014-2016 John MacFarlane\n");
      -      exit(0);
      -    } else if (strcmp(argv[i], "--sourcepos") == 0) {
      -      options |= CMARK_OPT_SOURCEPOS;
      -    } else if (strcmp(argv[i], "--hardbreaks") == 0) {
      -      options |= CMARK_OPT_HARDBREAKS;
      -    } else if (strcmp(argv[i], "--nobreaks") == 0) {
      -      options |= CMARK_OPT_NOBREAKS;
      -    } else if (strcmp(argv[i], "--smart") == 0) {
      -      options |= CMARK_OPT_SMART;
      -    } else if (strcmp(argv[i], "--unsafe") == 0) {
      -      options |= CMARK_OPT_UNSAFE;
      -    } else if (strcmp(argv[i], "--validate-utf8") == 0) {
      -      options |= CMARK_OPT_VALIDATE_UTF8;
      -    } else if ((strcmp(argv[i], "--help") == 0) ||
      -               (strcmp(argv[i], "-h") == 0)) {
      -      print_usage();
      -      exit(0);
      -    } else if (strcmp(argv[i], "--width") == 0) {
      -      i += 1;
      -      if (i < argc) {
      -        width = (int)strtol(argv[i], &unparsed, 10);
      -        if (unparsed && strlen(unparsed) > 0) {
      -          fprintf(stderr, "failed parsing width '%s' at '%s'\n", argv[i],
      -                  unparsed);
      -          exit(1);
      -        }
      -      } else {
      -        fprintf(stderr, "--width requires an argument\n");
      -        exit(1);
      -      }
      -    } else if ((strcmp(argv[i], "-t") == 0) || (strcmp(argv[i], "--to") == 0)) {
      -      i += 1;
      -      if (i < argc) {
      -        if (strcmp(argv[i], "man") == 0) {
      -          writer = FORMAT_MAN;
      -        } else if (strcmp(argv[i], "html") == 0) {
      -          writer = FORMAT_HTML;
      -        } else if (strcmp(argv[i], "xml") == 0) {
      -          writer = FORMAT_XML;
      -        } else if (strcmp(argv[i], "commonmark") == 0) {
      -          writer = FORMAT_COMMONMARK;
      -        } else if (strcmp(argv[i], "latex") == 0) {
      -          writer = FORMAT_LATEX;
      -        } else {
      -          fprintf(stderr, "Unknown format %s\n", argv[i]);
      -          exit(1);
      -        }
      -      } else {
      -        fprintf(stderr, "No argument provided for %s\n", argv[i - 1]);
      -        exit(1);
      -      }
      -    } else if (*argv[i] == '-') {
      -      print_usage();
      -      exit(1);
      -    } else { // treat as file argument
      -      files[numfps++] = i;
      -    }
      -  }
      -
      -  parser = cmark_parser_new(options);
      -  for (i = 0; i < numfps; i++) {
      -    FILE *fp = fopen(argv[files[i]], "rb");
      -    if (fp == NULL) {
      -      fprintf(stderr, "Error opening file %s: %s\n", argv[files[i]],
      -              strerror(errno));
      -      exit(1);
      -    }
      -
      -    while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
      -      cmark_parser_feed(parser, buffer, bytes);
      -      if (bytes < sizeof(buffer)) {
      -        break;
      -      }
      -    }
      -
      -    fclose(fp);
      -  }
      -
      -  if (numfps == 0) {
      -
      -    while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0) {
      -      cmark_parser_feed(parser, buffer, bytes);
      -      if (bytes < sizeof(buffer)) {
      -        break;
      -      }
      -    }
      -  }
      -
      -#ifdef USE_PLEDGE
      -  if (pledge("stdio", NULL) != 0) {
      -    perror("pledge");
      -    return 1;
      -  }
      -#endif
      -
      -  document = cmark_parser_finish(parser);
      -  cmark_parser_free(parser);
      -
      -  print_document(document, writer, options, width);
      -
      -  cmark_node_free(document);
      -
      -  free(files);
      -
      -  return 0;
      -}
      diff --git a/src/man.c b/src/man.c
      index 1c76f68bb..c60e1bfe7 100644
      --- a/src/man.c
      +++ b/src/man.c
      @@ -3,21 +3,23 @@
       #include 
       #include 
       
      -#include "config.h"
      -#include "cmark.h"
      +#include "cmark-gfm_config.h"
      +#include "cmark-gfm.h"
       #include "node.h"
       #include "buffer.h"
       #include "utf8.h"
       #include "render.h"
      +#include "syntax_extension.h"
       
      -#define OUT(s, wrap, escaping) renderer->out(renderer, s, wrap, escaping)
      -#define LIT(s) renderer->out(renderer, s, false, LITERAL)
      +#define OUT(s, wrap, escaping) renderer->out(renderer, node, s, wrap, escaping)
      +#define LIT(s) renderer->out(renderer, node, s, false, LITERAL)
       #define CR() renderer->cr(renderer)
       #define BLANKLINE() renderer->blankline(renderer)
       #define LIST_NUMBER_SIZE 20
       
       // Functions to convert cmark_nodes to groff man strings.
      -static void S_outc(cmark_renderer *renderer, cmark_escaping escape, int32_t c,
      +static void S_outc(cmark_renderer *renderer, cmark_node *node, 
      +                   cmark_escaping escape, int32_t c,
                          unsigned char nextc) {
         (void)(nextc);
       
      @@ -77,11 +79,26 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
         bool entering = (ev_type == CMARK_EVENT_ENTER);
         bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options);
       
      -  // avoid unused parameter error:
      -  (void)(options);
      +  if (node->extension && node->extension->man_render_func) {
      +    node->extension->man_render_func(node->extension, renderer, node, ev_type, options);
      +    return 1;
      +  }
       
         switch (node->type) {
         case CMARK_NODE_DOCUMENT:
      +    if (entering) {
      +      /* Define a strikethrough macro */
      +      /* Commenting out because this makes tests fail
      +      LIT(".de ST");
      +      CR();
      +      LIT(".nr ww \\w'\\\\$1'");
      +      CR();
      +      LIT("\\Z@\\v'-.25m'\\l'\\\\n[ww]u'@\\\\$1");
      +      CR();
      +      LIT("..");
      +      CR();
      +      */
      +    }
           break;
       
         case CMARK_NODE_BLOCK_QUOTE:
      @@ -239,6 +256,15 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
           }
           break;
       
      +  case CMARK_NODE_ATTRIBUTE:
      +    OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
      +    break;
      +
      +  case CMARK_NODE_FOOTNOTE_DEFINITION:
      +  case CMARK_NODE_FOOTNOTE_REFERENCE:
      +    // TODO
      +    break;
      +
         default:
           assert(false);
           break;
      @@ -248,5 +274,9 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
       }
       
       char *cmark_render_man(cmark_node *root, int options, int width) {
      -  return cmark_render(root, options, width, S_outc, S_render_node);
      +  return cmark_render_man_with_mem(root, options, width, cmark_node_mem(root));
      +}
      +
      +char *cmark_render_man_with_mem(cmark_node *root, int options, int width, cmark_mem *mem) {
      +  return cmark_render(mem, root, options, width, S_outc, S_render_node);
       }
      diff --git a/src/map.c b/src/map.c
      new file mode 100644
      index 000000000..9a418dfd4
      --- /dev/null
      +++ b/src/map.c
      @@ -0,0 +1,122 @@
      +#include "map.h"
      +#include "utf8.h"
      +#include "parser.h"
      +
      +// normalize map label:  collapse internal whitespace to single space,
      +// remove leading/trailing whitespace, case fold
      +// Return NULL if the label is actually empty (i.e. composed solely from
      +// whitespace)
      +unsigned char *normalize_map_label(cmark_mem *mem, cmark_chunk *ref) {
      +  cmark_strbuf normalized = CMARK_BUF_INIT(mem);
      +  unsigned char *result;
      +
      +  if (ref == NULL)
      +    return NULL;
      +
      +  if (ref->len == 0)
      +    return NULL;
      +
      +  cmark_utf8proc_case_fold(&normalized, ref->data, ref->len);
      +  cmark_strbuf_trim(&normalized);
      +  cmark_strbuf_normalize_whitespace(&normalized);
      +
      +  result = cmark_strbuf_detach(&normalized);
      +  assert(result);
      +
      +  if (result[0] == '\0') {
      +    mem->free(result);
      +    return NULL;
      +  }
      +
      +  return result;
      +}
      +
      +static int
      +labelcmp(const unsigned char *a, const unsigned char *b) {
      +  return strcmp((const char *)a, (const char *)b);
      +}
      +
      +static int
      +refcmp(const void *p1, const void *p2) {
      +  cmark_map_entry *r1 = *(cmark_map_entry **)p1;
      +  cmark_map_entry *r2 = *(cmark_map_entry **)p2;
      +  int res = labelcmp(r1->label, r2->label);
      +  return res ? res : ((int)r1->age - (int)r2->age);
      +}
      +
      +static int
      +refsearch(const void *label, const void *p2) {
      +  cmark_map_entry *ref = *(cmark_map_entry **)p2;
      +  return labelcmp((const unsigned char *)label, ref->label);
      +}
      +
      +static void sort_map(cmark_map *map) {
      +  unsigned int i = 0, last = 0, size = map->size;
      +  cmark_map_entry *r = map->refs, **sorted = NULL;
      +
      +  sorted = (cmark_map_entry **)map->mem->calloc(size, sizeof(cmark_map_entry *));
      +  while (r) {
      +    sorted[i++] = r;
      +    r = r->next;
      +  }
      +
      +  qsort(sorted, size, sizeof(cmark_map_entry *), refcmp);
      +
      +  for (i = 1; i < size; i++) {
      +    if (labelcmp(sorted[i]->label, sorted[last]->label) != 0)
      +      sorted[++last] = sorted[i];
      +  }
      +
      +  map->sorted = sorted;
      +  map->size = last + 1;
      +}
      +
      +cmark_map_entry *cmark_map_lookup(cmark_map *map, cmark_chunk *label) {
      +  cmark_map_entry **ref = NULL;
      +  unsigned char *norm;
      +
      +  if (label->len < 1 || label->len > MAX_LINK_LABEL_LENGTH)
      +    return NULL;
      +
      +  if (map == NULL || !map->size)
      +    return NULL;
      +
      +  norm = normalize_map_label(map->mem, label);
      +  if (norm == NULL)
      +    return NULL;
      +
      +  if (!map->sorted)
      +    sort_map(map);
      +
      +  ref = (cmark_map_entry **)bsearch(norm, map->sorted, map->size, sizeof(cmark_map_entry *), refsearch);
      +  map->mem->free(norm);
      +
      +  if (!ref)
      +    return NULL;
      +
      +  return ref[0];
      +}
      +
      +void cmark_map_free(cmark_map *map) {
      +  cmark_map_entry *ref;
      +
      +  if (map == NULL)
      +    return;
      +
      +  ref = map->refs;
      +  while (ref) {
      +    cmark_map_entry *next = ref->next;
      +    map->free(map, ref);
      +    ref = next;
      +  }
      +
      +  map->mem->free(map->sorted);
      +  map->mem->free(map);
      +}
      +
      +cmark_map *cmark_map_new(cmark_mem *mem, cmark_map_free_f free) {
      +  cmark_map *map = (cmark_map *)mem->calloc(1, sizeof(cmark_map));
      +  map->mem = mem;
      +  map->free = free;
      +  return map;
      +}
      diff --git a/src/node.c b/src/node.c
      index c6c29028e..1d9b468cc 100644
      --- a/src/node.c
      +++ b/src/node.c
      @@ -1,57 +1,32 @@
       #include 
       #include 
       
      -#include "config.h"
      +#include "cmark-gfm_config.h"
       #include "node.h"
      +#include "syntax_extension.h"
       
       static void S_node_unlink(cmark_node *node);
       
       #define NODE_MEM(node) cmark_node_mem(node)
       
      -static CMARK_INLINE bool S_is_block(cmark_node *node) {
      -  if (node == NULL) {
      -    return false;
      -  }
      -  return node->type >= CMARK_NODE_FIRST_BLOCK &&
      -         node->type <= CMARK_NODE_LAST_BLOCK;
      -}
      -
      -static CMARK_INLINE bool S_is_inline(cmark_node *node) {
      -  if (node == NULL) {
      -    return false;
      -  }
      -  return node->type >= CMARK_NODE_FIRST_INLINE &&
      -         node->type <= CMARK_NODE_LAST_INLINE;
      -}
      -
      -static bool S_can_contain(cmark_node *node, cmark_node *child) {
      -  cmark_node *cur;
      -
      -  if (node == NULL || child == NULL) {
      -    return false;
      -  }
      -
      -  // Verify that child is not an ancestor of node or equal to node.
      -  cur = node;
      -  do {
      -    if (cur == child) {
      +bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type) {
      +  if (child_type == CMARK_NODE_DOCUMENT) {
             return false;
           }
      -    cur = cur->parent;
      -  } while (cur != NULL);
       
      -  if (child->type == CMARK_NODE_DOCUMENT) {
      -    return false;
      +  if (node->extension && node->extension->can_contain_func) {
      +    return node->extension->can_contain_func(node->extension, node, child_type) != 0;
         }
       
         switch (node->type) {
         case CMARK_NODE_DOCUMENT:
         case CMARK_NODE_BLOCK_QUOTE:
      +  case CMARK_NODE_FOOTNOTE_DEFINITION:
         case CMARK_NODE_ITEM:
      -    return S_is_block(child) && child->type != CMARK_NODE_ITEM;
      +    return CMARK_NODE_TYPE_BLOCK_P(child_type) && child_type != CMARK_NODE_ITEM;
       
         case CMARK_NODE_LIST:
      -    return child->type == CMARK_NODE_ITEM;
      +    return child_type == CMARK_NODE_ITEM;
       
         case CMARK_NODE_CUSTOM_BLOCK:
           return true;
      @@ -62,8 +37,9 @@ static bool S_can_contain(cmark_node *node, cmark_node *child) {
         case CMARK_NODE_STRONG:
         case CMARK_NODE_LINK:
         case CMARK_NODE_IMAGE:
      +  case CMARK_NODE_ATTRIBUTE:
         case CMARK_NODE_CUSTOM_INLINE:
      -    return S_is_inline(child);
      +    return CMARK_NODE_TYPE_INLINE_P(child_type);
       
         default:
           break;
      @@ -72,10 +48,33 @@ static bool S_can_contain(cmark_node *node, cmark_node *child) {
         return false;
       }
       
      -cmark_node *cmark_node_new_with_mem(cmark_node_type type, cmark_mem *mem) {
      +static bool S_can_contain(cmark_node *node, cmark_node *child) {
      +  cmark_node *cur;
      +
      +  if (node == NULL || child == NULL) {
      +    return false;
      +  }
      +  if (NODE_MEM(node) != NODE_MEM(child)) {
      +    return 0;
      +  }
      +
      +  // Verify that child is not an ancestor of node or equal to node.
      +  cur = node;
      +  do {
      +    if (cur == child) {
      +      return false;
      +    }
      +    cur = cur->parent;
      +  } while (cur != NULL);
      +
      +  return cmark_node_can_contain_type(node, (cmark_node_type) child->type);
      +}
      +
      +cmark_node *cmark_node_new_with_mem_and_ext(cmark_node_type type, cmark_mem *mem, cmark_syntax_extension *extension) {
         cmark_node *node = (cmark_node *)mem->calloc(1, sizeof(*node));
         cmark_strbuf_init(mem, &node->content, 0);
         node->type = (uint16_t)type;
      +  node->extension = extension;
       
         switch (node->type) {
         case CMARK_NODE_HEADING:
      @@ -94,43 +93,73 @@ cmark_node *cmark_node_new_with_mem(cmark_node_type type, cmark_mem *mem) {
           break;
         }
       
      +  if (node->extension && node->extension->opaque_alloc_func) {
      +    node->extension->opaque_alloc_func(node->extension, mem, node);
      +  }
      +
         return node;
       }
       
      +cmark_node *cmark_node_new_with_ext(cmark_node_type type, cmark_syntax_extension *extension) {
      +  extern cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR;
      +  return cmark_node_new_with_mem_and_ext(type, &CMARK_DEFAULT_MEM_ALLOCATOR, extension);
      +}
      +
      +cmark_node *cmark_node_new_with_mem(cmark_node_type type, cmark_mem *mem)
      +{
      +  return cmark_node_new_with_mem_and_ext(type, mem, NULL);
      +}
      +
       cmark_node *cmark_node_new(cmark_node_type type) {
      -  extern cmark_mem DEFAULT_MEM_ALLOCATOR;
      -  return cmark_node_new_with_mem(type, &DEFAULT_MEM_ALLOCATOR);
      +  return cmark_node_new_with_ext(type, NULL);
       }
       
      -// Free a cmark_node list and any children.
      -static void S_free_nodes(cmark_node *e) {
      -  cmark_node *next;
      -  while (e != NULL) {
      -    cmark_strbuf_free(&e->content);
      -    switch (e->type) {
      +static void free_node_as(cmark_node *node) {
      +  switch (node->type) {
           case CMARK_NODE_CODE_BLOCK:
      -      cmark_chunk_free(NODE_MEM(e), &e->as.code.info);
      -      cmark_chunk_free(NODE_MEM(e), &e->as.code.literal);
      +    cmark_chunk_free(NODE_MEM(node), &node->as.code.info);
      +    cmark_chunk_free(NODE_MEM(node), &node->as.code.literal);
             break;
           case CMARK_NODE_TEXT:
           case CMARK_NODE_HTML_INLINE:
           case CMARK_NODE_CODE:
           case CMARK_NODE_HTML_BLOCK:
      -      cmark_chunk_free(NODE_MEM(e), &e->as.literal);
      +    case CMARK_NODE_FOOTNOTE_REFERENCE:
      +    case CMARK_NODE_FOOTNOTE_DEFINITION:
      +    cmark_chunk_free(NODE_MEM(node), &node->as.literal);
             break;
           case CMARK_NODE_LINK:
           case CMARK_NODE_IMAGE:
      -      cmark_chunk_free(NODE_MEM(e), &e->as.link.url);
      -      cmark_chunk_free(NODE_MEM(e), &e->as.link.title);
      +    cmark_chunk_free(NODE_MEM(node), &node->as.link.url);
      +    cmark_chunk_free(NODE_MEM(node), &node->as.link.title);
      +      break;
      +    case CMARK_NODE_ATTRIBUTE:
      +    cmark_chunk_free(NODE_MEM(node), &node->as.attribute.attributes);
             break;
           case CMARK_NODE_CUSTOM_BLOCK:
           case CMARK_NODE_CUSTOM_INLINE:
      -      cmark_chunk_free(NODE_MEM(e), &e->as.custom.on_enter);
      -      cmark_chunk_free(NODE_MEM(e), &e->as.custom.on_exit);
      +    cmark_chunk_free(NODE_MEM(node), &node->as.custom.on_enter);
      +    cmark_chunk_free(NODE_MEM(node), &node->as.custom.on_exit);
             break;
           default:
             break;
           }
      +}
      +
      +// Free a cmark_node list and any children.
      +static void S_free_nodes(cmark_node *e) {
      +  cmark_node *next;
      +  while (e != NULL) {
      +    cmark_strbuf_free(&e->content);
      +
      +    if (e->user_data && e->user_data_free_func)
      +      e->user_data_free_func(NODE_MEM(e), e->user_data);
      +
      +    if (e->as.opaque && e->extension && e->extension->opaque_free_func)
      +      e->extension->opaque_free_func(e->extension, NODE_MEM(e), e);
      +
      +    free_node_as(e);
      +
           if (e->last_child) {
             // Splice children into list
             e->last_child->next = e->next;
      @@ -156,11 +185,38 @@ cmark_node_type cmark_node_get_type(cmark_node *node) {
         }
       }
       
      +int cmark_node_set_type(cmark_node * node, cmark_node_type type) {
      +  cmark_node_type initial_type;
      +
      +  if (type == node->type)
      +    return 1;
      +
      +  initial_type = (cmark_node_type) node->type;
      +  node->type = (uint16_t)type;
      +
      +  if (!S_can_contain(node->parent, node)) {
      +    node->type = (uint16_t)initial_type;
      +    return 0;
      +  }
      +
      +  /* We rollback the type to free the union members appropriately */
      +  node->type = (uint16_t)initial_type;
      +  free_node_as(node);
      +
      +  node->type = (uint16_t)type;
      +
      +  return 1;
      +}
      +
       const char *cmark_node_get_type_string(cmark_node *node) {
         if (node == NULL) {
           return "NONE";
         }
       
      +  if (node->extension && node->extension->get_type_string_func) {
      +    return node->extension->get_type_string_func(node->extension, node);
      +  }
      +
         switch (node->type) {
         case CMARK_NODE_NONE:
           return "none";
      @@ -204,6 +260,8 @@ const char *cmark_node_get_type_string(cmark_node *node) {
           return "link";
         case CMARK_NODE_IMAGE:
           return "image";
      +  case CMARK_NODE_ATTRIBUTE:
      +    return "attribute";
         }
       
         return "";
      @@ -265,6 +323,15 @@ int cmark_node_set_user_data(cmark_node *node, void *user_data) {
         return 1;
       }
       
      +int cmark_node_set_user_data_free_func(cmark_node *node,
      +                                        cmark_free_func free_func) {
      +  if (node == NULL) {
      +    return 0;
      +  }
      +  node->user_data_free_func = free_func;
      +  return 1;
      +}
      +
       const char *cmark_node_get_literal(cmark_node *node) {
         if (node == NULL) {
           return NULL;
      @@ -275,6 +342,7 @@ const char *cmark_node_get_literal(cmark_node *node) {
         case CMARK_NODE_TEXT:
         case CMARK_NODE_HTML_INLINE:
         case CMARK_NODE_CODE:
      +  case CMARK_NODE_FOOTNOTE_REFERENCE:
           return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.literal);
       
         case CMARK_NODE_CODE_BLOCK:
      @@ -287,6 +355,10 @@ const char *cmark_node_get_literal(cmark_node *node) {
         return NULL;
       }
       
      +int cmark_node_get_backtick_count(cmark_node *node) {
      +  return node->backtick_count;
      +}
      +
       int cmark_node_set_literal(cmark_node *node, const char *content) {
         if (node == NULL) {
           return 0;
      @@ -297,6 +369,7 @@ int cmark_node_set_literal(cmark_node *node, const char *content) {
         case CMARK_NODE_TEXT:
         case CMARK_NODE_HTML_INLINE:
         case CMARK_NODE_CODE:
      +  case CMARK_NODE_FOOTNOTE_REFERENCE:
           cmark_chunk_set_cstr(NODE_MEM(node), &node->as.literal, content);
           return 1;
       
      @@ -311,6 +384,15 @@ int cmark_node_set_literal(cmark_node *node, const char *content) {
         return 0;
       }
       
      +const char *cmark_node_get_string_content(cmark_node *node) {
      +  return (char *) node->content.ptr;
      +}
      +
      +int cmark_node_set_string_content(cmark_node *node, const char *content) {
      +  cmark_strbuf_sets(&node->content, content);
      +  return true;
      +}
      +
       int cmark_node_get_heading_level(cmark_node *node) {
         if (node == NULL) {
           return 0;
      @@ -477,6 +559,38 @@ int cmark_node_set_fence_info(cmark_node *node, const char *info) {
         }
       }
       
      +int cmark_node_get_fenced(cmark_node *node, int *length, int *offset, char *character) {
      +  if (node == NULL) {
      +    return 0;
      +  }
      +
      +  if (node->type == CMARK_NODE_CODE_BLOCK) {
      +    *length = node->as.code.fence_length;
      +    *offset = node->as.code.fence_offset;
      +    *character = node->as.code.fence_char;
      +    return node->as.code.fenced;
      +  } else {
      +    return 0;
      +  }
      +}
      +
      +int cmark_node_set_fenced(cmark_node * node, int fenced,
      +    int length, int offset, char character) {
      +  if (node == NULL) {
      +    return 0;
      +  }
      +
      +  if (node->type == CMARK_NODE_CODE_BLOCK) {
      +    node->as.code.fenced = (int8_t)fenced;
      +    node->as.code.fence_length = (uint8_t)length;
      +    node->as.code.fence_offset = (uint8_t)offset;
      +    node->as.code.fence_char = character;
      +    return 1;
      +  } else {
      +    return 0;
      +  }
      +}
      +
       const char *cmark_node_get_url(cmark_node *node) {
         if (node == NULL) {
           return NULL;
      @@ -543,6 +657,37 @@ int cmark_node_set_title(cmark_node *node, const char *title) {
         return 0;
       }
       
      +const char *cmark_node_get_attributes(cmark_node *node) {
      +  if (node == NULL) {
      +    return NULL;
      +  }
      +
      +  switch (node->type) {
      +  case CMARK_NODE_ATTRIBUTE:
      +    return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.attribute.attributes);
      +  default:
      +    break;
      +  }
      +
      +  return NULL;
      +}
      +
      +int cmark_node_set_attributes(cmark_node *node, const char *attributes) {
      +  if (node == NULL) {
      +    return 0;
      +  }
      +
      +  switch (node->type) {
      +  case CMARK_NODE_ATTRIBUTE:
      +    cmark_chunk_set_cstr(NODE_MEM(node), &node->as.attribute.attributes, attributes);
      +    return 1;
      +  default:
      +    break;
      +  }
      +
      +  return 0;
      +}
      +
       const char *cmark_node_get_on_enter(cmark_node *node) {
         if (node == NULL) {
           return NULL;
      @@ -609,6 +754,23 @@ int cmark_node_set_on_exit(cmark_node *node, const char *on_exit) {
         return 0;
       }
       
      +cmark_syntax_extension *cmark_node_get_syntax_extension(cmark_node *node) {
      +  if (node == NULL) {
      +    return NULL;
      +  }
      +
      +  return node->extension;
      +}
      +
      +int cmark_node_set_syntax_extension(cmark_node *node, cmark_syntax_extension *extension) {
      +  if (node == NULL) {
      +    return 0;
      +  }
      +
      +  node->extension = extension;
      +  return 1;
      +}
      +
       int cmark_node_get_start_line(cmark_node *node) {
         if (node == NULL) {
           return 0;
      diff --git a/src/parser.h b/src/parser.h
      deleted file mode 100644
      index f41f09960..000000000
      --- a/src/parser.h
      +++ /dev/null
      @@ -1,40 +0,0 @@
      -#ifndef CMARK_AST_H
      -#define CMARK_AST_H
      -
      -#include 
      -#include "references.h"
      -#include "node.h"
      -#include "buffer.h"
      -
      -#ifdef __cplusplus
      -extern "C" {
      -#endif
      -
      -#define MAX_LINK_LABEL_LENGTH 1000
      -
      -struct cmark_parser {
      -  struct cmark_mem *mem;
      -  struct cmark_reference_map *refmap;
      -  struct cmark_node *root;
      -  struct cmark_node *current;
      -  int line_number;
      -  bufsize_t offset;
      -  bufsize_t column;
      -  bufsize_t first_nonspace;
      -  bufsize_t first_nonspace_column;
      -  bufsize_t thematic_break_kill_pos;
      -  int indent;
      -  bool blank;
      -  bool partially_consumed_tab;
      -  cmark_strbuf curline;
      -  bufsize_t last_line_length;
      -  cmark_strbuf linebuf;
      -  int options;
      -  bool last_buffer_ended_with_cr;
      -};
      -
      -#ifdef __cplusplus
      -}
      -#endif
      -
      -#endif
      diff --git a/src/plaintext.c b/src/plaintext.c
      new file mode 100644
      index 000000000..0edbd1406
      --- /dev/null
      +++ b/src/plaintext.c
      @@ -0,0 +1,239 @@
      +#include "node.h"
      +#include "syntax_extension.h"
      +#include "render.h"
      +
      +#define OUT(s, wrap, escaping) renderer->out(renderer, node, s, wrap, escaping)
      +#define LIT(s) renderer->out(renderer, node, s, false, LITERAL)
      +#define CR() renderer->cr(renderer)
      +#define BLANKLINE() renderer->blankline(renderer)
      +#define LISTMARKER_SIZE 20
      +
      +// Functions to convert cmark_nodes to plain text strings.
      +
      +static CMARK_INLINE void outc(cmark_renderer *renderer, cmark_node *node, 
      +                              cmark_escaping escape,
      +                              int32_t c, unsigned char nextc) {
      +  cmark_render_code_point(renderer, c);
      +}
      +
      +// if node is a block node, returns node.
      +// otherwise returns first block-level node that is an ancestor of node.
      +// if there is no block-level ancestor, returns NULL.
      +static cmark_node *get_containing_block(cmark_node *node) {
      +  while (node) {
      +    if (CMARK_NODE_BLOCK_P(node)) {
      +      return node;
      +    } else {
      +      node = node->parent;
      +    }
      +  }
      +  return NULL;
      +}
      +
      +static int S_render_node(cmark_renderer *renderer, cmark_node *node,
      +                         cmark_event_type ev_type, int options) {
      +  cmark_node *tmp;
      +  int list_number;
      +  cmark_delim_type list_delim;
      +  int i;
      +  bool entering = (ev_type == CMARK_EVENT_ENTER);
      +  char listmarker[LISTMARKER_SIZE];
      +  bool first_in_list_item;
      +  bufsize_t marker_width;
      +  bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options) &&
      +                    !(CMARK_OPT_HARDBREAKS & options);
      +
      +  // Don't adjust tight list status til we've started the list.
      +  // Otherwise we loose the blank line between a paragraph and
      +  // a following list.
      +  if (!(node->type == CMARK_NODE_ITEM && node->prev == NULL && entering)) {
      +    tmp = get_containing_block(node);
      +    renderer->in_tight_list_item =
      +        tmp && // tmp might be NULL if there is no containing block
      +        ((tmp->type == CMARK_NODE_ITEM &&
      +          cmark_node_get_list_tight(tmp->parent)) ||
      +         (tmp && tmp->parent && tmp->parent->type == CMARK_NODE_ITEM &&
      +          cmark_node_get_list_tight(tmp->parent->parent)));
      +  }
      +
      +  if (node->extension && node->extension->plaintext_render_func) {
      +    node->extension->plaintext_render_func(node->extension, renderer, node, ev_type, options);
      +    return 1;
      +  }
      +
      +  switch (node->type) {
      +  case CMARK_NODE_DOCUMENT:
      +    break;
      +
      +  case CMARK_NODE_BLOCK_QUOTE:
      +    break;
      +
      +  case CMARK_NODE_LIST:
      +    if (!entering && node->next && (node->next->type == CMARK_NODE_CODE_BLOCK ||
      +                                    node->next->type == CMARK_NODE_LIST)) {
      +      CR();
      +    }
      +    break;
      +
      +  case CMARK_NODE_ITEM:
      +    if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
      +      marker_width = 4;
      +    } else {
      +      list_number = cmark_node_get_list_start(node->parent);
      +      list_delim = cmark_node_get_list_delim(node->parent);
      +      tmp = node;
      +      while (tmp->prev) {
      +        tmp = tmp->prev;
      +        list_number += 1;
      +      }
      +      // we ensure a width of at least 4 so
      +      // we get nice transition from single digits
      +      // to double
      +      snprintf(listmarker, LISTMARKER_SIZE, "%d%s%s", list_number,
      +               list_delim == CMARK_PAREN_DELIM ? ")" : ".",
      +               list_number < 10 ? "  " : " ");
      +      marker_width = (bufsize_t)strlen(listmarker);
      +    }
      +    if (entering) {
      +      if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
      +        LIT("  - ");
      +        renderer->begin_content = true;
      +      } else {
      +        LIT(listmarker);
      +        renderer->begin_content = true;
      +      }
      +      for (i = marker_width; i--;) {
      +        cmark_strbuf_putc(renderer->prefix, ' ');
      +      }
      +    } else {
      +      cmark_strbuf_truncate(renderer->prefix,
      +                            renderer->prefix->size - marker_width);
      +      CR();
      +    }
      +    break;
      +
      +  case CMARK_NODE_HEADING:
      +    if (entering) {
      +      renderer->begin_content = true;
      +      renderer->no_linebreaks = true;
      +    } else {
      +      renderer->no_linebreaks = false;
      +      BLANKLINE();
      +    }
      +    break;
      +
      +  case CMARK_NODE_CODE_BLOCK:
      +    first_in_list_item = node->prev == NULL && node->parent &&
      +                         node->parent->type == CMARK_NODE_ITEM;
      +
      +    if (!first_in_list_item) {
      +      BLANKLINE();
      +    }
      +    OUT(cmark_node_get_literal(node), false, LITERAL);
      +    BLANKLINE();
      +    break;
      +
      +  case CMARK_NODE_HTML_BLOCK:
      +    break;
      +
      +  case CMARK_NODE_CUSTOM_BLOCK:
      +    break;
      +
      +  case CMARK_NODE_THEMATIC_BREAK:
      +    BLANKLINE();
      +    break;
      +
      +  case CMARK_NODE_PARAGRAPH:
      +    if (!entering) {
      +      BLANKLINE();
      +    }
      +    break;
      +
      +  case CMARK_NODE_TEXT:
      +    OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
      +    break;
      +
      +  case CMARK_NODE_LINEBREAK:
      +    CR();
      +    break;
      +
      +  case CMARK_NODE_SOFTBREAK:
      +    if (CMARK_OPT_HARDBREAKS & options) {
      +      CR();
      +    } else if (!renderer->no_linebreaks && renderer->width == 0 &&
      +               !(CMARK_OPT_HARDBREAKS & options) &&
      +               !(CMARK_OPT_NOBREAKS & options)) {
      +      CR();
      +    } else {
      +      OUT(" ", allow_wrap, LITERAL);
      +    }
      +    break;
      +
      +  case CMARK_NODE_CODE:
      +    OUT(cmark_node_get_literal(node), allow_wrap, LITERAL);
      +    break;
      +
      +  case CMARK_NODE_HTML_INLINE:
      +    break;
      +
      +  case CMARK_NODE_CUSTOM_INLINE:
      +    break;
      +
      +  case CMARK_NODE_STRONG:
      +    break;
      +
      +  case CMARK_NODE_EMPH:
      +    break;
      +
      +  case CMARK_NODE_LINK:
      +    break;
      +
      +  case CMARK_NODE_IMAGE:
      +    break;
      +
      +  case CMARK_NODE_ATTRIBUTE:
      +    OUT(cmark_chunk_to_cstr(renderer->mem, &node->as.literal), false, LITERAL);
      +    break;
      +
      +  case CMARK_NODE_FOOTNOTE_REFERENCE:
      +    if (entering) {
      +      LIT("[^");
      +      OUT(cmark_chunk_to_cstr(renderer->mem, &node->as.literal), false, LITERAL);
      +      LIT("]");
      +    }
      +    break;
      +
      +  case CMARK_NODE_FOOTNOTE_DEFINITION:
      +    if (entering) {
      +      renderer->footnote_ix += 1;
      +      LIT("[^");
      +      char n[32];
      +      snprintf(n, sizeof(n), "%d", renderer->footnote_ix);
      +      OUT(n, false, LITERAL);
      +      LIT("]: ");
      +
      +      cmark_strbuf_puts(renderer->prefix, "    ");
      +    } else {
      +      cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 4);
      +    }
      +    break;
      +  default:
      +    assert(false);
      +    break;
      +  }
      +
      +  return 1;
      +}
      +
      +char *cmark_render_plaintext(cmark_node *root, int options, int width) {
      +  return cmark_render_plaintext_with_mem(root, options, width, cmark_node_mem(root));
      +}
      +
      +char *cmark_render_plaintext_with_mem(cmark_node *root, int options, int width, cmark_mem *mem) {
      +  if (options & CMARK_OPT_HARDBREAKS) {
      +    // disable breaking on width, since it has
      +    // a different meaning with OPT_HARDBREAKS
      +    width = 0;
      +  }
      +  return cmark_render(mem, root, options, width, outc, S_render_node);
      +}
      diff --git a/src/plugin.c b/src/plugin.c
      new file mode 100644
      index 000000000..3992fe197
      --- /dev/null
      +++ b/src/plugin.c
      @@ -0,0 +1,36 @@
      +#include 
      +
      +#include "plugin.h"
      +
      +extern cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR;
      +
      +int cmark_plugin_register_syntax_extension(cmark_plugin    * plugin,
      +                                        cmark_syntax_extension * extension) {
      +  plugin->syntax_extensions = cmark_llist_append(&CMARK_DEFAULT_MEM_ALLOCATOR, plugin->syntax_extensions, extension);
      +  return 1;
      +}
      +
      +cmark_plugin *
      +cmark_plugin_new(void) {
      +  cmark_plugin *res = (cmark_plugin *) CMARK_DEFAULT_MEM_ALLOCATOR.calloc(1, sizeof(cmark_plugin));
      +
      +  res->syntax_extensions = NULL;
      +
      +  return res;
      +}
      +
      +void
      +cmark_plugin_free(cmark_plugin *plugin) {
      +  cmark_llist_free_full(&CMARK_DEFAULT_MEM_ALLOCATOR,
      +                        plugin->syntax_extensions,
      +                        (cmark_free_func) cmark_syntax_extension_free);
      +  CMARK_DEFAULT_MEM_ALLOCATOR.free(plugin);
      +}
      +
      +cmark_llist *
      +cmark_plugin_steal_syntax_extensions(cmark_plugin *plugin) {
      +  cmark_llist *res = plugin->syntax_extensions;
      +
      +  plugin->syntax_extensions = NULL;
      +  return res;
      +}
      diff --git a/src/references.c b/src/references.c
      index 89f2dc8cb..5104c4190 100644
      --- a/src/references.c
      +++ b/src/references.c
      @@ -1,146 +1,69 @@
      -#include "cmark.h"
      -#include "utf8.h"
      +#include "cmark-gfm.h"
       #include "parser.h"
       #include "references.h"
       #include "inlines.h"
       #include "chunk.h"
       
      -static unsigned int refhash(const unsigned char *link_ref) {
      -  unsigned int hash = 0;
      -
      -  while (*link_ref)
      -    hash = (*link_ref++) + (hash << 6) + (hash << 16) - hash;
      -
      -  return hash;
      -}
      -
      -static void reference_free(cmark_reference_map *map, cmark_reference *ref) {
      +static void reference_free(cmark_map *map, cmark_map_entry *_ref) {
      +  cmark_reference *ref = (cmark_reference *)_ref;
         cmark_mem *mem = map->mem;
         if (ref != NULL) {
      -    mem->free(ref->label);
      +    mem->free(ref->entry.label);
           cmark_chunk_free(mem, &ref->url);
           cmark_chunk_free(mem, &ref->title);
      +    cmark_chunk_free(mem, &ref->attributes);
           mem->free(ref);
         }
       }
       
      -// normalize reference:  collapse internal whitespace to single space,
      -// remove leading/trailing whitespace, case fold
      -// Return NULL if the reference name is actually empty (i.e. composed
      -// solely from whitespace)
      -static unsigned char *normalize_reference(cmark_mem *mem, cmark_chunk *ref) {
      -  cmark_strbuf normalized = CMARK_BUF_INIT(mem);
      -  unsigned char *result;
      -
      -  if (ref == NULL)
      -    return NULL;
      -
      -  if (ref->len == 0)
      -    return NULL;
      -
      -  cmark_utf8proc_case_fold(&normalized, ref->data, ref->len);
      -  cmark_strbuf_trim(&normalized);
      -  cmark_strbuf_normalize_whitespace(&normalized);
      -
      -  result = cmark_strbuf_detach(&normalized);
      -  assert(result);
      -
      -  if (result[0] == '\0') {
      -    mem->free(result);
      -    return NULL;
      -  }
      -
      -  return result;
      -}
      -
      -static void add_reference(cmark_reference_map *map, cmark_reference *ref) {
      -  cmark_reference *t = ref->next = map->table[ref->hash % REFMAP_SIZE];
      -
      -  while (t) {
      -    if (t->hash == ref->hash && !strcmp((char *)t->label, (char *)ref->label)) {
      -      reference_free(map, ref);
      -      return;
      -    }
      -
      -    t = t->next;
      -  }
      -
      -  map->table[ref->hash % REFMAP_SIZE] = ref;
      -}
      -
      -void cmark_reference_create(cmark_reference_map *map, cmark_chunk *label,
      +void cmark_reference_create(cmark_map *map, cmark_chunk *label,
                                   cmark_chunk *url, cmark_chunk *title) {
         cmark_reference *ref;
      -  unsigned char *reflabel = normalize_reference(map->mem, label);
      +  unsigned char *reflabel = normalize_map_label(map->mem, label);
       
         /* empty reference name, or composed from only whitespace */
         if (reflabel == NULL)
           return;
       
      +  assert(map->sorted == NULL);
      +
         ref = (cmark_reference *)map->mem->calloc(1, sizeof(*ref));
      -  ref->label = reflabel;
      -  ref->hash = refhash(ref->label);
      +  ref->entry.label = reflabel;
      +  ref->is_attributes_reference = false;
         ref->url = cmark_clean_url(map->mem, url);
         ref->title = cmark_clean_title(map->mem, title);
      -  ref->next = NULL;
      +  ref->attributes = cmark_chunk_literal("");
      +  ref->entry.age = map->size;
      +  ref->entry.next = map->refs;
       
      -  add_reference(map, ref);
      +  map->refs = (cmark_map_entry *)ref;
      +  map->size++;
       }
       
      -// Returns reference if refmap contains a reference with matching
      -// label, otherwise NULL.
      -cmark_reference *cmark_reference_lookup(cmark_reference_map *map,
      -                                        cmark_chunk *label) {
      -  cmark_reference *ref = NULL;
      -  unsigned char *norm;
      -  unsigned int hash;
      -
      -  if (label->len < 1 || label->len > MAX_LINK_LABEL_LENGTH)
      -    return NULL;
      -
      -  if (map == NULL)
      -    return NULL;
      -
      -  norm = normalize_reference(map->mem, label);
      -  if (norm == NULL)
      -    return NULL;
      -
      -  hash = refhash(norm);
      -  ref = map->table[hash % REFMAP_SIZE];
      -
      -  while (ref) {
      -    if (ref->hash == hash && !strcmp((char *)ref->label, (char *)norm))
      -      break;
      -    ref = ref->next;
      -  }
      -
      -  map->mem->free(norm);
      -  return ref;
      -}
      -
      -void cmark_reference_map_free(cmark_reference_map *map) {
      -  unsigned int i;
      +void cmark_reference_create_attributes(cmark_map *map, cmark_chunk *label,
      +                                       cmark_chunk *attributes) {
      +  cmark_reference *ref;
      +  unsigned char *reflabel = normalize_map_label(map->mem, label);
       
      -  if (map == NULL)
      +  /* empty reference name, or composed from only whitespace */
      +  if (reflabel == NULL)
           return;
       
      -  for (i = 0; i < REFMAP_SIZE; ++i) {
      -    cmark_reference *ref = map->table[i];
      -    cmark_reference *next;
      -
      -    while (ref) {
      -      next = ref->next;
      -      reference_free(map, ref);
      -      ref = next;
      -    }
      -  }
      +  assert(map->sorted == NULL);
       
      -  map->mem->free(map);
      +  ref = (cmark_reference *)map->mem->calloc(1, sizeof(*ref));
      +  ref->entry.label = reflabel;
      +  ref->is_attributes_reference = true;
      +  ref->url = cmark_chunk_literal("");
      +  ref->title = cmark_chunk_literal("");
      +  ref->attributes = cmark_clean_attributes(map->mem, attributes);
      +  ref->entry.age = map->size;
      +  ref->entry.next = map->refs;
      +  
      +  map->refs = (cmark_map_entry *)ref;
      +  map->size++;
       }
       
      -cmark_reference_map *cmark_reference_map_new(cmark_mem *mem) {
      -  cmark_reference_map *map =
      -      (cmark_reference_map *)mem->calloc(1, sizeof(cmark_reference_map));
      -  map->mem = mem;
      -  return map;
      +cmark_map *cmark_reference_map_new(cmark_mem *mem) {
      +  return cmark_map_new(mem, reference_free);
       }
      diff --git a/src/references.h b/src/references.h
      deleted file mode 100644
      index 8d3631f34..000000000
      --- a/src/references.h
      +++ /dev/null
      @@ -1,40 +0,0 @@
      -#ifndef CMARK_REFERENCES_H
      -#define CMARK_REFERENCES_H
      -
      -#include "chunk.h"
      -
      -#ifdef __cplusplus
      -extern "C" {
      -#endif
      -
      -#define REFMAP_SIZE 16
      -
      -struct cmark_reference {
      -  struct cmark_reference *next;
      -  unsigned char *label;
      -  cmark_chunk url;
      -  cmark_chunk title;
      -  unsigned int hash;
      -};
      -
      -typedef struct cmark_reference cmark_reference;
      -
      -struct cmark_reference_map {
      -  cmark_mem *mem;
      -  cmark_reference *table[REFMAP_SIZE];
      -};
      -
      -typedef struct cmark_reference_map cmark_reference_map;
      -
      -cmark_reference_map *cmark_reference_map_new(cmark_mem *mem);
      -void cmark_reference_map_free(cmark_reference_map *map);
      -cmark_reference *cmark_reference_lookup(cmark_reference_map *map,
      -                                        cmark_chunk *label);
      -extern void cmark_reference_create(cmark_reference_map *map, cmark_chunk *label,
      -                                   cmark_chunk *url, cmark_chunk *title);
      -
      -#ifdef __cplusplus
      -}
      -#endif
      -
      -#endif
      diff --git a/src/registry.c b/src/registry.c
      new file mode 100644
      index 000000000..91f79530a
      --- /dev/null
      +++ b/src/registry.c
      @@ -0,0 +1,85 @@
      +#include 
      +#include 
      +#include 
      +
      +#include "cmark-gfm_config.h"
      +#include "cmark-gfm.h"
      +#include "mutex.h"
      +#include "syntax_extension.h"
      +#include "registry.h"
      +#include "plugin.h"
      +
      +extern cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR;
      +
      +static cmark_llist *syntax_extensions = NULL;
      +
      +CMARK_DEFINE_LOCK(extensions);
      +
      +void cmark_register_plugin(cmark_plugin_init_func reg_fn) {
      +  cmark_plugin *plugin = cmark_plugin_new();
      +
      +  if (!reg_fn(plugin)) {
      +    cmark_plugin_free(plugin);
      +    return;
      +  }
      +
      +  cmark_llist *syntax_extensions_list = cmark_plugin_steal_syntax_extensions(plugin),
      +              *it;
      +
      +  CMARK_INITIALIZE_AND_LOCK(extensions);
      +  
      +  for (it = syntax_extensions_list; it; it = it->next) {
      +    syntax_extensions = cmark_llist_append(&CMARK_DEFAULT_MEM_ALLOCATOR, syntax_extensions, it->data);
      +  }
      +  
      +  CMARK_UNLOCK(extensions);
      +
      +  cmark_llist_free(&CMARK_DEFAULT_MEM_ALLOCATOR, syntax_extensions_list);
      +  cmark_plugin_free(plugin);
      +}
      +
      +void cmark_release_plugins(void) {
      +  CMARK_INITIALIZE_AND_LOCK(extensions);
      +  
      +  if (syntax_extensions) {
      +    cmark_llist_free_full(
      +        &CMARK_DEFAULT_MEM_ALLOCATOR,
      +        syntax_extensions,
      +        (cmark_free_func) cmark_syntax_extension_free);
      +    syntax_extensions = NULL;
      +  }
      +  
      +  CMARK_UNLOCK(extensions);
      +}
      +
      +cmark_llist *cmark_list_syntax_extensions(cmark_mem *mem) {
      +  cmark_llist *it;
      +  cmark_llist *res = NULL;
      +
      +  CMARK_INITIALIZE_AND_LOCK(extensions);
      +  
      +  for (it = syntax_extensions; it; it = it->next) {
      +    res = cmark_llist_append(mem, res, it->data);
      +  }
      +  
      +  CMARK_UNLOCK(extensions);
      +  return res;
      +}
      +
      +cmark_syntax_extension *cmark_find_syntax_extension(const char *name) {
      +  cmark_llist *tmp;
      +  cmark_syntax_extension *res = NULL;
      +
      +  CMARK_INITIALIZE_AND_LOCK(extensions);
      +  
      +  for (tmp = syntax_extensions; tmp; tmp = tmp->next) {
      +    cmark_syntax_extension *ext = (cmark_syntax_extension *) tmp->data;
      +    if (!strcmp(ext->name, name)) {
      +      res = ext;
      +      break;
      +    }
      +  }
      +  
      +  CMARK_UNLOCK(extensions);
      +  return res;
      +}
      diff --git a/src/render.c b/src/render.c
      index fdd73df1c..02e9e838b 100644
      --- a/src/render.c
      +++ b/src/render.c
      @@ -1,10 +1,11 @@
       #include 
       #include "buffer.h"
       #include "chunk.h"
      -#include "cmark.h"
      +#include "cmark-gfm.h"
       #include "utf8.h"
       #include "render.h"
       #include "node.h"
      +#include "syntax_extension.h"
       
       static CMARK_INLINE void S_cr(cmark_renderer *renderer) {
         if (renderer->need_cr < 1) {
      @@ -18,9 +19,10 @@ static CMARK_INLINE void S_blankline(cmark_renderer *renderer) {
         }
       }
       
      -static void S_out(cmark_renderer *renderer, const char *source, bool wrap,
      +static void S_out(cmark_renderer *renderer, cmark_node *node,
      +                  const char *source, bool wrap,
                         cmark_escaping escape) {
      -  int length = strlen(source);
      +  int length = (int)strlen(source);
         unsigned char nextc;
         int32_t c;
         int i = 0;
      @@ -29,6 +31,16 @@ static void S_out(cmark_renderer *renderer, const char *source, bool wrap,
         cmark_chunk remainder = cmark_chunk_literal("");
         int k = renderer->buffer->size - 1;
       
      +  cmark_syntax_extension *ext = NULL;
      +  cmark_node *n = node;
      +  while (n && !ext) {
      +    ext = n->extension;
      +    if (!ext)
      +      n = n->parent;
      +  }
      +  if (ext && !ext->commonmark_escape_func)
      +    ext = NULL;
      +
         wrap = wrap && !renderer->no_linebreaks;
       
         if (renderer->in_tight_list_item && renderer->need_cr > 1) {
      @@ -63,6 +75,10 @@ static void S_out(cmark_renderer *renderer, const char *source, bool wrap,
           if (len == -1) { // error condition
             return;        // return without rendering rest of string
           }
      +
      +    if (ext && ext->commonmark_escape_func(ext, node, c))
      +      cmark_strbuf_putc(renderer->buffer, '\\');
      +
           nextc = source[i + len];
           if (c == 32 && wrap) {
             if (!renderer->begin_line) {
      @@ -97,13 +113,13 @@ static void S_out(cmark_renderer *renderer, const char *source, bool wrap,
               // we need to escape a potential list marker after
               // a digit:
               renderer->begin_content =
      -            renderer->begin_content && cmark_isdigit(c) == 1;
      +            renderer->begin_content && cmark_isdigit((char)c) == 1;
             }
           } else {
      -      (renderer->outc)(renderer, escape, c, nextc);
      +      (renderer->outc)(renderer, node, escape, c, nextc);
             renderer->begin_line = false;
             renderer->begin_content =
      -          renderer->begin_content && cmark_isdigit(c) == 1;
      +          renderer->begin_content && cmark_isdigit((char)c) == 1;
           }
       
           // If adding the character went beyond width, look for an
      @@ -145,13 +161,13 @@ void cmark_render_code_point(cmark_renderer *renderer, uint32_t c) {
         renderer->column += 1;
       }
       
      -char *cmark_render(cmark_node *root, int options, int width,
      -                   void (*outc)(cmark_renderer *, cmark_escaping, int32_t,
      +char *cmark_render(cmark_mem *mem, cmark_node *root, int options, int width,
      +                   void (*outc)(cmark_renderer *, cmark_node *,
      +                                cmark_escaping, int32_t,
                                       unsigned char),
                          int (*render_node)(cmark_renderer *renderer,
                                             cmark_node *node,
                                             cmark_event_type ev_type, int options)) {
      -  cmark_mem *mem = cmark_node_mem(root);
         cmark_strbuf pref = CMARK_BUF_INIT(mem);
         cmark_strbuf buf = CMARK_BUF_INIT(mem);
         cmark_node *cur;
      @@ -161,7 +177,8 @@ char *cmark_render(cmark_node *root, int options, int width,
       
         cmark_renderer renderer = {mem,   &buf, &pref, 0,           width,
                                    0,     0,    true,  true,        false,
      -                             false, outc, S_cr,  S_blankline, S_out};
      +                             false, outc, S_cr,  S_blankline, S_out,
      +                             0};
       
         while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
           cur = cmark_iter_get_node(iter);
      diff --git a/src/scanners.c b/src/scanners.c
      index f8e6c15f2..dfa6e5c10 100644
      --- a/src/scanners.c
      +++ b/src/scanners.c
      @@ -1,13787 +1,10520 @@
      -/* Generated by re2c 0.16 */
      +/* Generated by re2c 1.1.1 */
       #include 
       #include "chunk.h"
       #include "scanners.h"
       
      -bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c,
      -                   bufsize_t offset) {
      -  bufsize_t res;
      -  unsigned char *ptr = (unsigned char *)c->data;
      +bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c, bufsize_t offset)
      +{
      +	bufsize_t res;
      +	unsigned char *ptr = (unsigned char *)c->data;
       
      -  if (ptr == NULL || offset > c->len) {
      -    return 0;
      -  } else {
      -    unsigned char lim = ptr[c->len];
      +        if (ptr == NULL || offset > c->len) {
      +          return 0;
      +        } else {
      +	  unsigned char lim = ptr[c->len];
       
      -    ptr[c->len] = '\0';
      -    res = scanner(ptr + offset);
      -    ptr[c->len] = lim;
      -  }
      +	  ptr[c->len] = '\0';
      +	  res = scanner(ptr + offset);
      +	  ptr[c->len] = lim;
      +        }
       
      -  return res;
      +	return res;
       }
       
      +
      +
       // Try to match a scheme including colon.
      -bufsize_t _scan_scheme(const unsigned char *p) {
      +bufsize_t _scan_scheme(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    yych = *p;
      -    if (yych <= '@')
      -      goto yy2;
      -    if (yych <= 'Z')
      -      goto yy4;
      -    if (yych <= '`')
      -      goto yy2;
      -    if (yych <= 'z')
      -      goto yy4;
      -  yy2:
      -    ++p;
      -  yy3 : { return 0; }
      -  yy4:
      -    yych = *(marker = ++p);
      -    if (yych <= '/') {
      -      if (yych <= '+') {
      -        if (yych <= '*')
      -          goto yy3;
      -      } else {
      -        if (yych <= ',')
      -          goto yy3;
      -        if (yych >= '/')
      -          goto yy3;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '9')
      -          goto yy5;
      -        if (yych <= '@')
      -          goto yy3;
      -      } else {
      -        if (yych <= '`')
      -          goto yy3;
      -        if (yych >= '{')
      -          goto yy3;
      -      }
      -    }
      -  yy5:
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych == '+')
      -          goto yy7;
      -      } else {
      -        if (yych != '/')
      -          goto yy7;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych >= 'A')
      -          goto yy7;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych <= 'z')
      -          goto yy7;
      -      }
      -    }
      -  yy6:
      -    p = marker;
      -    goto yy3;
      -  yy7:
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych == '+')
      -          goto yy10;
      -        goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -        goto yy10;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -        goto yy10;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych <= 'z')
      -          goto yy10;
      -        goto yy6;
      -      }
      -    }
      -  yy8:
      -    ++p;
      -    { return (bufsize_t)(p - start); }
      -  yy10:
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy6;
      -      } else {
      -        if (yych == '/')
      -          goto yy6;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy8;
      -        if (yych <= '@')
      -          goto yy6;
      -      } else {
      -        if (yych <= '`')
      -          goto yy6;
      -        if (yych >= '{')
      -          goto yy6;
      -      }
      -    }
      -    ++p;
      -    if ((yych = *p) == ':')
      -      goto yy8;
      -    goto yy6;
      -  }
      +{
      +	unsigned char yych;
      +	yych = *p;
      +	if (yych <= '@') goto yy2;
      +	if (yych <= 'Z') goto yy4;
      +	if (yych <= '`') goto yy2;
      +	if (yych <= 'z') goto yy4;
      +yy2:
      +	++p;
      +yy3:
      +	{ return 0; }
      +yy4:
      +	yych = *(marker = ++p);
      +	if (yych <= '/') {
      +		if (yych <= '+') {
      +			if (yych <= '*') goto yy3;
      +		} else {
      +			if (yych <= ',') goto yy3;
      +			if (yych >= '/') goto yy3;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '9') goto yy5;
      +			if (yych <= '@') goto yy3;
      +		} else {
      +			if (yych <= '`') goto yy3;
      +			if (yych >= '{') goto yy3;
      +		}
      +	}
      +yy5:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych == '+') goto yy7;
      +		} else {
      +			if (yych != '/') goto yy7;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych >= 'A') goto yy7;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych <= 'z') goto yy7;
      +		}
      +	}
      +yy6:
      +	p = marker;
      +	goto yy3;
      +yy7:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych == '+') goto yy10;
      +			goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +			goto yy10;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +			goto yy10;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych <= 'z') goto yy10;
      +			goto yy6;
      +		}
      +	}
      +yy8:
      +	++p;
      +	{ return (bufsize_t)(p - start); }
      +yy10:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy6;
      +		} else {
      +			if (yych == '/') goto yy6;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy8;
      +			if (yych <= '@') goto yy6;
      +		} else {
      +			if (yych <= '`') goto yy6;
      +			if (yych >= '{') goto yy6;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych == ':') goto yy8;
      +	goto yy6;
      +}
      +
       }
       
       // Try to match URI autolink after first <, returning number of chars matched.
      -bufsize_t _scan_autolink_uri(const unsigned char *p) {
      +bufsize_t _scan_autolink_uri(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    static const unsigned char yybm[] = {
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 0,   128, 0,   128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,
      -    };
      -    yych = *p;
      -    if (yych <= '@')
      -      goto yy41;
      -    if (yych <= 'Z')
      -      goto yy43;
      -    if (yych <= '`')
      -      goto yy41;
      -    if (yych <= 'z')
      -      goto yy43;
      -  yy41:
      -    ++p;
      -  yy42 : { return 0; }
      -  yy43:
      -    yych = *(marker = ++p);
      -    if (yych <= '/') {
      -      if (yych <= '+') {
      -        if (yych <= '*')
      -          goto yy42;
      -      } else {
      -        if (yych <= ',')
      -          goto yy42;
      -        if (yych >= '/')
      -          goto yy42;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '9')
      -          goto yy44;
      -        if (yych <= '@')
      -          goto yy42;
      -      } else {
      -        if (yych <= '`')
      -          goto yy42;
      -        if (yych >= '{')
      -          goto yy42;
      -      }
      -    }
      -  yy44:
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych == '+')
      -          goto yy46;
      -      } else {
      -        if (yych != '/')
      -          goto yy46;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych >= 'A')
      -          goto yy46;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych <= 'z')
      -          goto yy46;
      -      }
      -    }
      -  yy45:
      -    p = marker;
      -    goto yy42;
      -  yy46:
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych == '+')
      -          goto yy49;
      -        goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -        goto yy49;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -        goto yy49;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych <= 'z')
      -          goto yy49;
      -        goto yy45;
      -      }
      -    }
      -  yy47:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy47;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '<')
      -          goto yy45;
      -        if (yych <= '>')
      -          goto yy50;
      -        goto yy45;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy52;
      -        if (yych <= 0xE0)
      -          goto yy53;
      -        goto yy54;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy55;
      -        if (yych <= 0xEF)
      -          goto yy54;
      -        goto yy56;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy57;
      -        if (yych <= 0xF4)
      -          goto yy58;
      -        goto yy45;
      -      }
      -    }
      -  yy49:
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych == '+')
      -          goto yy59;
      -        goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -        goto yy59;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -        goto yy59;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych <= 'z')
      -          goto yy59;
      -        goto yy45;
      -      }
      -    }
      -  yy50:
      -    ++p;
      -    { return (bufsize_t)(p - start); }
      -  yy52:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy45;
      -    if (yych <= 0xBF)
      -      goto yy47;
      -    goto yy45;
      -  yy53:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy45;
      -    if (yych <= 0xBF)
      -      goto yy52;
      -    goto yy45;
      -  yy54:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy45;
      -    if (yych <= 0xBF)
      -      goto yy52;
      -    goto yy45;
      -  yy55:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy45;
      -    if (yych <= 0x9F)
      -      goto yy52;
      -    goto yy45;
      -  yy56:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy45;
      -    if (yych <= 0xBF)
      -      goto yy54;
      -    goto yy45;
      -  yy57:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy45;
      -    if (yych <= 0xBF)
      -      goto yy54;
      -    goto yy45;
      -  yy58:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy45;
      -    if (yych <= 0x8F)
      -      goto yy54;
      -    goto yy45;
      -  yy59:
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    yych = *++p;
      -    if (yych <= '9') {
      -      if (yych <= ',') {
      -        if (yych != '+')
      -          goto yy45;
      -      } else {
      -        if (yych == '/')
      -          goto yy45;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= ':')
      -          goto yy47;
      -        if (yych <= '@')
      -          goto yy45;
      -      } else {
      -        if (yych <= '`')
      -          goto yy45;
      -        if (yych >= '{')
      -          goto yy45;
      -      }
      -    }
      -    ++p;
      -    if ((yych = *p) == ':')
      -      goto yy47;
      -    goto yy45;
      -  }
      +{
      +	unsigned char yych;
      +	static const unsigned char yybm[] = {
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128,   0, 128,   0, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych <= '@') goto yy41;
      +	if (yych <= 'Z') goto yy43;
      +	if (yych <= '`') goto yy41;
      +	if (yych <= 'z') goto yy43;
      +yy41:
      +	++p;
      +yy42:
      +	{ return 0; }
      +yy43:
      +	yych = *(marker = ++p);
      +	if (yych <= '/') {
      +		if (yych <= '+') {
      +			if (yych <= '*') goto yy42;
      +		} else {
      +			if (yych <= ',') goto yy42;
      +			if (yych >= '/') goto yy42;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '9') goto yy44;
      +			if (yych <= '@') goto yy42;
      +		} else {
      +			if (yych <= '`') goto yy42;
      +			if (yych >= '{') goto yy42;
      +		}
      +	}
      +yy44:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych == '+') goto yy46;
      +		} else {
      +			if (yych != '/') goto yy46;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych >= 'A') goto yy46;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych <= 'z') goto yy46;
      +		}
      +	}
      +yy45:
      +	p = marker;
      +	goto yy42;
      +yy46:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych == '+') goto yy49;
      +			goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +			goto yy49;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +			goto yy49;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych <= 'z') goto yy49;
      +			goto yy45;
      +		}
      +	}
      +yy47:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy47;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '<') goto yy45;
      +			if (yych <= '>') goto yy50;
      +			goto yy45;
      +		} else {
      +			if (yych <= 0xDF) goto yy52;
      +			if (yych <= 0xE0) goto yy53;
      +			goto yy54;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy55;
      +			if (yych <= 0xEF) goto yy54;
      +			goto yy56;
      +		} else {
      +			if (yych <= 0xF3) goto yy57;
      +			if (yych <= 0xF4) goto yy58;
      +			goto yy45;
      +		}
      +	}
      +yy49:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych == '+') goto yy59;
      +			goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +			goto yy59;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +			goto yy59;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych <= 'z') goto yy59;
      +			goto yy45;
      +		}
      +	}
      +yy50:
      +	++p;
      +	{ return (bufsize_t)(p - start); }
      +yy52:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy45;
      +	if (yych <= 0xBF) goto yy47;
      +	goto yy45;
      +yy53:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy45;
      +	if (yych <= 0xBF) goto yy52;
      +	goto yy45;
      +yy54:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy45;
      +	if (yych <= 0xBF) goto yy52;
      +	goto yy45;
      +yy55:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy45;
      +	if (yych <= 0x9F) goto yy52;
      +	goto yy45;
      +yy56:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy45;
      +	if (yych <= 0xBF) goto yy54;
      +	goto yy45;
      +yy57:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy45;
      +	if (yych <= 0xBF) goto yy54;
      +	goto yy45;
      +yy58:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy45;
      +	if (yych <= 0x8F) goto yy54;
      +	goto yy45;
      +yy59:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych <= ',') {
      +			if (yych != '+') goto yy45;
      +		} else {
      +			if (yych == '/') goto yy45;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= ':') goto yy47;
      +			if (yych <= '@') goto yy45;
      +		} else {
      +			if (yych <= '`') goto yy45;
      +			if (yych >= '{') goto yy45;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych == ':') goto yy47;
      +	goto yy45;
      +}
      +
       }
       
       // Try to match email autolink after first <, returning num of chars matched.
      -bufsize_t _scan_autolink_email(const unsigned char *p) {
      +bufsize_t _scan_autolink_email(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    static const unsigned char yybm[] = {
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   128, 0,   128, 128, 128, 128, 128, 0,   0,
      -        128, 128, 0,   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 0,   0,   0,   128, 0,   128, 0,   128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 0,   0,   0,   128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,
      -    };
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych <= '\'') {
      -        if (yych == '!')
      -          goto yy91;
      -        if (yych >= '#')
      -          goto yy91;
      -      } else {
      -        if (yych <= ')')
      -          goto yy89;
      -        if (yych != ',')
      -          goto yy91;
      -      }
      -    } else {
      -      if (yych <= '?') {
      -        if (yych == '=')
      -          goto yy91;
      -        if (yych >= '?')
      -          goto yy91;
      -      } else {
      -        if (yych <= 'Z') {
      -          if (yych >= 'A')
      -            goto yy91;
      -        } else {
      -          if (yych <= ']')
      -            goto yy89;
      -          if (yych <= '~')
      -            goto yy91;
      -        }
      -      }
      -    }
      -  yy89:
      -    ++p;
      -  yy90 : { return 0; }
      -  yy91:
      -    yych = *(marker = ++p);
      -    if (yych <= ',') {
      -      if (yych <= '"') {
      -        if (yych == '!')
      -          goto yy93;
      -        goto yy90;
      -      } else {
      -        if (yych <= '\'')
      -          goto yy93;
      -        if (yych <= ')')
      -          goto yy90;
      -        if (yych <= '+')
      -          goto yy93;
      -        goto yy90;
      -      }
      -    } else {
      -      if (yych <= '>') {
      -        if (yych <= '9')
      -          goto yy93;
      -        if (yych == '=')
      -          goto yy93;
      -        goto yy90;
      -      } else {
      -        if (yych <= 'Z')
      -          goto yy93;
      -        if (yych <= ']')
      -          goto yy90;
      -        if (yych <= '~')
      -          goto yy93;
      -        goto yy90;
      -      }
      -    }
      -  yy92:
      -    ++p;
      -    yych = *p;
      -  yy93:
      -    if (yybm[0 + yych] & 128) {
      -      goto yy92;
      -    }
      -    if (yych <= '>')
      -      goto yy94;
      -    if (yych <= '@')
      -      goto yy95;
      -  yy94:
      -    p = marker;
      -    goto yy90;
      -  yy95:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '@') {
      -      if (yych <= '/')
      -        goto yy94;
      -      if (yych >= ':')
      -        goto yy94;
      -    } else {
      -      if (yych <= 'Z')
      -        goto yy96;
      -      if (yych <= '`')
      -        goto yy94;
      -      if (yych >= '{')
      -        goto yy94;
      -    }
      -  yy96:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy98;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy98;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy98;
      -        goto yy94;
      -      }
      -    }
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy101;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy102;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy102;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy102;
      -        goto yy94;
      -      }
      -    }
      -  yy98:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych <= '-')
      -          goto yy101;
      -        goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy102;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy102;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy102;
      -        goto yy94;
      -      }
      -    }
      -  yy99:
      -    ++p;
      -    { return (bufsize_t)(p - start); }
      -  yy101:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy103;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy104;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy104;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy104;
      -        goto yy94;
      -      }
      -    }
      -  yy102:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy104;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy104;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy104;
      -        goto yy94;
      -      }
      -    }
      -  yy103:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy105;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy106;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy106;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy106;
      -        goto yy94;
      -      }
      -    }
      -  yy104:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy106;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy106;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy106;
      -        goto yy94;
      -      }
      -    }
      -  yy105:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy107;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy108;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy108;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy108;
      -        goto yy94;
      -      }
      -    }
      -  yy106:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy108;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy108;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy108;
      -        goto yy94;
      -      }
      -    }
      -  yy107:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy109;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy110;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy110;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy110;
      -        goto yy94;
      -      }
      -    }
      -  yy108:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy110;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy110;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy110;
      -        goto yy94;
      -      }
      -    }
      -  yy109:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy111;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy112;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy112;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy112;
      -        goto yy94;
      -      }
      -    }
      -  yy110:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy112;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy112;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy112;
      -        goto yy94;
      -      }
      -    }
      -  yy111:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy113;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy114;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy114;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy114;
      -        goto yy94;
      -      }
      -    }
      -  yy112:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy114;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy114;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy114;
      -        goto yy94;
      -      }
      -    }
      -  yy113:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy115;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy116;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy116;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy116;
      -        goto yy94;
      -      }
      -    }
      -  yy114:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy116;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy116;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy116;
      -        goto yy94;
      -      }
      -    }
      -  yy115:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy117;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy118;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy118;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy118;
      -        goto yy94;
      -      }
      -    }
      -  yy116:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy118;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy118;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy118;
      -        goto yy94;
      -      }
      -    }
      -  yy117:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy119;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy120;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy120;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy120;
      -        goto yy94;
      -      }
      -    }
      -  yy118:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy120;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy120;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy120;
      -        goto yy94;
      -      }
      -    }
      -  yy119:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy121;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy122;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy122;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy122;
      -        goto yy94;
      -      }
      -    }
      -  yy120:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy122;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy122;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy122;
      -        goto yy94;
      -      }
      -    }
      -  yy121:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy123;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy124;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy124;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy124;
      -        goto yy94;
      -      }
      -    }
      -  yy122:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy124;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy124;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy124;
      -        goto yy94;
      -      }
      -    }
      -  yy123:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy125;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy126;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy126;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy126;
      -        goto yy94;
      -      }
      -    }
      -  yy124:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy126;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy126;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy126;
      -        goto yy94;
      -      }
      -    }
      -  yy125:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy127;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy128;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy128;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy128;
      -        goto yy94;
      -      }
      -    }
      -  yy126:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy128;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy128;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy128;
      -        goto yy94;
      -      }
      -    }
      -  yy127:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy129;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy130;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy130;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy130;
      -        goto yy94;
      -      }
      -    }
      -  yy128:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy130;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy130;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy130;
      -        goto yy94;
      -      }
      -    }
      -  yy129:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy131;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy132;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy132;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy132;
      -        goto yy94;
      -      }
      -    }
      -  yy130:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy132;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy132;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy132;
      -        goto yy94;
      -      }
      -    }
      -  yy131:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy133;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy134;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy134;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy134;
      -        goto yy94;
      -      }
      -    }
      -  yy132:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy134;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy134;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy134;
      -        goto yy94;
      -      }
      -    }
      -  yy133:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy135;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy136;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy136;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy136;
      -        goto yy94;
      -      }
      -    }
      -  yy134:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy136;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy136;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy136;
      -        goto yy94;
      -      }
      -    }
      -  yy135:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy137;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy138;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy138;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy138;
      -        goto yy94;
      -      }
      -    }
      -  yy136:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy138;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy138;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy138;
      -        goto yy94;
      -      }
      -    }
      -  yy137:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy139;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy140;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy140;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy140;
      -        goto yy94;
      -      }
      -    }
      -  yy138:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy140;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy140;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy140;
      -        goto yy94;
      -      }
      -    }
      -  yy139:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy141;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy142;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy142;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy142;
      -        goto yy94;
      -      }
      -    }
      -  yy140:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy142;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy142;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy142;
      -        goto yy94;
      -      }
      -    }
      -  yy141:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy143;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy144;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy144;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy144;
      -        goto yy94;
      -      }
      -    }
      -  yy142:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy144;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy144;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy144;
      -        goto yy94;
      -      }
      -    }
      -  yy143:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy145;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy146;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy146;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy146;
      -        goto yy94;
      -      }
      -    }
      -  yy144:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy146;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy146;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy146;
      -        goto yy94;
      -      }
      -    }
      -  yy145:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy147;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy148;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy148;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy148;
      -        goto yy94;
      -      }
      -    }
      -  yy146:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy148;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy148;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy148;
      -        goto yy94;
      -      }
      -    }
      -  yy147:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy149;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy150;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy150;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy150;
      -        goto yy94;
      -      }
      -    }
      -  yy148:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy150;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy150;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy150;
      -        goto yy94;
      -      }
      -    }
      -  yy149:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy151;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy152;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy152;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy152;
      -        goto yy94;
      -      }
      -    }
      -  yy150:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy152;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy152;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy152;
      -        goto yy94;
      -      }
      -    }
      -  yy151:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy153;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy154;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy154;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy154;
      -        goto yy94;
      -      }
      -    }
      -  yy152:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy154;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy154;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy154;
      -        goto yy94;
      -      }
      -    }
      -  yy153:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy155;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy156;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy156;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy156;
      -        goto yy94;
      -      }
      -    }
      -  yy154:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy156;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy156;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy156;
      -        goto yy94;
      -      }
      -    }
      -  yy155:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy157;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy158;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy158;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy158;
      -        goto yy94;
      -      }
      -    }
      -  yy156:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy158;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy158;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy158;
      -        goto yy94;
      -      }
      -    }
      -  yy157:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy159;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy160;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy160;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy160;
      -        goto yy94;
      -      }
      -    }
      -  yy158:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy160;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy160;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy160;
      -        goto yy94;
      -      }
      -    }
      -  yy159:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy161;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy162;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy162;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy162;
      -        goto yy94;
      -      }
      -    }
      -  yy160:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy162;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy162;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy162;
      -        goto yy94;
      -      }
      -    }
      -  yy161:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy163;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy164;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy164;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy164;
      -        goto yy94;
      -      }
      -    }
      -  yy162:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy164;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy164;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy164;
      -        goto yy94;
      -      }
      -    }
      -  yy163:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy165;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy166;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy166;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy166;
      -        goto yy94;
      -      }
      -    }
      -  yy164:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy166;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy166;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy166;
      -        goto yy94;
      -      }
      -    }
      -  yy165:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy167;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy168;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy168;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy168;
      -        goto yy94;
      -      }
      -    }
      -  yy166:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy168;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy168;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy168;
      -        goto yy94;
      -      }
      -    }
      -  yy167:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy169;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy170;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy170;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy170;
      -        goto yy94;
      -      }
      -    }
      -  yy168:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy170;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy170;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy170;
      -        goto yy94;
      -      }
      -    }
      -  yy169:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy171;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy172;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy172;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy172;
      -        goto yy94;
      -      }
      -    }
      -  yy170:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy172;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy172;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy172;
      -        goto yy94;
      -      }
      -    }
      -  yy171:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy173;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy174;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy174;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy174;
      -        goto yy94;
      -      }
      -    }
      -  yy172:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy174;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy174;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy174;
      -        goto yy94;
      -      }
      -    }
      -  yy173:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy175;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy176;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy176;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy176;
      -        goto yy94;
      -      }
      -    }
      -  yy174:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy176;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy176;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy176;
      -        goto yy94;
      -      }
      -    }
      -  yy175:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy177;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy178;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy178;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy178;
      -        goto yy94;
      -      }
      -    }
      -  yy176:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy178;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy178;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy178;
      -        goto yy94;
      -      }
      -    }
      -  yy177:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy179;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy180;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy180;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy180;
      -        goto yy94;
      -      }
      -    }
      -  yy178:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy180;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy180;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy180;
      -        goto yy94;
      -      }
      -    }
      -  yy179:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy181;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy182;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy182;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy182;
      -        goto yy94;
      -      }
      -    }
      -  yy180:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy182;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy182;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy182;
      -        goto yy94;
      -      }
      -    }
      -  yy181:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy183;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy184;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy184;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy184;
      -        goto yy94;
      -      }
      -    }
      -  yy182:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy184;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy184;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy184;
      -        goto yy94;
      -      }
      -    }
      -  yy183:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy185;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy186;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy186;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy186;
      -        goto yy94;
      -      }
      -    }
      -  yy184:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy186;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy186;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy186;
      -        goto yy94;
      -      }
      -    }
      -  yy185:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy187;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy188;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy188;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy188;
      -        goto yy94;
      -      }
      -    }
      -  yy186:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy188;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy188;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy188;
      -        goto yy94;
      -      }
      -    }
      -  yy187:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy189;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy190;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy190;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy190;
      -        goto yy94;
      -      }
      -    }
      -  yy188:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy190;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy190;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy190;
      -        goto yy94;
      -      }
      -    }
      -  yy189:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy191;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy192;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy192;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy192;
      -        goto yy94;
      -      }
      -    }
      -  yy190:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy192;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy192;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy192;
      -        goto yy94;
      -      }
      -    }
      -  yy191:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy193;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy194;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy194;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy194;
      -        goto yy94;
      -      }
      -    }
      -  yy192:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy194;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy194;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy194;
      -        goto yy94;
      -      }
      -    }
      -  yy193:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy195;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy196;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy196;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy196;
      -        goto yy94;
      -      }
      -    }
      -  yy194:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy196;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy196;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy196;
      -        goto yy94;
      -      }
      -    }
      -  yy195:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy197;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy198;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy198;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy198;
      -        goto yy94;
      -      }
      -    }
      -  yy196:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy198;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy198;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy198;
      -        goto yy94;
      -      }
      -    }
      -  yy197:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy199;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy200;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy200;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy200;
      -        goto yy94;
      -      }
      -    }
      -  yy198:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy200;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy200;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy200;
      -        goto yy94;
      -      }
      -    }
      -  yy199:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy201;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy202;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy202;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy202;
      -        goto yy94;
      -      }
      -    }
      -  yy200:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy202;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy202;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy202;
      -        goto yy94;
      -      }
      -    }
      -  yy201:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy203;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy204;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy204;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy204;
      -        goto yy94;
      -      }
      -    }
      -  yy202:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy204;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy204;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy204;
      -        goto yy94;
      -      }
      -    }
      -  yy203:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy205;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy206;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy206;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy206;
      -        goto yy94;
      -      }
      -    }
      -  yy204:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy206;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy206;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy206;
      -        goto yy94;
      -      }
      -    }
      -  yy205:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy207;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy208;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy208;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy208;
      -        goto yy94;
      -      }
      -    }
      -  yy206:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy208;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy208;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy208;
      -        goto yy94;
      -      }
      -    }
      -  yy207:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy209;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy210;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy210;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy210;
      -        goto yy94;
      -      }
      -    }
      -  yy208:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy210;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy210;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy210;
      -        goto yy94;
      -      }
      -    }
      -  yy209:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy211;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy212;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy212;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy212;
      -        goto yy94;
      -      }
      -    }
      -  yy210:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy212;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy212;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy212;
      -        goto yy94;
      -      }
      -    }
      -  yy211:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy213;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy214;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy214;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy214;
      -        goto yy94;
      -      }
      -    }
      -  yy212:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy214;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy214;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy214;
      -        goto yy94;
      -      }
      -    }
      -  yy213:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy215;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy216;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy216;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy216;
      -        goto yy94;
      -      }
      -    }
      -  yy214:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy216;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy216;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy216;
      -        goto yy94;
      -      }
      -    }
      -  yy215:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy217;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy218;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy218;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy218;
      -        goto yy94;
      -      }
      -    }
      -  yy216:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy218;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy218;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy218;
      -        goto yy94;
      -      }
      -    }
      -  yy217:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '9') {
      -      if (yych == '-')
      -        goto yy219;
      -      if (yych <= '/')
      -        goto yy94;
      -      goto yy220;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy220;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy220;
      -        goto yy94;
      -      }
      -    }
      -  yy218:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= ',')
      -          goto yy94;
      -        if (yych >= '.')
      -          goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych <= '9')
      -          goto yy220;
      -        goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -        goto yy220;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych <= 'z')
      -          goto yy220;
      -        goto yy94;
      -      }
      -    }
      -  yy219:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '@') {
      -      if (yych <= '/')
      -        goto yy94;
      -      if (yych <= '9')
      -        goto yy221;
      -      goto yy94;
      -    } else {
      -      if (yych <= 'Z')
      -        goto yy221;
      -      if (yych <= '`')
      -        goto yy94;
      -      if (yych <= 'z')
      -        goto yy221;
      -      goto yy94;
      -    }
      -  yy220:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych <= '-')
      -          goto yy94;
      -        goto yy95;
      -      } else {
      -        if (yych <= '/')
      -          goto yy94;
      -        if (yych >= ':')
      -          goto yy94;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy99;
      -        if (yych <= '@')
      -          goto yy94;
      -      } else {
      -        if (yych <= '`')
      -          goto yy94;
      -        if (yych >= '{')
      -          goto yy94;
      -      }
      -    }
      -  yy221:
      -    ++p;
      -    yych = *p;
      -    if (yych == '.')
      -      goto yy95;
      -    if (yych == '>')
      -      goto yy99;
      -    goto yy94;
      -  }
      +{
      +	unsigned char yych;
      +	static const unsigned char yybm[] = {
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0, 128,   0, 128, 128, 128, 128, 128, 
      +		  0,   0, 128, 128,   0, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128,   0,   0,   0, 128,   0, 128, 
      +		  0, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128,   0,   0,   0, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych <= '9') {
      +		if (yych <= '\'') {
      +			if (yych == '!') goto yy91;
      +			if (yych >= '#') goto yy91;
      +		} else {
      +			if (yych <= ')') goto yy89;
      +			if (yych != ',') goto yy91;
      +		}
      +	} else {
      +		if (yych <= '?') {
      +			if (yych == '=') goto yy91;
      +			if (yych >= '?') goto yy91;
      +		} else {
      +			if (yych <= 'Z') {
      +				if (yych >= 'A') goto yy91;
      +			} else {
      +				if (yych <= ']') goto yy89;
      +				if (yych <= '~') goto yy91;
      +			}
      +		}
      +	}
      +yy89:
      +	++p;
      +yy90:
      +	{ return 0; }
      +yy91:
      +	yych = *(marker = ++p);
      +	if (yych <= ',') {
      +		if (yych <= '"') {
      +			if (yych == '!') goto yy93;
      +			goto yy90;
      +		} else {
      +			if (yych <= '\'') goto yy93;
      +			if (yych <= ')') goto yy90;
      +			if (yych <= '+') goto yy93;
      +			goto yy90;
      +		}
      +	} else {
      +		if (yych <= '>') {
      +			if (yych <= '9') goto yy93;
      +			if (yych == '=') goto yy93;
      +			goto yy90;
      +		} else {
      +			if (yych <= 'Z') goto yy93;
      +			if (yych <= ']') goto yy90;
      +			if (yych <= '~') goto yy93;
      +			goto yy90;
      +		}
      +	}
      +yy92:
      +	yych = *++p;
      +yy93:
      +	if (yybm[0+yych] & 128) {
      +		goto yy92;
      +	}
      +	if (yych <= '>') goto yy94;
      +	if (yych <= '@') goto yy95;
      +yy94:
      +	p = marker;
      +	goto yy90;
      +yy95:
      +	yych = *++p;
      +	if (yych <= '@') {
      +		if (yych <= '/') goto yy94;
      +		if (yych >= ':') goto yy94;
      +	} else {
      +		if (yych <= 'Z') goto yy96;
      +		if (yych <= '`') goto yy94;
      +		if (yych >= '{') goto yy94;
      +	}
      +yy96:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy98;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy98;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy98;
      +			goto yy94;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy101;
      +		if (yych <= '/') goto yy94;
      +		goto yy102;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy102;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy102;
      +			goto yy94;
      +		}
      +	}
      +yy98:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych <= '-') goto yy101;
      +			goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy102;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy102;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy102;
      +			goto yy94;
      +		}
      +	}
      +yy99:
      +	++p;
      +	{ return (bufsize_t)(p - start); }
      +yy101:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy103;
      +		if (yych <= '/') goto yy94;
      +		goto yy104;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy104;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy104;
      +			goto yy94;
      +		}
      +	}
      +yy102:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy104;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy104;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy104;
      +			goto yy94;
      +		}
      +	}
      +yy103:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy105;
      +		if (yych <= '/') goto yy94;
      +		goto yy106;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy106;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy106;
      +			goto yy94;
      +		}
      +	}
      +yy104:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy106;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy106;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy106;
      +			goto yy94;
      +		}
      +	}
      +yy105:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy107;
      +		if (yych <= '/') goto yy94;
      +		goto yy108;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy108;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy108;
      +			goto yy94;
      +		}
      +	}
      +yy106:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy108;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy108;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy108;
      +			goto yy94;
      +		}
      +	}
      +yy107:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy109;
      +		if (yych <= '/') goto yy94;
      +		goto yy110;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy110;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy110;
      +			goto yy94;
      +		}
      +	}
      +yy108:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy110;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy110;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy110;
      +			goto yy94;
      +		}
      +	}
      +yy109:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy111;
      +		if (yych <= '/') goto yy94;
      +		goto yy112;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy112;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy112;
      +			goto yy94;
      +		}
      +	}
      +yy110:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy112;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy112;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy112;
      +			goto yy94;
      +		}
      +	}
      +yy111:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy113;
      +		if (yych <= '/') goto yy94;
      +		goto yy114;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy114;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy114;
      +			goto yy94;
      +		}
      +	}
      +yy112:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy114;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy114;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy114;
      +			goto yy94;
      +		}
      +	}
      +yy113:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy115;
      +		if (yych <= '/') goto yy94;
      +		goto yy116;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy116;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy116;
      +			goto yy94;
      +		}
      +	}
      +yy114:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy116;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy116;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy116;
      +			goto yy94;
      +		}
      +	}
      +yy115:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy117;
      +		if (yych <= '/') goto yy94;
      +		goto yy118;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy118;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy118;
      +			goto yy94;
      +		}
      +	}
      +yy116:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy118;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy118;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy118;
      +			goto yy94;
      +		}
      +	}
      +yy117:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy119;
      +		if (yych <= '/') goto yy94;
      +		goto yy120;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy120;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy120;
      +			goto yy94;
      +		}
      +	}
      +yy118:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy120;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy120;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy120;
      +			goto yy94;
      +		}
      +	}
      +yy119:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy121;
      +		if (yych <= '/') goto yy94;
      +		goto yy122;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy122;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy122;
      +			goto yy94;
      +		}
      +	}
      +yy120:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy122;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy122;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy122;
      +			goto yy94;
      +		}
      +	}
      +yy121:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy123;
      +		if (yych <= '/') goto yy94;
      +		goto yy124;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy124;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy124;
      +			goto yy94;
      +		}
      +	}
      +yy122:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy124;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy124;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy124;
      +			goto yy94;
      +		}
      +	}
      +yy123:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy125;
      +		if (yych <= '/') goto yy94;
      +		goto yy126;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy126;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy126;
      +			goto yy94;
      +		}
      +	}
      +yy124:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy126;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy126;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy126;
      +			goto yy94;
      +		}
      +	}
      +yy125:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy127;
      +		if (yych <= '/') goto yy94;
      +		goto yy128;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy128;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy128;
      +			goto yy94;
      +		}
      +	}
      +yy126:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy128;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy128;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy128;
      +			goto yy94;
      +		}
      +	}
      +yy127:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy129;
      +		if (yych <= '/') goto yy94;
      +		goto yy130;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy130;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy130;
      +			goto yy94;
      +		}
      +	}
      +yy128:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy130;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy130;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy130;
      +			goto yy94;
      +		}
      +	}
      +yy129:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy131;
      +		if (yych <= '/') goto yy94;
      +		goto yy132;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy132;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy132;
      +			goto yy94;
      +		}
      +	}
      +yy130:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy132;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy132;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy132;
      +			goto yy94;
      +		}
      +	}
      +yy131:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy133;
      +		if (yych <= '/') goto yy94;
      +		goto yy134;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy134;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy134;
      +			goto yy94;
      +		}
      +	}
      +yy132:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy134;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy134;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy134;
      +			goto yy94;
      +		}
      +	}
      +yy133:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy135;
      +		if (yych <= '/') goto yy94;
      +		goto yy136;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy136;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy136;
      +			goto yy94;
      +		}
      +	}
      +yy134:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy136;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy136;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy136;
      +			goto yy94;
      +		}
      +	}
      +yy135:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy137;
      +		if (yych <= '/') goto yy94;
      +		goto yy138;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy138;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy138;
      +			goto yy94;
      +		}
      +	}
      +yy136:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy138;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy138;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy138;
      +			goto yy94;
      +		}
      +	}
      +yy137:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy139;
      +		if (yych <= '/') goto yy94;
      +		goto yy140;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy140;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy140;
      +			goto yy94;
      +		}
      +	}
      +yy138:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy140;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy140;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy140;
      +			goto yy94;
      +		}
      +	}
      +yy139:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy141;
      +		if (yych <= '/') goto yy94;
      +		goto yy142;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy142;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy142;
      +			goto yy94;
      +		}
      +	}
      +yy140:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy142;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy142;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy142;
      +			goto yy94;
      +		}
      +	}
      +yy141:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy143;
      +		if (yych <= '/') goto yy94;
      +		goto yy144;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy144;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy144;
      +			goto yy94;
      +		}
      +	}
      +yy142:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy144;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy144;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy144;
      +			goto yy94;
      +		}
      +	}
      +yy143:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy145;
      +		if (yych <= '/') goto yy94;
      +		goto yy146;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy146;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy146;
      +			goto yy94;
      +		}
      +	}
      +yy144:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy146;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy146;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy146;
      +			goto yy94;
      +		}
      +	}
      +yy145:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy147;
      +		if (yych <= '/') goto yy94;
      +		goto yy148;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy148;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy148;
      +			goto yy94;
      +		}
      +	}
      +yy146:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy148;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy148;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy148;
      +			goto yy94;
      +		}
      +	}
      +yy147:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy149;
      +		if (yych <= '/') goto yy94;
      +		goto yy150;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy150;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy150;
      +			goto yy94;
      +		}
      +	}
      +yy148:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy150;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy150;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy150;
      +			goto yy94;
      +		}
      +	}
      +yy149:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy151;
      +		if (yych <= '/') goto yy94;
      +		goto yy152;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy152;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy152;
      +			goto yy94;
      +		}
      +	}
      +yy150:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy152;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy152;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy152;
      +			goto yy94;
      +		}
      +	}
      +yy151:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy153;
      +		if (yych <= '/') goto yy94;
      +		goto yy154;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy154;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy154;
      +			goto yy94;
      +		}
      +	}
      +yy152:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy154;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy154;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy154;
      +			goto yy94;
      +		}
      +	}
      +yy153:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy155;
      +		if (yych <= '/') goto yy94;
      +		goto yy156;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy156;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy156;
      +			goto yy94;
      +		}
      +	}
      +yy154:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy156;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy156;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy156;
      +			goto yy94;
      +		}
      +	}
      +yy155:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy157;
      +		if (yych <= '/') goto yy94;
      +		goto yy158;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy158;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy158;
      +			goto yy94;
      +		}
      +	}
      +yy156:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy158;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy158;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy158;
      +			goto yy94;
      +		}
      +	}
      +yy157:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy159;
      +		if (yych <= '/') goto yy94;
      +		goto yy160;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy160;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy160;
      +			goto yy94;
      +		}
      +	}
      +yy158:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy160;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy160;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy160;
      +			goto yy94;
      +		}
      +	}
      +yy159:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy161;
      +		if (yych <= '/') goto yy94;
      +		goto yy162;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy162;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy162;
      +			goto yy94;
      +		}
      +	}
      +yy160:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy162;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy162;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy162;
      +			goto yy94;
      +		}
      +	}
      +yy161:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy163;
      +		if (yych <= '/') goto yy94;
      +		goto yy164;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy164;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy164;
      +			goto yy94;
      +		}
      +	}
      +yy162:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy164;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy164;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy164;
      +			goto yy94;
      +		}
      +	}
      +yy163:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy165;
      +		if (yych <= '/') goto yy94;
      +		goto yy166;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy166;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy166;
      +			goto yy94;
      +		}
      +	}
      +yy164:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy166;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy166;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy166;
      +			goto yy94;
      +		}
      +	}
      +yy165:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy167;
      +		if (yych <= '/') goto yy94;
      +		goto yy168;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy168;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy168;
      +			goto yy94;
      +		}
      +	}
      +yy166:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy168;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy168;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy168;
      +			goto yy94;
      +		}
      +	}
      +yy167:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy169;
      +		if (yych <= '/') goto yy94;
      +		goto yy170;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy170;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy170;
      +			goto yy94;
      +		}
      +	}
      +yy168:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy170;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy170;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy170;
      +			goto yy94;
      +		}
      +	}
      +yy169:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy171;
      +		if (yych <= '/') goto yy94;
      +		goto yy172;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy172;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy172;
      +			goto yy94;
      +		}
      +	}
      +yy170:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy172;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy172;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy172;
      +			goto yy94;
      +		}
      +	}
      +yy171:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy173;
      +		if (yych <= '/') goto yy94;
      +		goto yy174;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy174;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy174;
      +			goto yy94;
      +		}
      +	}
      +yy172:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy174;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy174;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy174;
      +			goto yy94;
      +		}
      +	}
      +yy173:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy175;
      +		if (yych <= '/') goto yy94;
      +		goto yy176;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy176;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy176;
      +			goto yy94;
      +		}
      +	}
      +yy174:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy176;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy176;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy176;
      +			goto yy94;
      +		}
      +	}
      +yy175:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy177;
      +		if (yych <= '/') goto yy94;
      +		goto yy178;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy178;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy178;
      +			goto yy94;
      +		}
      +	}
      +yy176:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy178;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy178;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy178;
      +			goto yy94;
      +		}
      +	}
      +yy177:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy179;
      +		if (yych <= '/') goto yy94;
      +		goto yy180;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy180;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy180;
      +			goto yy94;
      +		}
      +	}
      +yy178:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy180;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy180;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy180;
      +			goto yy94;
      +		}
      +	}
      +yy179:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy181;
      +		if (yych <= '/') goto yy94;
      +		goto yy182;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy182;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy182;
      +			goto yy94;
      +		}
      +	}
      +yy180:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy182;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy182;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy182;
      +			goto yy94;
      +		}
      +	}
      +yy181:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy183;
      +		if (yych <= '/') goto yy94;
      +		goto yy184;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy184;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy184;
      +			goto yy94;
      +		}
      +	}
      +yy182:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy184;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy184;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy184;
      +			goto yy94;
      +		}
      +	}
      +yy183:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy185;
      +		if (yych <= '/') goto yy94;
      +		goto yy186;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy186;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy186;
      +			goto yy94;
      +		}
      +	}
      +yy184:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy186;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy186;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy186;
      +			goto yy94;
      +		}
      +	}
      +yy185:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy187;
      +		if (yych <= '/') goto yy94;
      +		goto yy188;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy188;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy188;
      +			goto yy94;
      +		}
      +	}
      +yy186:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy188;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy188;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy188;
      +			goto yy94;
      +		}
      +	}
      +yy187:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy189;
      +		if (yych <= '/') goto yy94;
      +		goto yy190;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy190;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy190;
      +			goto yy94;
      +		}
      +	}
      +yy188:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy190;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy190;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy190;
      +			goto yy94;
      +		}
      +	}
      +yy189:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy191;
      +		if (yych <= '/') goto yy94;
      +		goto yy192;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy192;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy192;
      +			goto yy94;
      +		}
      +	}
      +yy190:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy192;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy192;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy192;
      +			goto yy94;
      +		}
      +	}
      +yy191:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy193;
      +		if (yych <= '/') goto yy94;
      +		goto yy194;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy194;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy194;
      +			goto yy94;
      +		}
      +	}
      +yy192:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy194;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy194;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy194;
      +			goto yy94;
      +		}
      +	}
      +yy193:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy195;
      +		if (yych <= '/') goto yy94;
      +		goto yy196;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy196;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy196;
      +			goto yy94;
      +		}
      +	}
      +yy194:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy196;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy196;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy196;
      +			goto yy94;
      +		}
      +	}
      +yy195:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy197;
      +		if (yych <= '/') goto yy94;
      +		goto yy198;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy198;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy198;
      +			goto yy94;
      +		}
      +	}
      +yy196:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy198;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy198;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy198;
      +			goto yy94;
      +		}
      +	}
      +yy197:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy199;
      +		if (yych <= '/') goto yy94;
      +		goto yy200;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy200;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy200;
      +			goto yy94;
      +		}
      +	}
      +yy198:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy200;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy200;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy200;
      +			goto yy94;
      +		}
      +	}
      +yy199:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy201;
      +		if (yych <= '/') goto yy94;
      +		goto yy202;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy202;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy202;
      +			goto yy94;
      +		}
      +	}
      +yy200:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy202;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy202;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy202;
      +			goto yy94;
      +		}
      +	}
      +yy201:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy203;
      +		if (yych <= '/') goto yy94;
      +		goto yy204;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy204;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy204;
      +			goto yy94;
      +		}
      +	}
      +yy202:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy204;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy204;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy204;
      +			goto yy94;
      +		}
      +	}
      +yy203:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy205;
      +		if (yych <= '/') goto yy94;
      +		goto yy206;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy206;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy206;
      +			goto yy94;
      +		}
      +	}
      +yy204:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy206;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy206;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy206;
      +			goto yy94;
      +		}
      +	}
      +yy205:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy207;
      +		if (yych <= '/') goto yy94;
      +		goto yy208;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy208;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy208;
      +			goto yy94;
      +		}
      +	}
      +yy206:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy208;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy208;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy208;
      +			goto yy94;
      +		}
      +	}
      +yy207:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy209;
      +		if (yych <= '/') goto yy94;
      +		goto yy210;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy210;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy210;
      +			goto yy94;
      +		}
      +	}
      +yy208:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy210;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy210;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy210;
      +			goto yy94;
      +		}
      +	}
      +yy209:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy211;
      +		if (yych <= '/') goto yy94;
      +		goto yy212;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy212;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy212;
      +			goto yy94;
      +		}
      +	}
      +yy210:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy212;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy212;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy212;
      +			goto yy94;
      +		}
      +	}
      +yy211:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy213;
      +		if (yych <= '/') goto yy94;
      +		goto yy214;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy214;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy214;
      +			goto yy94;
      +		}
      +	}
      +yy212:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy214;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy214;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy214;
      +			goto yy94;
      +		}
      +	}
      +yy213:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy215;
      +		if (yych <= '/') goto yy94;
      +		goto yy216;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy216;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy216;
      +			goto yy94;
      +		}
      +	}
      +yy214:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy216;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy216;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy216;
      +			goto yy94;
      +		}
      +	}
      +yy215:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy217;
      +		if (yych <= '/') goto yy94;
      +		goto yy218;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy218;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy218;
      +			goto yy94;
      +		}
      +	}
      +yy216:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy218;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy218;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy218;
      +			goto yy94;
      +		}
      +	}
      +yy217:
      +	yych = *++p;
      +	if (yych <= '9') {
      +		if (yych == '-') goto yy219;
      +		if (yych <= '/') goto yy94;
      +		goto yy220;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy94;
      +			goto yy220;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy220;
      +			goto yy94;
      +		}
      +	}
      +yy218:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= ',') goto yy94;
      +			if (yych >= '.') goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych <= '9') goto yy220;
      +			goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +			goto yy220;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych <= 'z') goto yy220;
      +			goto yy94;
      +		}
      +	}
      +yy219:
      +	yych = *++p;
      +	if (yych <= '@') {
      +		if (yych <= '/') goto yy94;
      +		if (yych <= '9') goto yy221;
      +		goto yy94;
      +	} else {
      +		if (yych <= 'Z') goto yy221;
      +		if (yych <= '`') goto yy94;
      +		if (yych <= 'z') goto yy221;
      +		goto yy94;
      +	}
      +yy220:
      +	yych = *++p;
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych <= '-') goto yy94;
      +			goto yy95;
      +		} else {
      +			if (yych <= '/') goto yy94;
      +			if (yych >= ':') goto yy94;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy99;
      +			if (yych <= '@') goto yy94;
      +		} else {
      +			if (yych <= '`') goto yy94;
      +			if (yych >= '{') goto yy94;
      +		}
      +	}
      +yy221:
      +	yych = *++p;
      +	if (yych == '.') goto yy95;
      +	if (yych == '>') goto yy99;
      +	goto yy94;
      +}
      +
       }
       
       // Try to match an HTML tag after first <, returning num of chars matched.
      -bufsize_t _scan_html_tag(const unsigned char *p) {
      +bufsize_t _scan_html_tag(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    static const unsigned char yybm[] = {
      -        /* table 1 .. 8: 0 */
      -        0,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        235,
      -        235,
      -        235,
      -        235,
      -        235,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        235,
      -        250,
      -        202,
      -        250,
      -        250,
      -        250,
      -        250,
      -        170,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        246,
      -        254,
      -        250,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        250,
      -        234,
      -        234,
      -        232,
      -        250,
      -        250,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        250,
      -        250,
      -        122,
      -        250,
      -        254,
      -        234,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        254,
      -        250,
      -        250,
      -        250,
      -        250,
      -        250,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        /* table 9 .. 11: 256 */
      -        0,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        192,
      -        128,
      -        128,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        0,
      -        128,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        224,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        192,
      -        128,
      -        128,
      -        128,
      -        128,
      -        128,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -        0,
      -    };
      -    yych = *p;
      -    if (yych <= '>') {
      -      if (yych <= '!') {
      -        if (yych >= '!')
      -          goto yy226;
      -      } else {
      -        if (yych == '/')
      -          goto yy227;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '?')
      -          goto yy228;
      -        if (yych >= 'A')
      -          goto yy229;
      -      } else {
      -        if (yych <= '`')
      -          goto yy224;
      -        if (yych <= 'z')
      -          goto yy229;
      -      }
      -    }
      -  yy224:
      -    ++p;
      -  yy225 : { return 0; }
      -  yy226:
      -    yych = *(marker = ++p);
      -    if (yybm[256 + yych] & 32) {
      -      goto yy232;
      -    }
      -    if (yych == '-')
      -      goto yy230;
      -    if (yych <= '@')
      -      goto yy225;
      -    if (yych <= '[')
      -      goto yy234;
      -    goto yy225;
      -  yy227:
      -    yych = *(marker = ++p);
      -    if (yych <= '@')
      -      goto yy225;
      -    if (yych <= 'Z')
      -      goto yy235;
      -    if (yych <= '`')
      -      goto yy225;
      -    if (yych <= 'z')
      -      goto yy235;
      -    goto yy225;
      -  yy228:
      -    yych = *(marker = ++p);
      -    if (yych <= 0x00)
      -      goto yy225;
      -    if (yych <= 0x7F)
      -      goto yy238;
      -    if (yych <= 0xC1)
      -      goto yy225;
      -    if (yych <= 0xF4)
      -      goto yy238;
      -    goto yy225;
      -  yy229:
      -    yych = *(marker = ++p);
      -    if (yybm[0 + yych] & 1) {
      -      goto yy247;
      -    }
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych == '-')
      -          goto yy249;
      -        goto yy225;
      -      } else {
      -        if (yych <= '/')
      -          goto yy251;
      -        if (yych <= '9')
      -          goto yy249;
      -        goto yy225;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy252;
      -        if (yych <= '@')
      -          goto yy225;
      -        goto yy249;
      -      } else {
      -        if (yych <= '`')
      -          goto yy225;
      -        if (yych <= 'z')
      -          goto yy249;
      -        goto yy225;
      -      }
      -    }
      -  yy230:
      -    yych = *++p;
      -    if (yych == '-')
      -      goto yy254;
      -  yy231:
      -    p = marker;
      -    goto yy225;
      -  yy232:
      -    ++p;
      -    yych = *p;
      -    if (yybm[256 + yych] & 32) {
      -      goto yy232;
      -    }
      -    if (yych <= 0x08)
      -      goto yy231;
      -    if (yych <= '\r')
      -      goto yy255;
      -    if (yych == ' ')
      -      goto yy255;
      -    goto yy231;
      -  yy234:
      -    yych = *++p;
      -    if (yych == 'C')
      -      goto yy257;
      -    if (yych == 'c')
      -      goto yy257;
      -    goto yy231;
      -  yy235:
      -    ++p;
      -    yych = *p;
      -    if (yybm[256 + yych] & 64) {
      -      goto yy235;
      -    }
      -    if (yych <= 0x1F) {
      -      if (yych <= 0x08)
      -        goto yy231;
      -      if (yych <= '\r')
      -        goto yy258;
      -      goto yy231;
      -    } else {
      -      if (yych <= ' ')
      -        goto yy258;
      -      if (yych == '>')
      -        goto yy252;
      -      goto yy231;
      -    }
      -  yy237:
      -    ++p;
      -    yych = *p;
      -  yy238:
      -    if (yybm[256 + yych] & 128) {
      -      goto yy237;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych >= '@')
      -          goto yy231;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy240;
      -        if (yych <= 0xE0)
      -          goto yy241;
      -        goto yy242;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy243;
      -        if (yych <= 0xEF)
      -          goto yy242;
      -        goto yy244;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy245;
      -        if (yych <= 0xF4)
      -          goto yy246;
      -        goto yy231;
      -      }
      -    }
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0xE0) {
      -      if (yych <= '>') {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych <= '=')
      -          goto yy237;
      -        goto yy252;
      -      } else {
      -        if (yych <= 0x7F)
      -          goto yy237;
      -        if (yych <= 0xC1)
      -          goto yy231;
      -        if (yych >= 0xE0)
      -          goto yy241;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy243;
      -        goto yy242;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy244;
      -        if (yych <= 0xF3)
      -          goto yy245;
      -        if (yych <= 0xF4)
      -          goto yy246;
      -        goto yy231;
      -      }
      -    }
      -  yy240:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy237;
      -    goto yy231;
      -  yy241:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy240;
      -    goto yy231;
      -  yy242:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy240;
      -    goto yy231;
      -  yy243:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x9F)
      -      goto yy240;
      -    goto yy231;
      -  yy244:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy242;
      -    goto yy231;
      -  yy245:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy242;
      -    goto yy231;
      -  yy246:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x8F)
      -      goto yy242;
      -    goto yy231;
      -  yy247:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 1) {
      -      goto yy247;
      -    }
      -    if (yych <= '>') {
      -      if (yych <= '9') {
      -        if (yych == '/')
      -          goto yy251;
      -        goto yy231;
      -      } else {
      -        if (yych <= ':')
      -          goto yy260;
      -        if (yych <= '=')
      -          goto yy231;
      -        goto yy252;
      -      }
      -    } else {
      -      if (yych <= '^') {
      -        if (yych <= '@')
      -          goto yy231;
      -        if (yych <= 'Z')
      -          goto yy260;
      -        goto yy231;
      -      } else {
      -        if (yych == '`')
      -          goto yy231;
      -        if (yych <= 'z')
      -          goto yy260;
      -        goto yy231;
      -      }
      -    }
      -  yy249:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 1) {
      -      goto yy247;
      -    }
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych == '-')
      -          goto yy249;
      -        goto yy231;
      -      } else {
      -        if (yych <= '/')
      -          goto yy251;
      -        if (yych <= '9')
      -          goto yy249;
      -        goto yy231;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy252;
      -        if (yych <= '@')
      -          goto yy231;
      -        goto yy249;
      -      } else {
      -        if (yych <= '`')
      -          goto yy231;
      -        if (yych <= 'z')
      -          goto yy249;
      -        goto yy231;
      -      }
      -    }
      -  yy251:
      -    yych = *++p;
      -    if (yych != '>')
      -      goto yy231;
      -  yy252:
      -    ++p;
      -    { return (bufsize_t)(p - start); }
      -  yy254:
      -    yych = *++p;
      -    if (yych == '-')
      -      goto yy264;
      -    if (yych == '>')
      -      goto yy231;
      -    goto yy263;
      -  yy255:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 2) {
      -      goto yy255;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych <= '>')
      -          goto yy252;
      -        goto yy231;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy272;
      -        if (yych <= 0xE0)
      -          goto yy273;
      -        goto yy274;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy275;
      -        if (yych <= 0xEF)
      -          goto yy274;
      -        goto yy276;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy277;
      -        if (yych <= 0xF4)
      -          goto yy278;
      -        goto yy231;
      -      }
      -    }
      -  yy257:
      -    yych = *++p;
      -    if (yych == 'D')
      -      goto yy279;
      -    if (yych == 'd')
      -      goto yy279;
      -    goto yy231;
      -  yy258:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x1F) {
      -      if (yych <= 0x08)
      -        goto yy231;
      -      if (yych <= '\r')
      -        goto yy258;
      -      goto yy231;
      -    } else {
      -      if (yych <= ' ')
      -        goto yy258;
      -      if (yych == '>')
      -        goto yy252;
      -      goto yy231;
      -    }
      -  yy260:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 4) {
      -      goto yy260;
      -    }
      -    if (yych <= ',') {
      -      if (yych <= '\r') {
      -        if (yych <= 0x08)
      -          goto yy231;
      -        goto yy280;
      -      } else {
      -        if (yych == ' ')
      -          goto yy280;
      -        goto yy231;
      -      }
      -    } else {
      -      if (yych <= '<') {
      -        if (yych <= '/')
      -          goto yy251;
      -        goto yy231;
      -      } else {
      -        if (yych <= '=')
      -          goto yy282;
      -        if (yych <= '>')
      -          goto yy252;
      -        goto yy231;
      -      }
      -    }
      -  yy262:
      -    ++p;
      -    yych = *p;
      -  yy263:
      -    if (yybm[0 + yych] & 8) {
      -      goto yy262;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych <= '-')
      -          goto yy284;
      -        goto yy231;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy265;
      -        if (yych <= 0xE0)
      -          goto yy266;
      -        goto yy267;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy268;
      -        if (yych <= 0xEF)
      -          goto yy267;
      -        goto yy269;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy270;
      -        if (yych <= 0xF4)
      -          goto yy271;
      -        goto yy231;
      -      }
      -    }
      -  yy264:
      -    yych = *++p;
      -    if (yych == '-')
      -      goto yy251;
      -    if (yych == '>')
      -      goto yy231;
      -    goto yy263;
      -  yy265:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy262;
      -    goto yy231;
      -  yy266:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy265;
      -    goto yy231;
      -  yy267:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy265;
      -    goto yy231;
      -  yy268:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x9F)
      -      goto yy265;
      -    goto yy231;
      -  yy269:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy267;
      -    goto yy231;
      -  yy270:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy267;
      -    goto yy231;
      -  yy271:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x8F)
      -      goto yy267;
      -    goto yy231;
      -  yy272:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy255;
      -    goto yy231;
      -  yy273:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy272;
      -    goto yy231;
      -  yy274:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy272;
      -    goto yy231;
      -  yy275:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x9F)
      -      goto yy272;
      -    goto yy231;
      -  yy276:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy274;
      -    goto yy231;
      -  yy277:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy274;
      -    goto yy231;
      -  yy278:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x8F)
      -      goto yy274;
      -    goto yy231;
      -  yy279:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy285;
      -    if (yych == 'a')
      -      goto yy285;
      -    goto yy231;
      -  yy280:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '<') {
      -      if (yych <= ' ') {
      -        if (yych <= 0x08)
      -          goto yy231;
      -        if (yych <= '\r')
      -          goto yy280;
      -        if (yych <= 0x1F)
      -          goto yy231;
      -        goto yy280;
      -      } else {
      -        if (yych <= '/') {
      -          if (yych <= '.')
      -            goto yy231;
      -          goto yy251;
      -        } else {
      -          if (yych == ':')
      -            goto yy260;
      -          goto yy231;
      -        }
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '=')
      -          goto yy282;
      -        if (yych <= '>')
      -          goto yy252;
      -        if (yych <= '@')
      -          goto yy231;
      -        goto yy260;
      -      } else {
      -        if (yych <= '_') {
      -          if (yych <= '^')
      -            goto yy231;
      -          goto yy260;
      -        } else {
      -          if (yych <= '`')
      -            goto yy231;
      -          if (yych <= 'z')
      -            goto yy260;
      -          goto yy231;
      -        }
      -      }
      -    }
      -  yy282:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 16) {
      -      goto yy286;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '"') {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych <= ' ')
      -          goto yy282;
      -        goto yy288;
      -      } else {
      -        if (yych <= '\'')
      -          goto yy290;
      -        if (yych <= 0xC1)
      -          goto yy231;
      -        if (yych <= 0xDF)
      -          goto yy292;
      -        goto yy293;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy295;
      -        goto yy294;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy296;
      -        if (yych <= 0xF3)
      -          goto yy297;
      -        if (yych <= 0xF4)
      -          goto yy298;
      -        goto yy231;
      -      }
      -    }
      -  yy284:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 8) {
      -      goto yy262;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych <= '-')
      -          goto yy251;
      -        goto yy231;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy265;
      -        if (yych <= 0xE0)
      -          goto yy266;
      -        goto yy267;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy268;
      -        if (yych <= 0xEF)
      -          goto yy267;
      -        goto yy269;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy270;
      -        if (yych <= 0xF4)
      -          goto yy271;
      -        goto yy231;
      -      }
      -    }
      -  yy285:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy299;
      -    if (yych == 't')
      -      goto yy299;
      -    goto yy231;
      -  yy286:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 16) {
      -      goto yy286;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '=') {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych <= ' ')
      -          goto yy247;
      -        goto yy231;
      -      } else {
      -        if (yych <= '>')
      -          goto yy252;
      -        if (yych <= 0xC1)
      -          goto yy231;
      -        if (yych <= 0xDF)
      -          goto yy292;
      -        goto yy293;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy295;
      -        goto yy294;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy296;
      -        if (yych <= 0xF3)
      -          goto yy297;
      -        if (yych <= 0xF4)
      -          goto yy298;
      -        goto yy231;
      -      }
      -    }
      -  yy288:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 32) {
      -      goto yy288;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych <= '"')
      -          goto yy300;
      -        goto yy231;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy301;
      -        if (yych <= 0xE0)
      -          goto yy302;
      -        goto yy303;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy304;
      -        if (yych <= 0xEF)
      -          goto yy303;
      -        goto yy305;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy306;
      -        if (yych <= 0xF4)
      -          goto yy307;
      -        goto yy231;
      -      }
      -    }
      -  yy290:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy290;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych <= '\'')
      -          goto yy300;
      -        goto yy231;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy308;
      -        if (yych <= 0xE0)
      -          goto yy309;
      -        goto yy310;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy311;
      -        if (yych <= 0xEF)
      -          goto yy310;
      -        goto yy312;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy313;
      -        if (yych <= 0xF4)
      -          goto yy314;
      -        goto yy231;
      -      }
      -    }
      -  yy292:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy286;
      -    goto yy231;
      -  yy293:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy292;
      -    goto yy231;
      -  yy294:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy292;
      -    goto yy231;
      -  yy295:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x9F)
      -      goto yy292;
      -    goto yy231;
      -  yy296:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy294;
      -    goto yy231;
      -  yy297:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy294;
      -    goto yy231;
      -  yy298:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x8F)
      -      goto yy294;
      -    goto yy231;
      -  yy299:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy315;
      -    if (yych == 'a')
      -      goto yy315;
      -    goto yy231;
      -  yy300:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 1) {
      -      goto yy247;
      -    }
      -    if (yych == '/')
      -      goto yy251;
      -    if (yych == '>')
      -      goto yy252;
      -    goto yy231;
      -  yy301:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy288;
      -    goto yy231;
      -  yy302:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy301;
      -    goto yy231;
      -  yy303:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy301;
      -    goto yy231;
      -  yy304:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x9F)
      -      goto yy301;
      -    goto yy231;
      -  yy305:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy303;
      -    goto yy231;
      -  yy306:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy303;
      -    goto yy231;
      -  yy307:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x8F)
      -      goto yy303;
      -    goto yy231;
      -  yy308:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy290;
      -    goto yy231;
      -  yy309:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy308;
      -    goto yy231;
      -  yy310:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy308;
      -    goto yy231;
      -  yy311:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x9F)
      -      goto yy308;
      -    goto yy231;
      -  yy312:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy310;
      -    goto yy231;
      -  yy313:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy310;
      -    goto yy231;
      -  yy314:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x8F)
      -      goto yy310;
      -    goto yy231;
      -  yy315:
      -    yych = *++p;
      -    if (yych != '[')
      -      goto yy231;
      -  yy316:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy316;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych >= '^')
      -          goto yy231;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy319;
      -        if (yych <= 0xE0)
      -          goto yy320;
      -        goto yy321;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy322;
      -        if (yych <= 0xEF)
      -          goto yy321;
      -        goto yy323;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy324;
      -        if (yych <= 0xF4)
      -          goto yy325;
      -        goto yy231;
      -      }
      -    }
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy316;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych <= ']')
      -          goto yy326;
      -        goto yy231;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy319;
      -        if (yych <= 0xE0)
      -          goto yy320;
      -        goto yy321;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy322;
      -        if (yych <= 0xEF)
      -          goto yy321;
      -        goto yy323;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy324;
      -        if (yych <= 0xF4)
      -          goto yy325;
      -        goto yy231;
      -      }
      -    }
      -  yy319:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy316;
      -    goto yy231;
      -  yy320:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy319;
      -    goto yy231;
      -  yy321:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy319;
      -    goto yy231;
      -  yy322:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x9F)
      -      goto yy319;
      -    goto yy231;
      -  yy323:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy321;
      -    goto yy231;
      -  yy324:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0xBF)
      -      goto yy321;
      -    goto yy231;
      -  yy325:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy231;
      -    if (yych <= 0x8F)
      -      goto yy321;
      -    goto yy231;
      -  yy326:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0xE0) {
      -      if (yych <= '>') {
      -        if (yych <= 0x00)
      -          goto yy231;
      -        if (yych <= '=')
      -          goto yy316;
      -        goto yy252;
      -      } else {
      -        if (yych <= 0x7F)
      -          goto yy316;
      -        if (yych <= 0xC1)
      -          goto yy231;
      -        if (yych <= 0xDF)
      -          goto yy319;
      -        goto yy320;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy322;
      -        goto yy321;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy323;
      -        if (yych <= 0xF3)
      -          goto yy324;
      -        if (yych <= 0xF4)
      -          goto yy325;
      -        goto yy231;
      -      }
      -    }
      -  }
      +{
      +	unsigned char yych;
      +	static const unsigned char yybm[] = {
      +		/* table 1 .. 8: 0 */
      +		  0, 250, 250, 250, 250, 250, 250, 250, 
      +		250, 235, 235, 235, 235, 235, 250, 250, 
      +		250, 250, 250, 250, 250, 250, 250, 250, 
      +		250, 250, 250, 250, 250, 250, 250, 250, 
      +		235, 250, 202, 250, 250, 250, 250, 170, 
      +		250, 250, 250, 250, 250, 246, 254, 250, 
      +		254, 254, 254, 254, 254, 254, 254, 254, 
      +		254, 254, 254, 250, 234, 234, 232, 250, 
      +		250, 254, 254, 254, 254, 254, 254, 254, 
      +		254, 254, 254, 254, 254, 254, 254, 254, 
      +		254, 254, 254, 254, 254, 254, 254, 254, 
      +		254, 254, 254, 250, 250, 122, 250, 254, 
      +		234, 254, 254, 254, 254, 254, 254, 254, 
      +		254, 254, 254, 254, 254, 254, 254, 254, 
      +		254, 254, 254, 254, 254, 254, 254, 254, 
      +		254, 254, 254, 250, 250, 250, 250, 250, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		/* table 9 .. 11: 256 */
      +		  0, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 192, 128, 128, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 128, 128, 128, 128, 128,   0, 
      +		128, 224, 224, 224, 224, 224, 224, 224, 
      +		224, 224, 224, 224, 224, 224, 224, 224, 
      +		224, 224, 224, 224, 224, 224, 224, 224, 
      +		224, 224, 224, 128, 128, 128, 128, 128, 
      +		128, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 128, 128, 128, 128, 128, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych <= '>') {
      +		if (yych <= '!') {
      +			if (yych >= '!') goto yy226;
      +		} else {
      +			if (yych == '/') goto yy227;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '?') goto yy228;
      +			if (yych >= 'A') goto yy229;
      +		} else {
      +			if (yych <= '`') goto yy224;
      +			if (yych <= 'z') goto yy229;
      +		}
      +	}
      +yy224:
      +	++p;
      +yy225:
      +	{ return 0; }
      +yy226:
      +	yych = *(marker = ++p);
      +	if (yybm[256+yych] & 32) {
      +		goto yy232;
      +	}
      +	if (yych == '-') goto yy230;
      +	if (yych <= '@') goto yy225;
      +	if (yych <= '[') goto yy234;
      +	goto yy225;
      +yy227:
      +	yych = *(marker = ++p);
      +	if (yych <= '@') goto yy225;
      +	if (yych <= 'Z') goto yy235;
      +	if (yych <= '`') goto yy225;
      +	if (yych <= 'z') goto yy235;
      +	goto yy225;
      +yy228:
      +	yych = *(marker = ++p);
      +	if (yych <= 0x00) goto yy225;
      +	if (yych <= 0x7F) goto yy238;
      +	if (yych <= 0xC1) goto yy225;
      +	if (yych <= 0xF4) goto yy238;
      +	goto yy225;
      +yy229:
      +	yych = *(marker = ++p);
      +	if (yych <= '.') {
      +		if (yych <= 0x1F) {
      +			if (yych <= 0x08) goto yy225;
      +			if (yych <= '\r') goto yy250;
      +			goto yy225;
      +		} else {
      +			if (yych <= ' ') goto yy250;
      +			if (yych == '-') goto yy250;
      +			goto yy225;
      +		}
      +	} else {
      +		if (yych <= '@') {
      +			if (yych <= '9') goto yy250;
      +			if (yych == '>') goto yy250;
      +			goto yy225;
      +		} else {
      +			if (yych <= 'Z') goto yy250;
      +			if (yych <= '`') goto yy225;
      +			if (yych <= 'z') goto yy250;
      +			goto yy225;
      +		}
      +	}
      +yy230:
      +	yych = *++p;
      +	if (yych == '-') goto yy254;
      +yy231:
      +	p = marker;
      +	goto yy225;
      +yy232:
      +	yych = *++p;
      +	if (yybm[256+yych] & 32) {
      +		goto yy232;
      +	}
      +	if (yych <= 0x08) goto yy231;
      +	if (yych <= '\r') goto yy255;
      +	if (yych == ' ') goto yy255;
      +	goto yy231;
      +yy234:
      +	yych = *++p;
      +	if (yych == 'C') goto yy257;
      +	if (yych == 'c') goto yy257;
      +	goto yy231;
      +yy235:
      +	yych = *++p;
      +	if (yybm[256+yych] & 64) {
      +		goto yy235;
      +	}
      +	if (yych <= 0x1F) {
      +		if (yych <= 0x08) goto yy231;
      +		if (yych <= '\r') goto yy258;
      +		goto yy231;
      +	} else {
      +		if (yych <= ' ') goto yy258;
      +		if (yych == '>') goto yy252;
      +		goto yy231;
      +	}
      +yy237:
      +	yych = *++p;
      +yy238:
      +	if (yybm[256+yych] & 128) {
      +		goto yy237;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych >= '@') goto yy231;
      +		} else {
      +			if (yych <= 0xDF) goto yy240;
      +			if (yych <= 0xE0) goto yy241;
      +			goto yy242;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy243;
      +			if (yych <= 0xEF) goto yy242;
      +			goto yy244;
      +		} else {
      +			if (yych <= 0xF3) goto yy245;
      +			if (yych <= 0xF4) goto yy246;
      +			goto yy231;
      +		}
      +	}
      +	yych = *++p;
      +	if (yych <= 0xE0) {
      +		if (yych <= '>') {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych <= '=') goto yy237;
      +			goto yy252;
      +		} else {
      +			if (yych <= 0x7F) goto yy237;
      +			if (yych <= 0xC1) goto yy231;
      +			if (yych >= 0xE0) goto yy241;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy243;
      +			goto yy242;
      +		} else {
      +			if (yych <= 0xF0) goto yy244;
      +			if (yych <= 0xF3) goto yy245;
      +			if (yych <= 0xF4) goto yy246;
      +			goto yy231;
      +		}
      +	}
      +yy240:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy237;
      +	goto yy231;
      +yy241:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy231;
      +	if (yych <= 0xBF) goto yy240;
      +	goto yy231;
      +yy242:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy240;
      +	goto yy231;
      +yy243:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x9F) goto yy240;
      +	goto yy231;
      +yy244:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy231;
      +	if (yych <= 0xBF) goto yy242;
      +	goto yy231;
      +yy245:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy242;
      +	goto yy231;
      +yy246:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x8F) goto yy242;
      +	goto yy231;
      +yy247:
      +	yych = *++p;
      +	if (yybm[0+yych] & 1) {
      +		goto yy247;
      +	}
      +	if (yych <= '>') {
      +		if (yych <= '9') {
      +			if (yych == '/') goto yy251;
      +			goto yy231;
      +		} else {
      +			if (yych <= ':') goto yy260;
      +			if (yych <= '=') goto yy231;
      +			goto yy252;
      +		}
      +	} else {
      +		if (yych <= '^') {
      +			if (yych <= '@') goto yy231;
      +			if (yych <= 'Z') goto yy260;
      +			goto yy231;
      +		} else {
      +			if (yych == '`') goto yy231;
      +			if (yych <= 'z') goto yy260;
      +			goto yy231;
      +		}
      +	}
      +yy249:
      +	yych = *++p;
      +yy250:
      +	if (yybm[0+yych] & 1) {
      +		goto yy247;
      +	}
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych == '-') goto yy249;
      +			goto yy231;
      +		} else {
      +			if (yych <= '/') goto yy251;
      +			if (yych <= '9') goto yy249;
      +			goto yy231;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy252;
      +			if (yych <= '@') goto yy231;
      +			goto yy249;
      +		} else {
      +			if (yych <= '`') goto yy231;
      +			if (yych <= 'z') goto yy249;
      +			goto yy231;
      +		}
      +	}
      +yy251:
      +	yych = *++p;
      +	if (yych != '>') goto yy231;
      +yy252:
      +	++p;
      +	{ return (bufsize_t)(p - start); }
      +yy254:
      +	yych = *++p;
      +	if (yych == '-') goto yy264;
      +	if (yych == '>') goto yy231;
      +	goto yy263;
      +yy255:
      +	yych = *++p;
      +	if (yybm[0+yych] & 2) {
      +		goto yy255;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych <= '>') goto yy252;
      +			goto yy231;
      +		} else {
      +			if (yych <= 0xDF) goto yy272;
      +			if (yych <= 0xE0) goto yy273;
      +			goto yy274;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy275;
      +			if (yych <= 0xEF) goto yy274;
      +			goto yy276;
      +		} else {
      +			if (yych <= 0xF3) goto yy277;
      +			if (yych <= 0xF4) goto yy278;
      +			goto yy231;
      +		}
      +	}
      +yy257:
      +	yych = *++p;
      +	if (yych == 'D') goto yy279;
      +	if (yych == 'd') goto yy279;
      +	goto yy231;
      +yy258:
      +	yych = *++p;
      +	if (yych <= 0x1F) {
      +		if (yych <= 0x08) goto yy231;
      +		if (yych <= '\r') goto yy258;
      +		goto yy231;
      +	} else {
      +		if (yych <= ' ') goto yy258;
      +		if (yych == '>') goto yy252;
      +		goto yy231;
      +	}
      +yy260:
      +	yych = *++p;
      +	if (yybm[0+yych] & 4) {
      +		goto yy260;
      +	}
      +	if (yych <= ',') {
      +		if (yych <= '\r') {
      +			if (yych <= 0x08) goto yy231;
      +			goto yy280;
      +		} else {
      +			if (yych == ' ') goto yy280;
      +			goto yy231;
      +		}
      +	} else {
      +		if (yych <= '<') {
      +			if (yych <= '/') goto yy251;
      +			goto yy231;
      +		} else {
      +			if (yych <= '=') goto yy282;
      +			if (yych <= '>') goto yy252;
      +			goto yy231;
      +		}
      +	}
      +yy262:
      +	yych = *++p;
      +yy263:
      +	if (yybm[0+yych] & 8) {
      +		goto yy262;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych <= '-') goto yy284;
      +			goto yy231;
      +		} else {
      +			if (yych <= 0xDF) goto yy265;
      +			if (yych <= 0xE0) goto yy266;
      +			goto yy267;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy268;
      +			if (yych <= 0xEF) goto yy267;
      +			goto yy269;
      +		} else {
      +			if (yych <= 0xF3) goto yy270;
      +			if (yych <= 0xF4) goto yy271;
      +			goto yy231;
      +		}
      +	}
      +yy264:
      +	yych = *++p;
      +	if (yych == '-') goto yy251;
      +	if (yych == '>') goto yy231;
      +	goto yy263;
      +yy265:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy262;
      +	goto yy231;
      +yy266:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy231;
      +	if (yych <= 0xBF) goto yy265;
      +	goto yy231;
      +yy267:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy265;
      +	goto yy231;
      +yy268:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x9F) goto yy265;
      +	goto yy231;
      +yy269:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy231;
      +	if (yych <= 0xBF) goto yy267;
      +	goto yy231;
      +yy270:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy267;
      +	goto yy231;
      +yy271:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x8F) goto yy267;
      +	goto yy231;
      +yy272:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy255;
      +	goto yy231;
      +yy273:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy231;
      +	if (yych <= 0xBF) goto yy272;
      +	goto yy231;
      +yy274:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy272;
      +	goto yy231;
      +yy275:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x9F) goto yy272;
      +	goto yy231;
      +yy276:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy231;
      +	if (yych <= 0xBF) goto yy274;
      +	goto yy231;
      +yy277:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy274;
      +	goto yy231;
      +yy278:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x8F) goto yy274;
      +	goto yy231;
      +yy279:
      +	yych = *++p;
      +	if (yych == 'A') goto yy285;
      +	if (yych == 'a') goto yy285;
      +	goto yy231;
      +yy280:
      +	yych = *++p;
      +	if (yych <= '<') {
      +		if (yych <= ' ') {
      +			if (yych <= 0x08) goto yy231;
      +			if (yych <= '\r') goto yy280;
      +			if (yych <= 0x1F) goto yy231;
      +			goto yy280;
      +		} else {
      +			if (yych <= '/') {
      +				if (yych <= '.') goto yy231;
      +				goto yy251;
      +			} else {
      +				if (yych == ':') goto yy260;
      +				goto yy231;
      +			}
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '=') goto yy282;
      +			if (yych <= '>') goto yy252;
      +			if (yych <= '@') goto yy231;
      +			goto yy260;
      +		} else {
      +			if (yych <= '_') {
      +				if (yych <= '^') goto yy231;
      +				goto yy260;
      +			} else {
      +				if (yych <= '`') goto yy231;
      +				if (yych <= 'z') goto yy260;
      +				goto yy231;
      +			}
      +		}
      +	}
      +yy282:
      +	yych = *++p;
      +	if (yybm[0+yych] & 16) {
      +		goto yy286;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '"') {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych <= ' ') goto yy282;
      +			goto yy288;
      +		} else {
      +			if (yych <= '\'') goto yy290;
      +			if (yych <= 0xC1) goto yy231;
      +			if (yych <= 0xDF) goto yy292;
      +			goto yy293;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy295;
      +			goto yy294;
      +		} else {
      +			if (yych <= 0xF0) goto yy296;
      +			if (yych <= 0xF3) goto yy297;
      +			if (yych <= 0xF4) goto yy298;
      +			goto yy231;
      +		}
      +	}
      +yy284:
      +	yych = *++p;
      +	if (yybm[0+yych] & 8) {
      +		goto yy262;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych <= '-') goto yy251;
      +			goto yy231;
      +		} else {
      +			if (yych <= 0xDF) goto yy265;
      +			if (yych <= 0xE0) goto yy266;
      +			goto yy267;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy268;
      +			if (yych <= 0xEF) goto yy267;
      +			goto yy269;
      +		} else {
      +			if (yych <= 0xF3) goto yy270;
      +			if (yych <= 0xF4) goto yy271;
      +			goto yy231;
      +		}
      +	}
      +yy285:
      +	yych = *++p;
      +	if (yych == 'T') goto yy299;
      +	if (yych == 't') goto yy299;
      +	goto yy231;
      +yy286:
      +	yych = *++p;
      +	if (yybm[0+yych] & 16) {
      +		goto yy286;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '=') {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych <= ' ') goto yy247;
      +			goto yy231;
      +		} else {
      +			if (yych <= '>') goto yy252;
      +			if (yych <= 0xC1) goto yy231;
      +			if (yych <= 0xDF) goto yy292;
      +			goto yy293;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy295;
      +			goto yy294;
      +		} else {
      +			if (yych <= 0xF0) goto yy296;
      +			if (yych <= 0xF3) goto yy297;
      +			if (yych <= 0xF4) goto yy298;
      +			goto yy231;
      +		}
      +	}
      +yy288:
      +	yych = *++p;
      +	if (yybm[0+yych] & 32) {
      +		goto yy288;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych <= '"') goto yy300;
      +			goto yy231;
      +		} else {
      +			if (yych <= 0xDF) goto yy301;
      +			if (yych <= 0xE0) goto yy302;
      +			goto yy303;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy304;
      +			if (yych <= 0xEF) goto yy303;
      +			goto yy305;
      +		} else {
      +			if (yych <= 0xF3) goto yy306;
      +			if (yych <= 0xF4) goto yy307;
      +			goto yy231;
      +		}
      +	}
      +yy290:
      +	yych = *++p;
      +	if (yybm[0+yych] & 64) {
      +		goto yy290;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych <= '\'') goto yy300;
      +			goto yy231;
      +		} else {
      +			if (yych <= 0xDF) goto yy308;
      +			if (yych <= 0xE0) goto yy309;
      +			goto yy310;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy311;
      +			if (yych <= 0xEF) goto yy310;
      +			goto yy312;
      +		} else {
      +			if (yych <= 0xF3) goto yy313;
      +			if (yych <= 0xF4) goto yy314;
      +			goto yy231;
      +		}
      +	}
      +yy292:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy286;
      +	goto yy231;
      +yy293:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy231;
      +	if (yych <= 0xBF) goto yy292;
      +	goto yy231;
      +yy294:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy292;
      +	goto yy231;
      +yy295:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x9F) goto yy292;
      +	goto yy231;
      +yy296:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy231;
      +	if (yych <= 0xBF) goto yy294;
      +	goto yy231;
      +yy297:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy294;
      +	goto yy231;
      +yy298:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x8F) goto yy294;
      +	goto yy231;
      +yy299:
      +	yych = *++p;
      +	if (yych == 'A') goto yy315;
      +	if (yych == 'a') goto yy315;
      +	goto yy231;
      +yy300:
      +	yych = *++p;
      +	if (yybm[0+yych] & 1) {
      +		goto yy247;
      +	}
      +	if (yych == '/') goto yy251;
      +	if (yych == '>') goto yy252;
      +	goto yy231;
      +yy301:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy288;
      +	goto yy231;
      +yy302:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy231;
      +	if (yych <= 0xBF) goto yy301;
      +	goto yy231;
      +yy303:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy301;
      +	goto yy231;
      +yy304:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x9F) goto yy301;
      +	goto yy231;
      +yy305:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy231;
      +	if (yych <= 0xBF) goto yy303;
      +	goto yy231;
      +yy306:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy303;
      +	goto yy231;
      +yy307:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x8F) goto yy303;
      +	goto yy231;
      +yy308:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy290;
      +	goto yy231;
      +yy309:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy231;
      +	if (yych <= 0xBF) goto yy308;
      +	goto yy231;
      +yy310:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy308;
      +	goto yy231;
      +yy311:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x9F) goto yy308;
      +	goto yy231;
      +yy312:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy231;
      +	if (yych <= 0xBF) goto yy310;
      +	goto yy231;
      +yy313:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy310;
      +	goto yy231;
      +yy314:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x8F) goto yy310;
      +	goto yy231;
      +yy315:
      +	yych = *++p;
      +	if (yych != '[') goto yy231;
      +yy316:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy316;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych >= '^') goto yy231;
      +		} else {
      +			if (yych <= 0xDF) goto yy319;
      +			if (yych <= 0xE0) goto yy320;
      +			goto yy321;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy322;
      +			if (yych <= 0xEF) goto yy321;
      +			goto yy323;
      +		} else {
      +			if (yych <= 0xF3) goto yy324;
      +			if (yych <= 0xF4) goto yy325;
      +			goto yy231;
      +		}
      +	}
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy316;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych <= ']') goto yy326;
      +			goto yy231;
      +		} else {
      +			if (yych <= 0xDF) goto yy319;
      +			if (yych <= 0xE0) goto yy320;
      +			goto yy321;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy322;
      +			if (yych <= 0xEF) goto yy321;
      +			goto yy323;
      +		} else {
      +			if (yych <= 0xF3) goto yy324;
      +			if (yych <= 0xF4) goto yy325;
      +			goto yy231;
      +		}
      +	}
      +yy319:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy316;
      +	goto yy231;
      +yy320:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy231;
      +	if (yych <= 0xBF) goto yy319;
      +	goto yy231;
      +yy321:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy319;
      +	goto yy231;
      +yy322:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x9F) goto yy319;
      +	goto yy231;
      +yy323:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy231;
      +	if (yych <= 0xBF) goto yy321;
      +	goto yy231;
      +yy324:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0xBF) goto yy321;
      +	goto yy231;
      +yy325:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy231;
      +	if (yych <= 0x8F) goto yy321;
      +	goto yy231;
      +yy326:
      +	yych = *++p;
      +	if (yych <= 0xE0) {
      +		if (yych <= '>') {
      +			if (yych <= 0x00) goto yy231;
      +			if (yych <= '=') goto yy316;
      +			goto yy252;
      +		} else {
      +			if (yych <= 0x7F) goto yy316;
      +			if (yych <= 0xC1) goto yy231;
      +			if (yych <= 0xDF) goto yy319;
      +			goto yy320;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy322;
      +			goto yy321;
      +		} else {
      +			if (yych <= 0xF0) goto yy323;
      +			if (yych <= 0xF3) goto yy324;
      +			if (yych <= 0xF4) goto yy325;
      +			goto yy231;
      +		}
      +	}
      +}
      +
      +}
      +
      +// Try to (liberally) match an HTML tag after first <, returning num of chars matched.
      +bufsize_t _scan_liberal_html_tag(const unsigned char *p)
      +{
      +  const unsigned char *marker = NULL;
      +  const unsigned char *start = p;
      +
      +{
      +	unsigned char yych;
      +	unsigned int yyaccept = 0;
      +	static const unsigned char yybm[] = {
      +		  0,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,   0,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64, 128,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych <= 0xE0) {
      +		if (yych <= '\n') {
      +			if (yych <= 0x00) goto yy329;
      +			if (yych <= '\t') goto yy331;
      +		} else {
      +			if (yych <= 0x7F) goto yy331;
      +			if (yych <= 0xC1) goto yy329;
      +			if (yych <= 0xDF) goto yy332;
      +			goto yy333;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy335;
      +			goto yy334;
      +		} else {
      +			if (yych <= 0xF0) goto yy336;
      +			if (yych <= 0xF3) goto yy337;
      +			if (yych <= 0xF4) goto yy338;
      +		}
      +	}
      +yy329:
      +	++p;
      +yy330:
      +	{ return 0; }
      +yy331:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= '\n') {
      +		if (yych <= 0x00) goto yy330;
      +		if (yych <= '\t') goto yy340;
      +		goto yy330;
      +	} else {
      +		if (yych <= 0x7F) goto yy340;
      +		if (yych <= 0xC1) goto yy330;
      +		if (yych <= 0xF4) goto yy340;
      +		goto yy330;
      +	}
      +yy332:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy330;
      +	if (yych <= 0xBF) goto yy339;
      +	goto yy330;
      +yy333:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x9F) goto yy330;
      +	if (yych <= 0xBF) goto yy345;
      +	goto yy330;
      +yy334:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy330;
      +	if (yych <= 0xBF) goto yy345;
      +	goto yy330;
      +yy335:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy330;
      +	if (yych <= 0x9F) goto yy345;
      +	goto yy330;
      +yy336:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x8F) goto yy330;
      +	if (yych <= 0xBF) goto yy347;
      +	goto yy330;
      +yy337:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy330;
      +	if (yych <= 0xBF) goto yy347;
      +	goto yy330;
      +yy338:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy330;
      +	if (yych <= 0x8F) goto yy347;
      +	goto yy330;
      +yy339:
      +	yych = *++p;
      +yy340:
      +	if (yybm[0+yych] & 64) {
      +		goto yy339;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy341;
      +			if (yych <= '>') goto yy342;
      +		} else {
      +			if (yych <= 0xDF) goto yy345;
      +			if (yych <= 0xE0) goto yy346;
      +			goto yy347;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy348;
      +			if (yych <= 0xEF) goto yy347;
      +			goto yy349;
      +		} else {
      +			if (yych <= 0xF3) goto yy350;
      +			if (yych <= 0xF4) goto yy351;
      +		}
      +	}
      +yy341:
      +	p = marker;
      +	if (yyaccept == 0) {
      +		goto yy330;
      +	} else {
      +		goto yy344;
      +	}
      +yy342:
      +	yyaccept = 1;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 64) {
      +		goto yy339;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy344;
      +			if (yych <= '>') goto yy342;
      +		} else {
      +			if (yych <= 0xDF) goto yy345;
      +			if (yych <= 0xE0) goto yy346;
      +			goto yy347;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy348;
      +			if (yych <= 0xEF) goto yy347;
      +			goto yy349;
      +		} else {
      +			if (yych <= 0xF3) goto yy350;
      +			if (yych <= 0xF4) goto yy351;
      +		}
      +	}
      +yy344:
      +	{ return (bufsize_t)(p - start); }
      +yy345:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy341;
      +	if (yych <= 0xBF) goto yy339;
      +	goto yy341;
      +yy346:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy341;
      +	if (yych <= 0xBF) goto yy345;
      +	goto yy341;
      +yy347:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy341;
      +	if (yych <= 0xBF) goto yy345;
      +	goto yy341;
      +yy348:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy341;
      +	if (yych <= 0x9F) goto yy345;
      +	goto yy341;
      +yy349:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy341;
      +	if (yych <= 0xBF) goto yy347;
      +	goto yy341;
      +yy350:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy341;
      +	if (yych <= 0xBF) goto yy347;
      +	goto yy341;
      +yy351:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy341;
      +	if (yych <= 0x8F) goto yy347;
      +	goto yy341;
      +}
      +
       }
       
       // Try to match an HTML block tag start line, returning
       // an integer code for the type of block (1-6, matching the spec).
       // #7 is handled by a separate function, below.
      -bufsize_t _scan_html_block_start(const unsigned char *p) {
      +bufsize_t _scan_html_block_start(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
       
      -  {
      -    unsigned char yych;
      -    yych = *p;
      -    if (yych == '<')
      -      goto yy331;
      -    ++p;
      -  yy330 : { return 0; }
      -  yy331:
      -    yych = *(marker = ++p);
      -    switch (yych) {
      -    case '!':
      -      goto yy332;
      -    case '/':
      -      goto yy334;
      -    case '?':
      -      goto yy335;
      -    case 'A':
      -    case 'a':
      -      goto yy337;
      -    case 'B':
      -    case 'b':
      -      goto yy338;
      -    case 'C':
      -    case 'c':
      -      goto yy339;
      -    case 'D':
      -    case 'd':
      -      goto yy340;
      -    case 'F':
      -    case 'f':
      -      goto yy341;
      -    case 'H':
      -    case 'h':
      -      goto yy342;
      -    case 'I':
      -    case 'i':
      -      goto yy343;
      -    case 'L':
      -    case 'l':
      -      goto yy344;
      -    case 'M':
      -    case 'm':
      -      goto yy345;
      -    case 'N':
      -    case 'n':
      -      goto yy346;
      -    case 'O':
      -    case 'o':
      -      goto yy347;
      -    case 'P':
      -    case 'p':
      -      goto yy348;
      -    case 'S':
      -    case 's':
      -      goto yy349;
      -    case 'T':
      -    case 't':
      -      goto yy350;
      -    case 'U':
      -    case 'u':
      -      goto yy351;
      -    default:
      -      goto yy330;
      -    }
      -  yy332:
      -    yych = *++p;
      -    if (yych <= '@') {
      -      if (yych == '-')
      -        goto yy352;
      -    } else {
      -      if (yych <= 'Z')
      -        goto yy353;
      -      if (yych <= '[')
      -        goto yy355;
      -    }
      -  yy333:
      -    p = marker;
      -    goto yy330;
      -  yy334:
      -    yych = *++p;
      -    switch (yych) {
      -    case 'A':
      -    case 'a':
      -      goto yy337;
      -    case 'B':
      -    case 'b':
      -      goto yy338;
      -    case 'C':
      -    case 'c':
      -      goto yy339;
      -    case 'D':
      -    case 'd':
      -      goto yy340;
      -    case 'F':
      -    case 'f':
      -      goto yy341;
      -    case 'H':
      -    case 'h':
      -      goto yy342;
      -    case 'I':
      -    case 'i':
      -      goto yy343;
      -    case 'L':
      -    case 'l':
      -      goto yy344;
      -    case 'M':
      -    case 'm':
      -      goto yy345;
      -    case 'N':
      -    case 'n':
      -      goto yy346;
      -    case 'O':
      -    case 'o':
      -      goto yy347;
      -    case 'P':
      -    case 'p':
      -      goto yy356;
      -    case 'S':
      -    case 's':
      -      goto yy357;
      -    case 'T':
      -    case 't':
      -      goto yy350;
      -    case 'U':
      -    case 'u':
      -      goto yy351;
      -    default:
      -      goto yy333;
      -    }
      -  yy335:
      -    ++p;
      -    { return 3; }
      -  yy337:
      -    yych = *++p;
      -    if (yych <= 'S') {
      -      if (yych <= 'D') {
      -        if (yych <= 'C')
      -          goto yy333;
      -        goto yy358;
      -      } else {
      -        if (yych <= 'Q')
      -          goto yy333;
      -        if (yych <= 'R')
      -          goto yy359;
      -        goto yy360;
      -      }
      -    } else {
      -      if (yych <= 'q') {
      -        if (yych == 'd')
      -          goto yy358;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'r')
      -          goto yy359;
      -        if (yych <= 's')
      -          goto yy360;
      -        goto yy333;
      -      }
      -    }
      -  yy338:
      -    yych = *++p;
      -    if (yych <= 'O') {
      -      if (yych <= 'K') {
      -        if (yych == 'A')
      -          goto yy361;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'L')
      -          goto yy362;
      -        if (yych <= 'N')
      -          goto yy333;
      -        goto yy363;
      -      }
      -    } else {
      -      if (yych <= 'k') {
      -        if (yych == 'a')
      -          goto yy361;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'l')
      -          goto yy362;
      -        if (yych == 'o')
      -          goto yy363;
      -        goto yy333;
      -      }
      -    }
      -  yy339:
      -    yych = *++p;
      -    if (yych <= 'O') {
      -      if (yych <= 'D') {
      -        if (yych == 'A')
      -          goto yy364;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'E')
      -          goto yy365;
      -        if (yych <= 'N')
      -          goto yy333;
      -        goto yy366;
      -      }
      -    } else {
      -      if (yych <= 'd') {
      -        if (yych == 'a')
      -          goto yy364;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'e')
      -          goto yy365;
      -        if (yych == 'o')
      -          goto yy366;
      -        goto yy333;
      -      }
      -    }
      -  yy340:
      -    yych = *++p;
      -    switch (yych) {
      -    case 'D':
      -    case 'L':
      -    case 'T':
      -    case 'd':
      -    case 'l':
      -    case 't':
      -      goto yy367;
      -    case 'E':
      -    case 'e':
      -      goto yy368;
      -    case 'I':
      -    case 'i':
      -      goto yy369;
      -    default:
      -      goto yy333;
      -    }
      -  yy341:
      -    yych = *++p;
      -    if (yych <= 'R') {
      -      if (yych <= 'N') {
      -        if (yych == 'I')
      -          goto yy370;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'O')
      -          goto yy371;
      -        if (yych <= 'Q')
      -          goto yy333;
      -        goto yy372;
      -      }
      -    } else {
      -      if (yych <= 'n') {
      -        if (yych == 'i')
      -          goto yy370;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'o')
      -          goto yy371;
      -        if (yych == 'r')
      -          goto yy372;
      -        goto yy333;
      -      }
      -    }
      -  yy342:
      -    yych = *++p;
      -    if (yych <= 'S') {
      -      if (yych <= 'D') {
      -        if (yych <= '0')
      -          goto yy333;
      -        if (yych <= '6')
      -          goto yy367;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'E')
      -          goto yy373;
      -        if (yych == 'R')
      -          goto yy367;
      -        goto yy333;
      -      }
      -    } else {
      -      if (yych <= 'q') {
      -        if (yych <= 'T')
      -          goto yy374;
      -        if (yych == 'e')
      -          goto yy373;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'r')
      -          goto yy367;
      -        if (yych == 't')
      -          goto yy374;
      -        goto yy333;
      -      }
      -    }
      -  yy343:
      -    yych = *++p;
      -    if (yych == 'F')
      -      goto yy375;
      -    if (yych == 'f')
      -      goto yy375;
      -    goto yy333;
      -  yy344:
      -    yych = *++p;
      -    if (yych <= 'I') {
      -      if (yych == 'E')
      -        goto yy376;
      -      if (yych <= 'H')
      -        goto yy333;
      -      goto yy377;
      -    } else {
      -      if (yych <= 'e') {
      -        if (yych <= 'd')
      -          goto yy333;
      -        goto yy376;
      -      } else {
      -        if (yych == 'i')
      -          goto yy377;
      -        goto yy333;
      -      }
      -    }
      -  yy345:
      -    yych = *++p;
      -    if (yych <= 'E') {
      -      if (yych == 'A')
      -        goto yy378;
      -      if (yych <= 'D')
      -        goto yy333;
      -      goto yy379;
      -    } else {
      -      if (yych <= 'a') {
      -        if (yych <= '`')
      -          goto yy333;
      -        goto yy378;
      -      } else {
      -        if (yych == 'e')
      -          goto yy379;
      -        goto yy333;
      -      }
      -    }
      -  yy346:
      -    yych = *++p;
      -    if (yych <= 'O') {
      -      if (yych == 'A')
      -        goto yy380;
      -      if (yych <= 'N')
      -        goto yy333;
      -      goto yy381;
      -    } else {
      -      if (yych <= 'a') {
      -        if (yych <= '`')
      -          goto yy333;
      -        goto yy380;
      -      } else {
      -        if (yych == 'o')
      -          goto yy381;
      -        goto yy333;
      -      }
      -    }
      -  yy347:
      -    yych = *++p;
      -    if (yych <= 'P') {
      -      if (yych == 'L')
      -        goto yy367;
      -      if (yych <= 'O')
      -        goto yy333;
      -      goto yy382;
      -    } else {
      -      if (yych <= 'l') {
      -        if (yych <= 'k')
      -          goto yy333;
      -        goto yy367;
      -      } else {
      -        if (yych == 'p')
      -          goto yy382;
      -        goto yy333;
      -      }
      -    }
      -  yy348:
      -    yych = *++p;
      -    if (yych <= '>') {
      -      if (yych <= ' ') {
      -        if (yych <= 0x08)
      -          goto yy333;
      -        if (yych <= '\r')
      -          goto yy383;
      -        if (yych <= 0x1F)
      -          goto yy333;
      -        goto yy383;
      -      } else {
      -        if (yych == '/')
      -          goto yy385;
      -        if (yych <= '=')
      -          goto yy333;
      -        goto yy383;
      -      }
      -    } else {
      -      if (yych <= 'R') {
      -        if (yych == 'A')
      -          goto yy386;
      -        if (yych <= 'Q')
      -          goto yy333;
      -        goto yy387;
      -      } else {
      -        if (yych <= 'a') {
      -          if (yych <= '`')
      -            goto yy333;
      -          goto yy386;
      -        } else {
      -          if (yych == 'r')
      -            goto yy387;
      -          goto yy333;
      -        }
      -      }
      -    }
      -  yy349:
      -    yych = *++p;
      -    switch (yych) {
      -    case 'C':
      -    case 'c':
      -      goto yy388;
      -    case 'E':
      -    case 'e':
      -      goto yy389;
      -    case 'O':
      -    case 'o':
      -      goto yy390;
      -    case 'T':
      -    case 't':
      -      goto yy391;
      -    case 'U':
      -    case 'u':
      -      goto yy392;
      -    default:
      -      goto yy333;
      -    }
      -  yy350:
      -    yych = *++p;
      -    switch (yych) {
      -    case 'A':
      -    case 'a':
      -      goto yy393;
      -    case 'B':
      -    case 'b':
      -      goto yy394;
      -    case 'D':
      -    case 'd':
      -      goto yy367;
      -    case 'F':
      -    case 'f':
      -      goto yy395;
      -    case 'H':
      -    case 'h':
      -      goto yy396;
      -    case 'I':
      -    case 'i':
      -      goto yy397;
      -    case 'R':
      -    case 'r':
      -      goto yy398;
      -    default:
      -      goto yy333;
      -    }
      -  yy351:
      -    yych = *++p;
      -    if (yych == 'L')
      -      goto yy367;
      -    if (yych == 'l')
      -      goto yy367;
      -    goto yy333;
      -  yy352:
      -    yych = *++p;
      -    if (yych == '-')
      -      goto yy399;
      -    goto yy333;
      -  yy353:
      -    ++p;
      -    { return 4; }
      -  yy355:
      -    yych = *++p;
      -    if (yych == 'C')
      -      goto yy401;
      -    if (yych == 'c')
      -      goto yy401;
      -    goto yy333;
      -  yy356:
      -    yych = *++p;
      -    if (yych <= '/') {
      -      if (yych <= 0x1F) {
      -        if (yych <= 0x08)
      -          goto yy333;
      -        if (yych <= '\r')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= ' ')
      -          goto yy383;
      -        if (yych <= '.')
      -          goto yy333;
      -        goto yy385;
      -      }
      -    } else {
      -      if (yych <= '@') {
      -        if (yych == '>')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'A')
      -          goto yy386;
      -        if (yych == 'a')
      -          goto yy386;
      -        goto yy333;
      -      }
      -    }
      -  yy357:
      -    yych = *++p;
      -    if (yych <= 'U') {
      -      if (yych <= 'N') {
      -        if (yych == 'E')
      -          goto yy389;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'O')
      -          goto yy390;
      -        if (yych <= 'T')
      -          goto yy333;
      -        goto yy392;
      -      }
      -    } else {
      -      if (yych <= 'n') {
      -        if (yych == 'e')
      -          goto yy389;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'o')
      -          goto yy390;
      -        if (yych == 'u')
      -          goto yy392;
      -        goto yy333;
      -      }
      -    }
      -  yy358:
      -    yych = *++p;
      -    if (yych == 'D')
      -      goto yy402;
      -    if (yych == 'd')
      -      goto yy402;
      -    goto yy333;
      -  yy359:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy403;
      -    if (yych == 't')
      -      goto yy403;
      -    goto yy333;
      -  yy360:
      -    yych = *++p;
      -    if (yych == 'I')
      -      goto yy404;
      -    if (yych == 'i')
      -      goto yy404;
      -    goto yy333;
      -  yy361:
      -    yych = *++p;
      -    if (yych == 'S')
      -      goto yy405;
      -    if (yych == 's')
      -      goto yy405;
      -    goto yy333;
      -  yy362:
      -    yych = *++p;
      -    if (yych == 'O')
      -      goto yy406;
      -    if (yych == 'o')
      -      goto yy406;
      -    goto yy333;
      -  yy363:
      -    yych = *++p;
      -    if (yych == 'D')
      -      goto yy407;
      -    if (yych == 'd')
      -      goto yy407;
      -    goto yy333;
      -  yy364:
      -    yych = *++p;
      -    if (yych == 'P')
      -      goto yy408;
      -    if (yych == 'p')
      -      goto yy408;
      -    goto yy333;
      -  yy365:
      -    yych = *++p;
      -    if (yych == 'N')
      -      goto yy409;
      -    if (yych == 'n')
      -      goto yy409;
      -    goto yy333;
      -  yy366:
      -    yych = *++p;
      -    if (yych == 'L')
      -      goto yy410;
      -    if (yych == 'l')
      -      goto yy410;
      -    goto yy333;
      -  yy367:
      -    yych = *++p;
      -    if (yych <= ' ') {
      -      if (yych <= 0x08)
      -        goto yy333;
      -      if (yych <= '\r')
      -        goto yy383;
      -      if (yych <= 0x1F)
      -        goto yy333;
      -      goto yy383;
      -    } else {
      -      if (yych <= '/') {
      -        if (yych <= '.')
      -          goto yy333;
      -        goto yy385;
      -      } else {
      -        if (yych == '>')
      -          goto yy383;
      -        goto yy333;
      -      }
      -    }
      -  yy368:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy411;
      -    if (yych == 't')
      -      goto yy411;
      -    goto yy333;
      -  yy369:
      -    yych = *++p;
      -    if (yych <= 'V') {
      -      if (yych <= 'Q') {
      -        if (yych == 'A')
      -          goto yy412;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'R')
      -          goto yy367;
      -        if (yych <= 'U')
      -          goto yy333;
      -        goto yy367;
      -      }
      -    } else {
      -      if (yych <= 'q') {
      -        if (yych == 'a')
      -          goto yy412;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'r')
      -          goto yy367;
      -        if (yych == 'v')
      -          goto yy367;
      -        goto yy333;
      -      }
      -    }
      -  yy370:
      -    yych = *++p;
      -    if (yych <= 'G') {
      -      if (yych == 'E')
      -        goto yy413;
      -      if (yych <= 'F')
      -        goto yy333;
      -      goto yy414;
      -    } else {
      -      if (yych <= 'e') {
      -        if (yych <= 'd')
      -          goto yy333;
      -        goto yy413;
      -      } else {
      -        if (yych == 'g')
      -          goto yy414;
      -        goto yy333;
      -      }
      -    }
      -  yy371:
      -    yych = *++p;
      -    if (yych <= 'R') {
      -      if (yych == 'O')
      -        goto yy409;
      -      if (yych <= 'Q')
      -        goto yy333;
      -      goto yy415;
      -    } else {
      -      if (yych <= 'o') {
      -        if (yych <= 'n')
      -          goto yy333;
      -        goto yy409;
      -      } else {
      -        if (yych == 'r')
      -          goto yy415;
      -        goto yy333;
      -      }
      -    }
      -  yy372:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy416;
      -    if (yych == 'a')
      -      goto yy416;
      -    goto yy333;
      -  yy373:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy417;
      -    if (yych == 'a')
      -      goto yy417;
      -    goto yy333;
      -  yy374:
      -    yych = *++p;
      -    if (yych == 'M')
      -      goto yy351;
      -    if (yych == 'm')
      -      goto yy351;
      -    goto yy333;
      -  yy375:
      -    yych = *++p;
      -    if (yych == 'R')
      -      goto yy418;
      -    if (yych == 'r')
      -      goto yy418;
      -    goto yy333;
      -  yy376:
      -    yych = *++p;
      -    if (yych == 'G')
      -      goto yy419;
      -    if (yych == 'g')
      -      goto yy419;
      -    goto yy333;
      -  yy377:
      -    yych = *++p;
      -    if (yych <= '/') {
      -      if (yych <= 0x1F) {
      -        if (yych <= 0x08)
      -          goto yy333;
      -        if (yych <= '\r')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= ' ')
      -          goto yy383;
      -        if (yych <= '.')
      -          goto yy333;
      -        goto yy385;
      -      }
      -    } else {
      -      if (yych <= 'M') {
      -        if (yych == '>')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'N')
      -          goto yy420;
      -        if (yych == 'n')
      -          goto yy420;
      -        goto yy333;
      -      }
      -    }
      -  yy378:
      -    yych = *++p;
      -    if (yych == 'I')
      -      goto yy421;
      -    if (yych == 'i')
      -      goto yy421;
      -    goto yy333;
      -  yy379:
      -    yych = *++p;
      -    if (yych == 'N')
      -      goto yy422;
      -    if (yych == 'n')
      -      goto yy422;
      -    goto yy333;
      -  yy380:
      -    yych = *++p;
      -    if (yych == 'V')
      -      goto yy367;
      -    if (yych == 'v')
      -      goto yy367;
      -    goto yy333;
      -  yy381:
      -    yych = *++p;
      -    if (yych == 'F')
      -      goto yy423;
      -    if (yych == 'f')
      -      goto yy423;
      -    goto yy333;
      -  yy382:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy424;
      -    if (yych == 't')
      -      goto yy424;
      -    goto yy333;
      -  yy383:
      -    ++p;
      -    { return 6; }
      -  yy385:
      -    yych = *++p;
      -    if (yych == '>')
      -      goto yy383;
      -    goto yy333;
      -  yy386:
      -    yych = *++p;
      -    if (yych == 'R')
      -      goto yy425;
      -    if (yych == 'r')
      -      goto yy425;
      -    goto yy333;
      -  yy387:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy426;
      -    if (yych == 'e')
      -      goto yy426;
      -    goto yy333;
      -  yy388:
      -    yych = *++p;
      -    if (yych == 'R')
      -      goto yy427;
      -    if (yych == 'r')
      -      goto yy427;
      -    goto yy333;
      -  yy389:
      -    yych = *++p;
      -    if (yych == 'C')
      -      goto yy408;
      -    if (yych == 'c')
      -      goto yy408;
      -    goto yy333;
      -  yy390:
      -    yych = *++p;
      -    if (yych == 'U')
      -      goto yy428;
      -    if (yych == 'u')
      -      goto yy428;
      -    goto yy333;
      -  yy391:
      -    yych = *++p;
      -    if (yych == 'Y')
      -      goto yy429;
      -    if (yych == 'y')
      -      goto yy429;
      -    goto yy333;
      -  yy392:
      -    yych = *++p;
      -    if (yych == 'M')
      -      goto yy430;
      -    if (yych == 'm')
      -      goto yy430;
      -    goto yy333;
      -  yy393:
      -    yych = *++p;
      -    if (yych == 'B')
      -      goto yy431;
      -    if (yych == 'b')
      -      goto yy431;
      -    goto yy333;
      -  yy394:
      -    yych = *++p;
      -    if (yych == 'O')
      -      goto yy363;
      -    if (yych == 'o')
      -      goto yy363;
      -    goto yy333;
      -  yy395:
      -    yych = *++p;
      -    if (yych == 'O')
      -      goto yy432;
      -    if (yych == 'o')
      -      goto yy432;
      -    goto yy333;
      -  yy396:
      -    yych = *++p;
      -    if (yych <= '/') {
      -      if (yych <= 0x1F) {
      -        if (yych <= 0x08)
      -          goto yy333;
      -        if (yych <= '\r')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= ' ')
      -          goto yy383;
      -        if (yych <= '.')
      -          goto yy333;
      -        goto yy385;
      -      }
      -    } else {
      -      if (yych <= 'D') {
      -        if (yych == '>')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'E')
      -          goto yy433;
      -        if (yych == 'e')
      -          goto yy433;
      -        goto yy333;
      -      }
      -    }
      -  yy397:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy431;
      -    if (yych == 't')
      -      goto yy431;
      -    goto yy333;
      -  yy398:
      -    yych = *++p;
      -    if (yych <= '/') {
      -      if (yych <= 0x1F) {
      -        if (yych <= 0x08)
      -          goto yy333;
      -        if (yych <= '\r')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= ' ')
      -          goto yy383;
      -        if (yych <= '.')
      -          goto yy333;
      -        goto yy385;
      -      }
      -    } else {
      -      if (yych <= '@') {
      -        if (yych == '>')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'A')
      -          goto yy434;
      -        if (yych == 'a')
      -          goto yy434;
      -        goto yy333;
      -      }
      -    }
      -  yy399:
      -    ++p;
      -    { return 2; }
      -  yy401:
      -    yych = *++p;
      -    if (yych == 'D')
      -      goto yy435;
      -    if (yych == 'd')
      -      goto yy435;
      -    goto yy333;
      -  yy402:
      -    yych = *++p;
      -    if (yych == 'R')
      -      goto yy436;
      -    if (yych == 'r')
      -      goto yy436;
      -    goto yy333;
      -  yy403:
      -    yych = *++p;
      -    if (yych == 'I')
      -      goto yy437;
      -    if (yych == 'i')
      -      goto yy437;
      -    goto yy333;
      -  yy404:
      -    yych = *++p;
      -    if (yych == 'D')
      -      goto yy438;
      -    if (yych == 'd')
      -      goto yy438;
      -    goto yy333;
      -  yy405:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy439;
      -    if (yych == 'e')
      -      goto yy439;
      -    goto yy333;
      -  yy406:
      -    yych = *++p;
      -    if (yych == 'C')
      -      goto yy440;
      -    if (yych == 'c')
      -      goto yy440;
      -    goto yy333;
      -  yy407:
      -    yych = *++p;
      -    if (yych == 'Y')
      -      goto yy367;
      -    if (yych == 'y')
      -      goto yy367;
      -    goto yy333;
      -  yy408:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy441;
      -    if (yych == 't')
      -      goto yy441;
      -    goto yy333;
      -  yy409:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy442;
      -    if (yych == 't')
      -      goto yy442;
      -    goto yy333;
      -  yy410:
      -    yych = *++p;
      -    if (yych <= '/') {
      -      if (yych <= 0x1F) {
      -        if (yych <= 0x08)
      -          goto yy333;
      -        if (yych <= '\r')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= ' ')
      -          goto yy383;
      -        if (yych <= '.')
      -          goto yy333;
      -        goto yy385;
      -      }
      -    } else {
      -      if (yych <= 'F') {
      -        if (yych == '>')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'G')
      -          goto yy443;
      -        if (yych == 'g')
      -          goto yy443;
      -        goto yy333;
      -      }
      -    }
      -  yy411:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy444;
      -    if (yych == 'a')
      -      goto yy444;
      -    goto yy333;
      -  yy412:
      -    yych = *++p;
      -    if (yych == 'L')
      -      goto yy445;
      -    if (yych == 'l')
      -      goto yy445;
      -    goto yy333;
      -  yy413:
      -    yych = *++p;
      -    if (yych == 'L')
      -      goto yy446;
      -    if (yych == 'l')
      -      goto yy446;
      -    goto yy333;
      -  yy414:
      -    yych = *++p;
      -    if (yych <= 'U') {
      -      if (yych == 'C')
      -        goto yy447;
      -      if (yych <= 'T')
      -        goto yy333;
      -      goto yy448;
      -    } else {
      -      if (yych <= 'c') {
      -        if (yych <= 'b')
      -          goto yy333;
      -        goto yy447;
      -      } else {
      -        if (yych == 'u')
      -          goto yy448;
      -        goto yy333;
      -      }
      -    }
      -  yy415:
      -    yych = *++p;
      -    if (yych == 'M')
      -      goto yy367;
      -    if (yych == 'm')
      -      goto yy367;
      -    goto yy333;
      -  yy416:
      -    yych = *++p;
      -    if (yych == 'M')
      -      goto yy449;
      -    if (yych == 'm')
      -      goto yy449;
      -    goto yy333;
      -  yy417:
      -    yych = *++p;
      -    if (yych == 'D')
      -      goto yy450;
      -    if (yych == 'd')
      -      goto yy450;
      -    goto yy333;
      -  yy418:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy451;
      -    if (yych == 'a')
      -      goto yy451;
      -    goto yy333;
      -  yy419:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy452;
      -    if (yych == 'e')
      -      goto yy452;
      -    goto yy333;
      -  yy420:
      -    yych = *++p;
      -    if (yych == 'K')
      -      goto yy367;
      -    if (yych == 'k')
      -      goto yy367;
      -    goto yy333;
      -  yy421:
      -    yych = *++p;
      -    if (yych == 'N')
      -      goto yy367;
      -    if (yych == 'n')
      -      goto yy367;
      -    goto yy333;
      -  yy422:
      -    yych = *++p;
      -    if (yych == 'U')
      -      goto yy453;
      -    if (yych == 'u')
      -      goto yy453;
      -    goto yy333;
      -  yy423:
      -    yych = *++p;
      -    if (yych == 'R')
      -      goto yy454;
      -    if (yych == 'r')
      -      goto yy454;
      -    goto yy333;
      -  yy424:
      -    yych = *++p;
      -    if (yych <= 'I') {
      -      if (yych == 'G')
      -        goto yy443;
      -      if (yych <= 'H')
      -        goto yy333;
      -      goto yy455;
      -    } else {
      -      if (yych <= 'g') {
      -        if (yych <= 'f')
      -          goto yy333;
      -        goto yy443;
      -      } else {
      -        if (yych == 'i')
      -          goto yy455;
      -        goto yy333;
      -      }
      -    }
      -  yy425:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy415;
      -    if (yych == 'a')
      -      goto yy415;
      -    goto yy333;
      -  yy426:
      -    yych = *++p;
      -    if (yych <= 0x1F) {
      -      if (yych <= 0x08)
      -        goto yy333;
      -      if (yych <= '\r')
      -        goto yy456;
      -      goto yy333;
      -    } else {
      -      if (yych <= ' ')
      -        goto yy456;
      -      if (yych == '>')
      -        goto yy456;
      -      goto yy333;
      -    }
      -  yy427:
      -    yych = *++p;
      -    if (yych == 'I')
      -      goto yy458;
      -    if (yych == 'i')
      -      goto yy458;
      -    goto yy333;
      -  yy428:
      -    yych = *++p;
      -    if (yych == 'R')
      -      goto yy459;
      -    if (yych == 'r')
      -      goto yy459;
      -    goto yy333;
      -  yy429:
      -    yych = *++p;
      -    if (yych == 'L')
      -      goto yy387;
      -    if (yych == 'l')
      -      goto yy387;
      -    goto yy333;
      -  yy430:
      -    yych = *++p;
      -    if (yych == 'M')
      -      goto yy460;
      -    if (yych == 'm')
      -      goto yy460;
      -    goto yy333;
      -  yy431:
      -    yych = *++p;
      -    if (yych == 'L')
      -      goto yy438;
      -    if (yych == 'l')
      -      goto yy438;
      -    goto yy333;
      -  yy432:
      -    yych = *++p;
      -    if (yych == 'O')
      -      goto yy461;
      -    if (yych == 'o')
      -      goto yy461;
      -    goto yy333;
      -  yy433:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy462;
      -    if (yych == 'a')
      -      goto yy462;
      -    goto yy333;
      -  yy434:
      -    yych = *++p;
      -    if (yych == 'C')
      -      goto yy420;
      -    if (yych == 'c')
      -      goto yy420;
      -    goto yy333;
      -  yy435:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy463;
      -    if (yych == 'a')
      -      goto yy463;
      -    goto yy333;
      -  yy436:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy464;
      -    if (yych == 'e')
      -      goto yy464;
      -    goto yy333;
      -  yy437:
      -    yych = *++p;
      -    if (yych == 'C')
      -      goto yy431;
      -    if (yych == 'c')
      -      goto yy431;
      -    goto yy333;
      -  yy438:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy367;
      -    if (yych == 'e')
      -      goto yy367;
      -    goto yy333;
      -  yy439:
      -    yych = *++p;
      -    if (yych <= '/') {
      -      if (yych <= 0x1F) {
      -        if (yych <= 0x08)
      -          goto yy333;
      -        if (yych <= '\r')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= ' ')
      -          goto yy383;
      -        if (yych <= '.')
      -          goto yy333;
      -        goto yy385;
      -      }
      -    } else {
      -      if (yych <= 'E') {
      -        if (yych == '>')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'F')
      -          goto yy465;
      -        if (yych == 'f')
      -          goto yy465;
      -        goto yy333;
      -      }
      -    }
      -  yy440:
      -    yych = *++p;
      -    if (yych == 'K')
      -      goto yy466;
      -    if (yych == 'k')
      -      goto yy466;
      -    goto yy333;
      -  yy441:
      -    yych = *++p;
      -    if (yych == 'I')
      -      goto yy455;
      -    if (yych == 'i')
      -      goto yy455;
      -    goto yy333;
      -  yy442:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy467;
      -    if (yych == 'e')
      -      goto yy467;
      -    goto yy333;
      -  yy443:
      -    yych = *++p;
      -    if (yych == 'R')
      -      goto yy468;
      -    if (yych == 'r')
      -      goto yy468;
      -    goto yy333;
      -  yy444:
      -    yych = *++p;
      -    if (yych == 'I')
      -      goto yy469;
      -    if (yych == 'i')
      -      goto yy469;
      -    goto yy333;
      -  yy445:
      -    yych = *++p;
      -    if (yych == 'O')
      -      goto yy470;
      -    if (yych == 'o')
      -      goto yy470;
      -    goto yy333;
      -  yy446:
      -    yych = *++p;
      -    if (yych == 'D')
      -      goto yy471;
      -    if (yych == 'd')
      -      goto yy471;
      -    goto yy333;
      -  yy447:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy364;
      -    if (yych == 'a')
      -      goto yy364;
      -    goto yy333;
      -  yy448:
      -    yych = *++p;
      -    if (yych == 'R')
      -      goto yy438;
      -    if (yych == 'r')
      -      goto yy438;
      -    goto yy333;
      -  yy449:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy472;
      -    if (yych == 'e')
      -      goto yy472;
      -    goto yy333;
      -  yy450:
      -    yych = *++p;
      -    if (yych <= '/') {
      -      if (yych <= 0x1F) {
      -        if (yych <= 0x08)
      -          goto yy333;
      -        if (yych <= '\r')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= ' ')
      -          goto yy383;
      -        if (yych <= '.')
      -          goto yy333;
      -        goto yy385;
      -      }
      -    } else {
      -      if (yych <= 'D') {
      -        if (yych == '>')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'E')
      -          goto yy467;
      -        if (yych == 'e')
      -          goto yy467;
      -        goto yy333;
      -      }
      -    }
      -  yy451:
      -    yych = *++p;
      -    if (yych == 'M')
      -      goto yy438;
      -    if (yych == 'm')
      -      goto yy438;
      -    goto yy333;
      -  yy452:
      -    yych = *++p;
      -    if (yych == 'N')
      -      goto yy462;
      -    if (yych == 'n')
      -      goto yy462;
      -    goto yy333;
      -  yy453:
      -    yych = *++p;
      -    if (yych <= '/') {
      -      if (yych <= 0x1F) {
      -        if (yych <= 0x08)
      -          goto yy333;
      -        if (yych <= '\r')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= ' ')
      -          goto yy383;
      -        if (yych <= '.')
      -          goto yy333;
      -        goto yy385;
      -      }
      -    } else {
      -      if (yych <= 'H') {
      -        if (yych == '>')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'I')
      -          goto yy473;
      -        if (yych == 'i')
      -          goto yy473;
      -        goto yy333;
      -      }
      -    }
      -  yy454:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy474;
      -    if (yych == 'a')
      -      goto yy474;
      -    goto yy333;
      -  yy455:
      -    yych = *++p;
      -    if (yych == 'O')
      -      goto yy421;
      -    if (yych == 'o')
      -      goto yy421;
      -    goto yy333;
      -  yy456:
      -    ++p;
      -    { return 1; }
      -  yy458:
      -    yych = *++p;
      -    if (yych == 'P')
      -      goto yy475;
      -    if (yych == 'p')
      -      goto yy475;
      -    goto yy333;
      -  yy459:
      -    yych = *++p;
      -    if (yych == 'C')
      -      goto yy438;
      -    if (yych == 'c')
      -      goto yy438;
      -    goto yy333;
      -  yy460:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy476;
      -    if (yych == 'a')
      -      goto yy476;
      -    goto yy333;
      -  yy461:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy367;
      -    if (yych == 't')
      -      goto yy367;
      -    goto yy333;
      -  yy462:
      -    yych = *++p;
      -    if (yych == 'D')
      -      goto yy367;
      -    if (yych == 'd')
      -      goto yy367;
      -    goto yy333;
      -  yy463:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy477;
      -    if (yych == 't')
      -      goto yy477;
      -    goto yy333;
      -  yy464:
      -    yych = *++p;
      -    if (yych == 'S')
      -      goto yy478;
      -    if (yych == 's')
      -      goto yy478;
      -    goto yy333;
      -  yy465:
      -    yych = *++p;
      -    if (yych == 'O')
      -      goto yy479;
      -    if (yych == 'o')
      -      goto yy479;
      -    goto yy333;
      -  yy466:
      -    yych = *++p;
      -    if (yych == 'Q')
      -      goto yy480;
      -    if (yych == 'q')
      -      goto yy480;
      -    goto yy333;
      -  yy467:
      -    yych = *++p;
      -    if (yych == 'R')
      -      goto yy367;
      -    if (yych == 'r')
      -      goto yy367;
      -    goto yy333;
      -  yy468:
      -    yych = *++p;
      -    if (yych == 'O')
      -      goto yy481;
      -    if (yych == 'o')
      -      goto yy481;
      -    goto yy333;
      -  yy469:
      -    yych = *++p;
      -    if (yych == 'L')
      -      goto yy478;
      -    if (yych == 'l')
      -      goto yy478;
      -    goto yy333;
      -  yy470:
      -    yych = *++p;
      -    if (yych == 'G')
      -      goto yy367;
      -    if (yych == 'g')
      -      goto yy367;
      -    goto yy333;
      -  yy471:
      -    yych = *++p;
      -    if (yych == 'S')
      -      goto yy482;
      -    if (yych == 's')
      -      goto yy482;
      -    goto yy333;
      -  yy472:
      -    yych = *++p;
      -    if (yych <= '/') {
      -      if (yych <= 0x1F) {
      -        if (yych <= 0x08)
      -          goto yy333;
      -        if (yych <= '\r')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= ' ')
      -          goto yy383;
      -        if (yych <= '.')
      -          goto yy333;
      -        goto yy385;
      -      }
      -    } else {
      -      if (yych <= 'R') {
      -        if (yych == '>')
      -          goto yy383;
      -        goto yy333;
      -      } else {
      -        if (yych <= 'S')
      -          goto yy482;
      -        if (yych == 's')
      -          goto yy482;
      -        goto yy333;
      -      }
      -    }
      -  yy473:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy483;
      -    if (yych == 't')
      -      goto yy483;
      -    goto yy333;
      -  yy474:
      -    yych = *++p;
      -    if (yych == 'M')
      -      goto yy484;
      -    if (yych == 'm')
      -      goto yy484;
      -    goto yy333;
      -  yy475:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy426;
      -    if (yych == 't')
      -      goto yy426;
      -    goto yy333;
      -  yy476:
      -    yych = *++p;
      -    if (yych == 'R')
      -      goto yy407;
      -    if (yych == 'r')
      -      goto yy407;
      -    goto yy333;
      -  yy477:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy485;
      -    if (yych == 'a')
      -      goto yy485;
      -    goto yy333;
      -  yy478:
      -    yych = *++p;
      -    if (yych == 'S')
      -      goto yy367;
      -    if (yych == 's')
      -      goto yy367;
      -    goto yy333;
      -  yy479:
      -    yych = *++p;
      -    if (yych == 'N')
      -      goto yy461;
      -    if (yych == 'n')
      -      goto yy461;
      -    goto yy333;
      -  yy480:
      -    yych = *++p;
      -    if (yych == 'U')
      -      goto yy486;
      -    if (yych == 'u')
      -      goto yy486;
      -    goto yy333;
      -  yy481:
      -    yych = *++p;
      -    if (yych == 'U')
      -      goto yy487;
      -    if (yych == 'u')
      -      goto yy487;
      -    goto yy333;
      -  yy482:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy461;
      -    if (yych == 'e')
      -      goto yy461;
      -    goto yy333;
      -  yy483:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy415;
      -    if (yych == 'e')
      -      goto yy415;
      -    goto yy333;
      -  yy484:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy478;
      -    if (yych == 'e')
      -      goto yy478;
      -    goto yy333;
      -  yy485:
      -    yych = *++p;
      -    if (yych == '[')
      -      goto yy488;
      -    goto yy333;
      -  yy486:
      -    yych = *++p;
      -    if (yych == 'O')
      -      goto yy490;
      -    if (yych == 'o')
      -      goto yy490;
      -    goto yy333;
      -  yy487:
      -    yych = *++p;
      -    if (yych == 'P')
      -      goto yy367;
      -    if (yych == 'p')
      -      goto yy367;
      -    goto yy333;
      -  yy488:
      -    ++p;
      -    { return 5; }
      -  yy490:
      -    ++p;
      -    if ((yych = *p) == 'T')
      -      goto yy438;
      -    if (yych == 't')
      -      goto yy438;
      -    goto yy333;
      -  }
      +{
      +	unsigned char yych;
      +	yych = *p;
      +	if (yych == '<') goto yy356;
      +	++p;
      +yy355:
      +	{ return 0; }
      +yy356:
      +	yych = *(marker = ++p);
      +	switch (yych) {
      +	case '!':	goto yy357;
      +	case '/':	goto yy359;
      +	case '?':	goto yy360;
      +	case 'A':
      +	case 'a':	goto yy362;
      +	case 'B':
      +	case 'b':	goto yy363;
      +	case 'C':
      +	case 'c':	goto yy364;
      +	case 'D':
      +	case 'd':	goto yy365;
      +	case 'F':
      +	case 'f':	goto yy366;
      +	case 'H':
      +	case 'h':	goto yy367;
      +	case 'I':
      +	case 'i':	goto yy368;
      +	case 'L':
      +	case 'l':	goto yy369;
      +	case 'M':
      +	case 'm':	goto yy370;
      +	case 'N':
      +	case 'n':	goto yy371;
      +	case 'O':
      +	case 'o':	goto yy372;
      +	case 'P':
      +	case 'p':	goto yy373;
      +	case 'S':
      +	case 's':	goto yy374;
      +	case 'T':
      +	case 't':	goto yy375;
      +	case 'U':
      +	case 'u':	goto yy376;
      +	default:	goto yy355;
      +	}
      +yy357:
      +	yych = *++p;
      +	if (yych <= '@') {
      +		if (yych == '-') goto yy377;
      +	} else {
      +		if (yych <= 'Z') goto yy378;
      +		if (yych <= '[') goto yy380;
      +	}
      +yy358:
      +	p = marker;
      +	goto yy355;
      +yy359:
      +	yych = *++p;
      +	switch (yych) {
      +	case 'A':
      +	case 'a':	goto yy362;
      +	case 'B':
      +	case 'b':	goto yy363;
      +	case 'C':
      +	case 'c':	goto yy364;
      +	case 'D':
      +	case 'd':	goto yy365;
      +	case 'F':
      +	case 'f':	goto yy366;
      +	case 'H':
      +	case 'h':	goto yy367;
      +	case 'I':
      +	case 'i':	goto yy368;
      +	case 'L':
      +	case 'l':	goto yy369;
      +	case 'M':
      +	case 'm':	goto yy370;
      +	case 'N':
      +	case 'n':	goto yy371;
      +	case 'O':
      +	case 'o':	goto yy372;
      +	case 'P':
      +	case 'p':	goto yy381;
      +	case 'S':
      +	case 's':	goto yy382;
      +	case 'T':
      +	case 't':	goto yy375;
      +	case 'U':
      +	case 'u':	goto yy376;
      +	default:	goto yy358;
      +	}
      +yy360:
      +	++p;
      +	{ return 3; }
      +yy362:
      +	yych = *++p;
      +	if (yych <= 'S') {
      +		if (yych <= 'D') {
      +			if (yych <= 'C') goto yy358;
      +			goto yy383;
      +		} else {
      +			if (yych <= 'Q') goto yy358;
      +			if (yych <= 'R') goto yy384;
      +			goto yy385;
      +		}
      +	} else {
      +		if (yych <= 'q') {
      +			if (yych == 'd') goto yy383;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'r') goto yy384;
      +			if (yych <= 's') goto yy385;
      +			goto yy358;
      +		}
      +	}
      +yy363:
      +	yych = *++p;
      +	if (yych <= 'O') {
      +		if (yych <= 'K') {
      +			if (yych == 'A') goto yy386;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'L') goto yy387;
      +			if (yych <= 'N') goto yy358;
      +			goto yy388;
      +		}
      +	} else {
      +		if (yych <= 'k') {
      +			if (yych == 'a') goto yy386;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'l') goto yy387;
      +			if (yych == 'o') goto yy388;
      +			goto yy358;
      +		}
      +	}
      +yy364:
      +	yych = *++p;
      +	if (yych <= 'O') {
      +		if (yych <= 'D') {
      +			if (yych == 'A') goto yy389;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'E') goto yy390;
      +			if (yych <= 'N') goto yy358;
      +			goto yy391;
      +		}
      +	} else {
      +		if (yych <= 'd') {
      +			if (yych == 'a') goto yy389;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'e') goto yy390;
      +			if (yych == 'o') goto yy391;
      +			goto yy358;
      +		}
      +	}
      +yy365:
      +	yych = *++p;
      +	switch (yych) {
      +	case 'D':
      +	case 'L':
      +	case 'T':
      +	case 'd':
      +	case 'l':
      +	case 't':	goto yy392;
      +	case 'E':
      +	case 'e':	goto yy393;
      +	case 'I':
      +	case 'i':	goto yy394;
      +	default:	goto yy358;
      +	}
      +yy366:
      +	yych = *++p;
      +	if (yych <= 'R') {
      +		if (yych <= 'N') {
      +			if (yych == 'I') goto yy395;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'O') goto yy396;
      +			if (yych <= 'Q') goto yy358;
      +			goto yy397;
      +		}
      +	} else {
      +		if (yych <= 'n') {
      +			if (yych == 'i') goto yy395;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'o') goto yy396;
      +			if (yych == 'r') goto yy397;
      +			goto yy358;
      +		}
      +	}
      +yy367:
      +	yych = *++p;
      +	if (yych <= 'S') {
      +		if (yych <= 'D') {
      +			if (yych <= '0') goto yy358;
      +			if (yych <= '6') goto yy392;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'E') goto yy398;
      +			if (yych == 'R') goto yy392;
      +			goto yy358;
      +		}
      +	} else {
      +		if (yych <= 'q') {
      +			if (yych <= 'T') goto yy399;
      +			if (yych == 'e') goto yy398;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'r') goto yy392;
      +			if (yych == 't') goto yy399;
      +			goto yy358;
      +		}
      +	}
      +yy368:
      +	yych = *++p;
      +	if (yych == 'F') goto yy400;
      +	if (yych == 'f') goto yy400;
      +	goto yy358;
      +yy369:
      +	yych = *++p;
      +	if (yych <= 'I') {
      +		if (yych == 'E') goto yy401;
      +		if (yych <= 'H') goto yy358;
      +		goto yy402;
      +	} else {
      +		if (yych <= 'e') {
      +			if (yych <= 'd') goto yy358;
      +			goto yy401;
      +		} else {
      +			if (yych == 'i') goto yy402;
      +			goto yy358;
      +		}
      +	}
      +yy370:
      +	yych = *++p;
      +	if (yych <= 'E') {
      +		if (yych == 'A') goto yy403;
      +		if (yych <= 'D') goto yy358;
      +		goto yy404;
      +	} else {
      +		if (yych <= 'a') {
      +			if (yych <= '`') goto yy358;
      +			goto yy403;
      +		} else {
      +			if (yych == 'e') goto yy404;
      +			goto yy358;
      +		}
      +	}
      +yy371:
      +	yych = *++p;
      +	if (yych <= 'O') {
      +		if (yych == 'A') goto yy405;
      +		if (yych <= 'N') goto yy358;
      +		goto yy406;
      +	} else {
      +		if (yych <= 'a') {
      +			if (yych <= '`') goto yy358;
      +			goto yy405;
      +		} else {
      +			if (yych == 'o') goto yy406;
      +			goto yy358;
      +		}
      +	}
      +yy372:
      +	yych = *++p;
      +	if (yych <= 'P') {
      +		if (yych == 'L') goto yy392;
      +		if (yych <= 'O') goto yy358;
      +		goto yy407;
      +	} else {
      +		if (yych <= 'l') {
      +			if (yych <= 'k') goto yy358;
      +			goto yy392;
      +		} else {
      +			if (yych == 'p') goto yy407;
      +			goto yy358;
      +		}
      +	}
      +yy373:
      +	yych = *++p;
      +	if (yych <= '>') {
      +		if (yych <= ' ') {
      +			if (yych <= 0x08) goto yy358;
      +			if (yych <= '\r') goto yy408;
      +			if (yych <= 0x1F) goto yy358;
      +			goto yy408;
      +		} else {
      +			if (yych == '/') goto yy410;
      +			if (yych <= '=') goto yy358;
      +			goto yy408;
      +		}
      +	} else {
      +		if (yych <= 'R') {
      +			if (yych == 'A') goto yy411;
      +			if (yych <= 'Q') goto yy358;
      +			goto yy412;
      +		} else {
      +			if (yych <= 'a') {
      +				if (yych <= '`') goto yy358;
      +				goto yy411;
      +			} else {
      +				if (yych == 'r') goto yy412;
      +				goto yy358;
      +			}
      +		}
      +	}
      +yy374:
      +	yych = *++p;
      +	switch (yych) {
      +	case 'C':
      +	case 'c':	goto yy413;
      +	case 'E':
      +	case 'e':	goto yy414;
      +	case 'O':
      +	case 'o':	goto yy415;
      +	case 'T':
      +	case 't':	goto yy416;
      +	case 'U':
      +	case 'u':	goto yy417;
      +	default:	goto yy358;
      +	}
      +yy375:
      +	yych = *++p;
      +	switch (yych) {
      +	case 'A':
      +	case 'a':	goto yy418;
      +	case 'B':
      +	case 'b':	goto yy419;
      +	case 'D':
      +	case 'd':	goto yy392;
      +	case 'F':
      +	case 'f':	goto yy420;
      +	case 'H':
      +	case 'h':	goto yy421;
      +	case 'I':
      +	case 'i':	goto yy422;
      +	case 'R':
      +	case 'r':	goto yy423;
      +	default:	goto yy358;
      +	}
      +yy376:
      +	yych = *++p;
      +	if (yych == 'L') goto yy392;
      +	if (yych == 'l') goto yy392;
      +	goto yy358;
      +yy377:
      +	yych = *++p;
      +	if (yych == '-') goto yy424;
      +	goto yy358;
      +yy378:
      +	++p;
      +	{ return 4; }
      +yy380:
      +	yych = *++p;
      +	if (yych == 'C') goto yy426;
      +	if (yych == 'c') goto yy426;
      +	goto yy358;
      +yy381:
      +	yych = *++p;
      +	if (yych <= '/') {
      +		if (yych <= 0x1F) {
      +			if (yych <= 0x08) goto yy358;
      +			if (yych <= '\r') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= ' ') goto yy408;
      +			if (yych <= '.') goto yy358;
      +			goto yy410;
      +		}
      +	} else {
      +		if (yych <= '@') {
      +			if (yych == '>') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'A') goto yy411;
      +			if (yych == 'a') goto yy411;
      +			goto yy358;
      +		}
      +	}
      +yy382:
      +	yych = *++p;
      +	if (yych <= 'U') {
      +		if (yych <= 'N') {
      +			if (yych == 'E') goto yy414;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'O') goto yy415;
      +			if (yych <= 'T') goto yy358;
      +			goto yy417;
      +		}
      +	} else {
      +		if (yych <= 'n') {
      +			if (yych == 'e') goto yy414;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'o') goto yy415;
      +			if (yych == 'u') goto yy417;
      +			goto yy358;
      +		}
      +	}
      +yy383:
      +	yych = *++p;
      +	if (yych == 'D') goto yy427;
      +	if (yych == 'd') goto yy427;
      +	goto yy358;
      +yy384:
      +	yych = *++p;
      +	if (yych == 'T') goto yy428;
      +	if (yych == 't') goto yy428;
      +	goto yy358;
      +yy385:
      +	yych = *++p;
      +	if (yych == 'I') goto yy429;
      +	if (yych == 'i') goto yy429;
      +	goto yy358;
      +yy386:
      +	yych = *++p;
      +	if (yych == 'S') goto yy430;
      +	if (yych == 's') goto yy430;
      +	goto yy358;
      +yy387:
      +	yych = *++p;
      +	if (yych == 'O') goto yy431;
      +	if (yych == 'o') goto yy431;
      +	goto yy358;
      +yy388:
      +	yych = *++p;
      +	if (yych == 'D') goto yy432;
      +	if (yych == 'd') goto yy432;
      +	goto yy358;
      +yy389:
      +	yych = *++p;
      +	if (yych == 'P') goto yy433;
      +	if (yych == 'p') goto yy433;
      +	goto yy358;
      +yy390:
      +	yych = *++p;
      +	if (yych == 'N') goto yy434;
      +	if (yych == 'n') goto yy434;
      +	goto yy358;
      +yy391:
      +	yych = *++p;
      +	if (yych == 'L') goto yy435;
      +	if (yych == 'l') goto yy435;
      +	goto yy358;
      +yy392:
      +	yych = *++p;
      +	if (yych <= ' ') {
      +		if (yych <= 0x08) goto yy358;
      +		if (yych <= '\r') goto yy408;
      +		if (yych <= 0x1F) goto yy358;
      +		goto yy408;
      +	} else {
      +		if (yych <= '/') {
      +			if (yych <= '.') goto yy358;
      +			goto yy410;
      +		} else {
      +			if (yych == '>') goto yy408;
      +			goto yy358;
      +		}
      +	}
      +yy393:
      +	yych = *++p;
      +	if (yych == 'T') goto yy436;
      +	if (yych == 't') goto yy436;
      +	goto yy358;
      +yy394:
      +	yych = *++p;
      +	if (yych <= 'V') {
      +		if (yych <= 'Q') {
      +			if (yych == 'A') goto yy437;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'R') goto yy392;
      +			if (yych <= 'U') goto yy358;
      +			goto yy392;
      +		}
      +	} else {
      +		if (yych <= 'q') {
      +			if (yych == 'a') goto yy437;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'r') goto yy392;
      +			if (yych == 'v') goto yy392;
      +			goto yy358;
      +		}
      +	}
      +yy395:
      +	yych = *++p;
      +	if (yych <= 'G') {
      +		if (yych == 'E') goto yy438;
      +		if (yych <= 'F') goto yy358;
      +		goto yy439;
      +	} else {
      +		if (yych <= 'e') {
      +			if (yych <= 'd') goto yy358;
      +			goto yy438;
      +		} else {
      +			if (yych == 'g') goto yy439;
      +			goto yy358;
      +		}
      +	}
      +yy396:
      +	yych = *++p;
      +	if (yych <= 'R') {
      +		if (yych == 'O') goto yy434;
      +		if (yych <= 'Q') goto yy358;
      +		goto yy440;
      +	} else {
      +		if (yych <= 'o') {
      +			if (yych <= 'n') goto yy358;
      +			goto yy434;
      +		} else {
      +			if (yych == 'r') goto yy440;
      +			goto yy358;
      +		}
      +	}
      +yy397:
      +	yych = *++p;
      +	if (yych == 'A') goto yy441;
      +	if (yych == 'a') goto yy441;
      +	goto yy358;
      +yy398:
      +	yych = *++p;
      +	if (yych == 'A') goto yy442;
      +	if (yych == 'a') goto yy442;
      +	goto yy358;
      +yy399:
      +	yych = *++p;
      +	if (yych == 'M') goto yy376;
      +	if (yych == 'm') goto yy376;
      +	goto yy358;
      +yy400:
      +	yych = *++p;
      +	if (yych == 'R') goto yy443;
      +	if (yych == 'r') goto yy443;
      +	goto yy358;
      +yy401:
      +	yych = *++p;
      +	if (yych == 'G') goto yy444;
      +	if (yych == 'g') goto yy444;
      +	goto yy358;
      +yy402:
      +	yych = *++p;
      +	if (yych <= '/') {
      +		if (yych <= 0x1F) {
      +			if (yych <= 0x08) goto yy358;
      +			if (yych <= '\r') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= ' ') goto yy408;
      +			if (yych <= '.') goto yy358;
      +			goto yy410;
      +		}
      +	} else {
      +		if (yych <= 'M') {
      +			if (yych == '>') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'N') goto yy445;
      +			if (yych == 'n') goto yy445;
      +			goto yy358;
      +		}
      +	}
      +yy403:
      +	yych = *++p;
      +	if (yych == 'I') goto yy446;
      +	if (yych == 'i') goto yy446;
      +	goto yy358;
      +yy404:
      +	yych = *++p;
      +	if (yych == 'N') goto yy447;
      +	if (yych == 'n') goto yy447;
      +	goto yy358;
      +yy405:
      +	yych = *++p;
      +	if (yych == 'V') goto yy392;
      +	if (yych == 'v') goto yy392;
      +	goto yy358;
      +yy406:
      +	yych = *++p;
      +	if (yych == 'F') goto yy448;
      +	if (yych == 'f') goto yy448;
      +	goto yy358;
      +yy407:
      +	yych = *++p;
      +	if (yych == 'T') goto yy449;
      +	if (yych == 't') goto yy449;
      +	goto yy358;
      +yy408:
      +	++p;
      +	{ return 6; }
      +yy410:
      +	yych = *++p;
      +	if (yych == '>') goto yy408;
      +	goto yy358;
      +yy411:
      +	yych = *++p;
      +	if (yych == 'R') goto yy450;
      +	if (yych == 'r') goto yy450;
      +	goto yy358;
      +yy412:
      +	yych = *++p;
      +	if (yych == 'E') goto yy451;
      +	if (yych == 'e') goto yy451;
      +	goto yy358;
      +yy413:
      +	yych = *++p;
      +	if (yych == 'R') goto yy452;
      +	if (yych == 'r') goto yy452;
      +	goto yy358;
      +yy414:
      +	yych = *++p;
      +	if (yych == 'C') goto yy433;
      +	if (yych == 'c') goto yy433;
      +	goto yy358;
      +yy415:
      +	yych = *++p;
      +	if (yych == 'U') goto yy453;
      +	if (yych == 'u') goto yy453;
      +	goto yy358;
      +yy416:
      +	yych = *++p;
      +	if (yych == 'Y') goto yy454;
      +	if (yych == 'y') goto yy454;
      +	goto yy358;
      +yy417:
      +	yych = *++p;
      +	if (yych == 'M') goto yy455;
      +	if (yych == 'm') goto yy455;
      +	goto yy358;
      +yy418:
      +	yych = *++p;
      +	if (yych == 'B') goto yy456;
      +	if (yych == 'b') goto yy456;
      +	goto yy358;
      +yy419:
      +	yych = *++p;
      +	if (yych == 'O') goto yy388;
      +	if (yych == 'o') goto yy388;
      +	goto yy358;
      +yy420:
      +	yych = *++p;
      +	if (yych == 'O') goto yy457;
      +	if (yych == 'o') goto yy457;
      +	goto yy358;
      +yy421:
      +	yych = *++p;
      +	if (yych <= '/') {
      +		if (yych <= 0x1F) {
      +			if (yych <= 0x08) goto yy358;
      +			if (yych <= '\r') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= ' ') goto yy408;
      +			if (yych <= '.') goto yy358;
      +			goto yy410;
      +		}
      +	} else {
      +		if (yych <= 'D') {
      +			if (yych == '>') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'E') goto yy458;
      +			if (yych == 'e') goto yy458;
      +			goto yy358;
      +		}
      +	}
      +yy422:
      +	yych = *++p;
      +	if (yych == 'T') goto yy456;
      +	if (yych == 't') goto yy456;
      +	goto yy358;
      +yy423:
      +	yych = *++p;
      +	if (yych <= '/') {
      +		if (yych <= 0x1F) {
      +			if (yych <= 0x08) goto yy358;
      +			if (yych <= '\r') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= ' ') goto yy408;
      +			if (yych <= '.') goto yy358;
      +			goto yy410;
      +		}
      +	} else {
      +		if (yych <= '@') {
      +			if (yych == '>') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'A') goto yy459;
      +			if (yych == 'a') goto yy459;
      +			goto yy358;
      +		}
      +	}
      +yy424:
      +	++p;
      +	{ return 2; }
      +yy426:
      +	yych = *++p;
      +	if (yych == 'D') goto yy460;
      +	if (yych == 'd') goto yy460;
      +	goto yy358;
      +yy427:
      +	yych = *++p;
      +	if (yych == 'R') goto yy461;
      +	if (yych == 'r') goto yy461;
      +	goto yy358;
      +yy428:
      +	yych = *++p;
      +	if (yych == 'I') goto yy462;
      +	if (yych == 'i') goto yy462;
      +	goto yy358;
      +yy429:
      +	yych = *++p;
      +	if (yych == 'D') goto yy463;
      +	if (yych == 'd') goto yy463;
      +	goto yy358;
      +yy430:
      +	yych = *++p;
      +	if (yych == 'E') goto yy464;
      +	if (yych == 'e') goto yy464;
      +	goto yy358;
      +yy431:
      +	yych = *++p;
      +	if (yych == 'C') goto yy465;
      +	if (yych == 'c') goto yy465;
      +	goto yy358;
      +yy432:
      +	yych = *++p;
      +	if (yych == 'Y') goto yy392;
      +	if (yych == 'y') goto yy392;
      +	goto yy358;
      +yy433:
      +	yych = *++p;
      +	if (yych == 'T') goto yy466;
      +	if (yych == 't') goto yy466;
      +	goto yy358;
      +yy434:
      +	yych = *++p;
      +	if (yych == 'T') goto yy467;
      +	if (yych == 't') goto yy467;
      +	goto yy358;
      +yy435:
      +	yych = *++p;
      +	if (yych <= '/') {
      +		if (yych <= 0x1F) {
      +			if (yych <= 0x08) goto yy358;
      +			if (yych <= '\r') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= ' ') goto yy408;
      +			if (yych <= '.') goto yy358;
      +			goto yy410;
      +		}
      +	} else {
      +		if (yych <= 'F') {
      +			if (yych == '>') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'G') goto yy468;
      +			if (yych == 'g') goto yy468;
      +			goto yy358;
      +		}
      +	}
      +yy436:
      +	yych = *++p;
      +	if (yych == 'A') goto yy469;
      +	if (yych == 'a') goto yy469;
      +	goto yy358;
      +yy437:
      +	yych = *++p;
      +	if (yych == 'L') goto yy470;
      +	if (yych == 'l') goto yy470;
      +	goto yy358;
      +yy438:
      +	yych = *++p;
      +	if (yych == 'L') goto yy471;
      +	if (yych == 'l') goto yy471;
      +	goto yy358;
      +yy439:
      +	yych = *++p;
      +	if (yych <= 'U') {
      +		if (yych == 'C') goto yy472;
      +		if (yych <= 'T') goto yy358;
      +		goto yy473;
      +	} else {
      +		if (yych <= 'c') {
      +			if (yych <= 'b') goto yy358;
      +			goto yy472;
      +		} else {
      +			if (yych == 'u') goto yy473;
      +			goto yy358;
      +		}
      +	}
      +yy440:
      +	yych = *++p;
      +	if (yych == 'M') goto yy392;
      +	if (yych == 'm') goto yy392;
      +	goto yy358;
      +yy441:
      +	yych = *++p;
      +	if (yych == 'M') goto yy474;
      +	if (yych == 'm') goto yy474;
      +	goto yy358;
      +yy442:
      +	yych = *++p;
      +	if (yych == 'D') goto yy475;
      +	if (yych == 'd') goto yy475;
      +	goto yy358;
      +yy443:
      +	yych = *++p;
      +	if (yych == 'A') goto yy476;
      +	if (yych == 'a') goto yy476;
      +	goto yy358;
      +yy444:
      +	yych = *++p;
      +	if (yych == 'E') goto yy477;
      +	if (yych == 'e') goto yy477;
      +	goto yy358;
      +yy445:
      +	yych = *++p;
      +	if (yych == 'K') goto yy392;
      +	if (yych == 'k') goto yy392;
      +	goto yy358;
      +yy446:
      +	yych = *++p;
      +	if (yych == 'N') goto yy392;
      +	if (yych == 'n') goto yy392;
      +	goto yy358;
      +yy447:
      +	yych = *++p;
      +	if (yych == 'U') goto yy478;
      +	if (yych == 'u') goto yy478;
      +	goto yy358;
      +yy448:
      +	yych = *++p;
      +	if (yych == 'R') goto yy479;
      +	if (yych == 'r') goto yy479;
      +	goto yy358;
      +yy449:
      +	yych = *++p;
      +	if (yych <= 'I') {
      +		if (yych == 'G') goto yy468;
      +		if (yych <= 'H') goto yy358;
      +		goto yy480;
      +	} else {
      +		if (yych <= 'g') {
      +			if (yych <= 'f') goto yy358;
      +			goto yy468;
      +		} else {
      +			if (yych == 'i') goto yy480;
      +			goto yy358;
      +		}
      +	}
      +yy450:
      +	yych = *++p;
      +	if (yych == 'A') goto yy440;
      +	if (yych == 'a') goto yy440;
      +	goto yy358;
      +yy451:
      +	yych = *++p;
      +	if (yych <= 0x1F) {
      +		if (yych <= 0x08) goto yy358;
      +		if (yych <= '\r') goto yy481;
      +		goto yy358;
      +	} else {
      +		if (yych <= ' ') goto yy481;
      +		if (yych == '>') goto yy481;
      +		goto yy358;
      +	}
      +yy452:
      +	yych = *++p;
      +	if (yych == 'I') goto yy483;
      +	if (yych == 'i') goto yy483;
      +	goto yy358;
      +yy453:
      +	yych = *++p;
      +	if (yych == 'R') goto yy484;
      +	if (yych == 'r') goto yy484;
      +	goto yy358;
      +yy454:
      +	yych = *++p;
      +	if (yych == 'L') goto yy412;
      +	if (yych == 'l') goto yy412;
      +	goto yy358;
      +yy455:
      +	yych = *++p;
      +	if (yych == 'M') goto yy485;
      +	if (yych == 'm') goto yy485;
      +	goto yy358;
      +yy456:
      +	yych = *++p;
      +	if (yych == 'L') goto yy463;
      +	if (yych == 'l') goto yy463;
      +	goto yy358;
      +yy457:
      +	yych = *++p;
      +	if (yych == 'O') goto yy486;
      +	if (yych == 'o') goto yy486;
      +	goto yy358;
      +yy458:
      +	yych = *++p;
      +	if (yych == 'A') goto yy487;
      +	if (yych == 'a') goto yy487;
      +	goto yy358;
      +yy459:
      +	yych = *++p;
      +	if (yych == 'C') goto yy445;
      +	if (yych == 'c') goto yy445;
      +	goto yy358;
      +yy460:
      +	yych = *++p;
      +	if (yych == 'A') goto yy488;
      +	if (yych == 'a') goto yy488;
      +	goto yy358;
      +yy461:
      +	yych = *++p;
      +	if (yych == 'E') goto yy489;
      +	if (yych == 'e') goto yy489;
      +	goto yy358;
      +yy462:
      +	yych = *++p;
      +	if (yych == 'C') goto yy456;
      +	if (yych == 'c') goto yy456;
      +	goto yy358;
      +yy463:
      +	yych = *++p;
      +	if (yych == 'E') goto yy392;
      +	if (yych == 'e') goto yy392;
      +	goto yy358;
      +yy464:
      +	yych = *++p;
      +	if (yych <= '/') {
      +		if (yych <= 0x1F) {
      +			if (yych <= 0x08) goto yy358;
      +			if (yych <= '\r') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= ' ') goto yy408;
      +			if (yych <= '.') goto yy358;
      +			goto yy410;
      +		}
      +	} else {
      +		if (yych <= 'E') {
      +			if (yych == '>') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'F') goto yy490;
      +			if (yych == 'f') goto yy490;
      +			goto yy358;
      +		}
      +	}
      +yy465:
      +	yych = *++p;
      +	if (yych == 'K') goto yy491;
      +	if (yych == 'k') goto yy491;
      +	goto yy358;
      +yy466:
      +	yych = *++p;
      +	if (yych == 'I') goto yy480;
      +	if (yych == 'i') goto yy480;
      +	goto yy358;
      +yy467:
      +	yych = *++p;
      +	if (yych == 'E') goto yy492;
      +	if (yych == 'e') goto yy492;
      +	goto yy358;
      +yy468:
      +	yych = *++p;
      +	if (yych == 'R') goto yy493;
      +	if (yych == 'r') goto yy493;
      +	goto yy358;
      +yy469:
      +	yych = *++p;
      +	if (yych == 'I') goto yy494;
      +	if (yych == 'i') goto yy494;
      +	goto yy358;
      +yy470:
      +	yych = *++p;
      +	if (yych == 'O') goto yy495;
      +	if (yych == 'o') goto yy495;
      +	goto yy358;
      +yy471:
      +	yych = *++p;
      +	if (yych == 'D') goto yy496;
      +	if (yych == 'd') goto yy496;
      +	goto yy358;
      +yy472:
      +	yych = *++p;
      +	if (yych == 'A') goto yy389;
      +	if (yych == 'a') goto yy389;
      +	goto yy358;
      +yy473:
      +	yych = *++p;
      +	if (yych == 'R') goto yy463;
      +	if (yych == 'r') goto yy463;
      +	goto yy358;
      +yy474:
      +	yych = *++p;
      +	if (yych == 'E') goto yy497;
      +	if (yych == 'e') goto yy497;
      +	goto yy358;
      +yy475:
      +	yych = *++p;
      +	if (yych <= '/') {
      +		if (yych <= 0x1F) {
      +			if (yych <= 0x08) goto yy358;
      +			if (yych <= '\r') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= ' ') goto yy408;
      +			if (yych <= '.') goto yy358;
      +			goto yy410;
      +		}
      +	} else {
      +		if (yych <= 'D') {
      +			if (yych == '>') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'E') goto yy492;
      +			if (yych == 'e') goto yy492;
      +			goto yy358;
      +		}
      +	}
      +yy476:
      +	yych = *++p;
      +	if (yych == 'M') goto yy463;
      +	if (yych == 'm') goto yy463;
      +	goto yy358;
      +yy477:
      +	yych = *++p;
      +	if (yych == 'N') goto yy487;
      +	if (yych == 'n') goto yy487;
      +	goto yy358;
      +yy478:
      +	yych = *++p;
      +	if (yych <= '/') {
      +		if (yych <= 0x1F) {
      +			if (yych <= 0x08) goto yy358;
      +			if (yych <= '\r') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= ' ') goto yy408;
      +			if (yych <= '.') goto yy358;
      +			goto yy410;
      +		}
      +	} else {
      +		if (yych <= 'H') {
      +			if (yych == '>') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'I') goto yy498;
      +			if (yych == 'i') goto yy498;
      +			goto yy358;
      +		}
      +	}
      +yy479:
      +	yych = *++p;
      +	if (yych == 'A') goto yy499;
      +	if (yych == 'a') goto yy499;
      +	goto yy358;
      +yy480:
      +	yych = *++p;
      +	if (yych == 'O') goto yy446;
      +	if (yych == 'o') goto yy446;
      +	goto yy358;
      +yy481:
      +	++p;
      +	{ return 1; }
      +yy483:
      +	yych = *++p;
      +	if (yych == 'P') goto yy500;
      +	if (yych == 'p') goto yy500;
      +	goto yy358;
      +yy484:
      +	yych = *++p;
      +	if (yych == 'C') goto yy463;
      +	if (yych == 'c') goto yy463;
      +	goto yy358;
      +yy485:
      +	yych = *++p;
      +	if (yych == 'A') goto yy501;
      +	if (yych == 'a') goto yy501;
      +	goto yy358;
      +yy486:
      +	yych = *++p;
      +	if (yych == 'T') goto yy392;
      +	if (yych == 't') goto yy392;
      +	goto yy358;
      +yy487:
      +	yych = *++p;
      +	if (yych == 'D') goto yy392;
      +	if (yych == 'd') goto yy392;
      +	goto yy358;
      +yy488:
      +	yych = *++p;
      +	if (yych == 'T') goto yy502;
      +	if (yych == 't') goto yy502;
      +	goto yy358;
      +yy489:
      +	yych = *++p;
      +	if (yych == 'S') goto yy503;
      +	if (yych == 's') goto yy503;
      +	goto yy358;
      +yy490:
      +	yych = *++p;
      +	if (yych == 'O') goto yy504;
      +	if (yych == 'o') goto yy504;
      +	goto yy358;
      +yy491:
      +	yych = *++p;
      +	if (yych == 'Q') goto yy505;
      +	if (yych == 'q') goto yy505;
      +	goto yy358;
      +yy492:
      +	yych = *++p;
      +	if (yych == 'R') goto yy392;
      +	if (yych == 'r') goto yy392;
      +	goto yy358;
      +yy493:
      +	yych = *++p;
      +	if (yych == 'O') goto yy506;
      +	if (yych == 'o') goto yy506;
      +	goto yy358;
      +yy494:
      +	yych = *++p;
      +	if (yych == 'L') goto yy503;
      +	if (yych == 'l') goto yy503;
      +	goto yy358;
      +yy495:
      +	yych = *++p;
      +	if (yych == 'G') goto yy392;
      +	if (yych == 'g') goto yy392;
      +	goto yy358;
      +yy496:
      +	yych = *++p;
      +	if (yych == 'S') goto yy507;
      +	if (yych == 's') goto yy507;
      +	goto yy358;
      +yy497:
      +	yych = *++p;
      +	if (yych <= '/') {
      +		if (yych <= 0x1F) {
      +			if (yych <= 0x08) goto yy358;
      +			if (yych <= '\r') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= ' ') goto yy408;
      +			if (yych <= '.') goto yy358;
      +			goto yy410;
      +		}
      +	} else {
      +		if (yych <= 'R') {
      +			if (yych == '>') goto yy408;
      +			goto yy358;
      +		} else {
      +			if (yych <= 'S') goto yy507;
      +			if (yych == 's') goto yy507;
      +			goto yy358;
      +		}
      +	}
      +yy498:
      +	yych = *++p;
      +	if (yych == 'T') goto yy508;
      +	if (yych == 't') goto yy508;
      +	goto yy358;
      +yy499:
      +	yych = *++p;
      +	if (yych == 'M') goto yy509;
      +	if (yych == 'm') goto yy509;
      +	goto yy358;
      +yy500:
      +	yych = *++p;
      +	if (yych == 'T') goto yy451;
      +	if (yych == 't') goto yy451;
      +	goto yy358;
      +yy501:
      +	yych = *++p;
      +	if (yych == 'R') goto yy432;
      +	if (yych == 'r') goto yy432;
      +	goto yy358;
      +yy502:
      +	yych = *++p;
      +	if (yych == 'A') goto yy510;
      +	if (yych == 'a') goto yy510;
      +	goto yy358;
      +yy503:
      +	yych = *++p;
      +	if (yych == 'S') goto yy392;
      +	if (yych == 's') goto yy392;
      +	goto yy358;
      +yy504:
      +	yych = *++p;
      +	if (yych == 'N') goto yy486;
      +	if (yych == 'n') goto yy486;
      +	goto yy358;
      +yy505:
      +	yych = *++p;
      +	if (yych == 'U') goto yy511;
      +	if (yych == 'u') goto yy511;
      +	goto yy358;
      +yy506:
      +	yych = *++p;
      +	if (yych == 'U') goto yy512;
      +	if (yych == 'u') goto yy512;
      +	goto yy358;
      +yy507:
      +	yych = *++p;
      +	if (yych == 'E') goto yy486;
      +	if (yych == 'e') goto yy486;
      +	goto yy358;
      +yy508:
      +	yych = *++p;
      +	if (yych == 'E') goto yy440;
      +	if (yych == 'e') goto yy440;
      +	goto yy358;
      +yy509:
      +	yych = *++p;
      +	if (yych == 'E') goto yy503;
      +	if (yych == 'e') goto yy503;
      +	goto yy358;
      +yy510:
      +	yych = *++p;
      +	if (yych == '[') goto yy513;
      +	goto yy358;
      +yy511:
      +	yych = *++p;
      +	if (yych == 'O') goto yy515;
      +	if (yych == 'o') goto yy515;
      +	goto yy358;
      +yy512:
      +	yych = *++p;
      +	if (yych == 'P') goto yy392;
      +	if (yych == 'p') goto yy392;
      +	goto yy358;
      +yy513:
      +	++p;
      +	{ return 5; }
      +yy515:
      +	yych = *++p;
      +	if (yych == 'T') goto yy463;
      +	if (yych == 't') goto yy463;
      +	goto yy358;
      +}
      +
       }
       
       // Try to match an HTML block tag start line of type 7, returning
       // 7 if successful, 0 if not.
      -bufsize_t _scan_html_block_start_7(const unsigned char *p) {
      +bufsize_t _scan_html_block_start_7(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
       
      -  {
      -    unsigned char yych;
      -    unsigned int yyaccept = 0;
      -    static const unsigned char yybm[] = {
      -        0,   224, 224, 224, 224, 224, 224, 224, 224, 198, 210, 194, 198, 194,
      -        224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
      -        224, 224, 224, 224, 198, 224, 128, 224, 224, 224, 224, 64,  224, 224,
      -        224, 224, 224, 233, 232, 224, 233, 233, 233, 233, 233, 233, 233, 233,
      -        233, 233, 232, 224, 192, 192, 192, 224, 224, 233, 233, 233, 233, 233,
      -        233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
      -        233, 233, 233, 233, 233, 233, 233, 224, 224, 224, 224, 232, 192, 233,
      -        233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
      -        233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 224, 224, 224,
      -        224, 224, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,
      -    };
      -    yych = *p;
      -    if (yych == '<')
      -      goto yy495;
      -    ++p;
      -  yy494 : { return 0; }
      -  yy495:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= '@') {
      -      if (yych != '/')
      -        goto yy494;
      -    } else {
      -      if (yych <= 'Z')
      -        goto yy498;
      -      if (yych <= '`')
      -        goto yy494;
      -      if (yych <= 'z')
      -        goto yy498;
      -      goto yy494;
      -    }
      -    yych = *++p;
      -    if (yych <= '@')
      -      goto yy497;
      -    if (yych <= 'Z')
      -      goto yy500;
      -    if (yych <= '`')
      -      goto yy497;
      -    if (yych <= 'z')
      -      goto yy500;
      -  yy497:
      -    p = marker;
      -    if (yyaccept == 0) {
      -      goto yy494;
      -    } else {
      -      goto yy513;
      -    }
      -  yy498:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 2) {
      -      goto yy502;
      -    }
      -    if (yych <= '=') {
      -      if (yych <= '.') {
      -        if (yych == '-')
      -          goto yy498;
      -        goto yy497;
      -      } else {
      -        if (yych <= '/')
      -          goto yy504;
      -        if (yych <= '9')
      -          goto yy498;
      -        goto yy497;
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '>')
      -          goto yy505;
      -        if (yych <= '@')
      -          goto yy497;
      -        goto yy498;
      -      } else {
      -        if (yych <= '`')
      -          goto yy497;
      -        if (yych <= 'z')
      -          goto yy498;
      -        goto yy497;
      -      }
      -    }
      -  yy500:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '/') {
      -      if (yych <= 0x1F) {
      -        if (yych <= 0x08)
      -          goto yy497;
      -        if (yych <= '\r')
      -          goto yy507;
      -        goto yy497;
      -      } else {
      -        if (yych <= ' ')
      -          goto yy507;
      -        if (yych == '-')
      -          goto yy500;
      -        goto yy497;
      -      }
      -    } else {
      -      if (yych <= '@') {
      -        if (yych <= '9')
      -          goto yy500;
      -        if (yych == '>')
      -          goto yy505;
      -        goto yy497;
      -      } else {
      -        if (yych <= 'Z')
      -          goto yy500;
      -        if (yych <= '`')
      -          goto yy497;
      -        if (yych <= 'z')
      -          goto yy500;
      -        goto yy497;
      -      }
      -    }
      -  yy502:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 2) {
      -      goto yy502;
      -    }
      -    if (yych <= '>') {
      -      if (yych <= '9') {
      -        if (yych != '/')
      -          goto yy497;
      -      } else {
      -        if (yych <= ':')
      -          goto yy509;
      -        if (yych <= '=')
      -          goto yy497;
      -        goto yy505;
      -      }
      -    } else {
      -      if (yych <= '^') {
      -        if (yych <= '@')
      -          goto yy497;
      -        if (yych <= 'Z')
      -          goto yy509;
      -        goto yy497;
      -      } else {
      -        if (yych == '`')
      -          goto yy497;
      -        if (yych <= 'z')
      -          goto yy509;
      -        goto yy497;
      -      }
      -    }
      -  yy504:
      -    yych = *++p;
      -    if (yych != '>')
      -      goto yy497;
      -  yy505:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 4) {
      -      goto yy505;
      -    }
      -    if (yych <= 0x08)
      -      goto yy497;
      -    if (yych <= '\n')
      -      goto yy511;
      -    if (yych <= '\v')
      -      goto yy497;
      -    if (yych <= '\r')
      -      goto yy514;
      -    goto yy497;
      -  yy507:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x1F) {
      -      if (yych <= 0x08)
      -        goto yy497;
      -      if (yych <= '\r')
      -        goto yy507;
      -      goto yy497;
      -    } else {
      -      if (yych <= ' ')
      -        goto yy507;
      -      if (yych == '>')
      -        goto yy505;
      -      goto yy497;
      -    }
      -  yy509:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 8) {
      -      goto yy509;
      -    }
      -    if (yych <= ',') {
      -      if (yych <= '\r') {
      -        if (yych <= 0x08)
      -          goto yy497;
      -        goto yy515;
      -      } else {
      -        if (yych == ' ')
      -          goto yy515;
      -        goto yy497;
      -      }
      -    } else {
      -      if (yych <= '<') {
      -        if (yych <= '/')
      -          goto yy504;
      -        goto yy497;
      -      } else {
      -        if (yych <= '=')
      -          goto yy517;
      -        if (yych <= '>')
      -          goto yy505;
      -        goto yy497;
      -      }
      -    }
      -  yy511:
      -    yyaccept = 1;
      -    marker = ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 4) {
      -      goto yy505;
      -    }
      -    if (yych <= 0x08)
      -      goto yy513;
      -    if (yych <= '\n')
      -      goto yy511;
      -    if (yych <= '\v')
      -      goto yy513;
      -    if (yych <= '\r')
      -      goto yy514;
      -  yy513 : { return 7; }
      -  yy514:
      -    yych = *++p;
      -    goto yy513;
      -  yy515:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '<') {
      -      if (yych <= ' ') {
      -        if (yych <= 0x08)
      -          goto yy497;
      -        if (yych <= '\r')
      -          goto yy515;
      -        if (yych <= 0x1F)
      -          goto yy497;
      -        goto yy515;
      -      } else {
      -        if (yych <= '/') {
      -          if (yych <= '.')
      -            goto yy497;
      -          goto yy504;
      -        } else {
      -          if (yych == ':')
      -            goto yy509;
      -          goto yy497;
      -        }
      -      }
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '=')
      -          goto yy517;
      -        if (yych <= '>')
      -          goto yy505;
      -        if (yych <= '@')
      -          goto yy497;
      -        goto yy509;
      -      } else {
      -        if (yych <= '_') {
      -          if (yych <= '^')
      -            goto yy497;
      -          goto yy509;
      -        } else {
      -          if (yych <= '`')
      -            goto yy497;
      -          if (yych <= 'z')
      -            goto yy509;
      -          goto yy497;
      -        }
      -      }
      -    }
      -  yy517:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 32) {
      -      goto yy519;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '"') {
      -        if (yych <= 0x00)
      -          goto yy497;
      -        if (yych <= ' ')
      -          goto yy517;
      -        goto yy521;
      -      } else {
      -        if (yych <= '\'')
      -          goto yy523;
      -        if (yych <= 0xC1)
      -          goto yy497;
      -        if (yych <= 0xDF)
      -          goto yy525;
      -        goto yy526;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy528;
      -        goto yy527;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy529;
      -        if (yych <= 0xF3)
      -          goto yy530;
      -        if (yych <= 0xF4)
      -          goto yy531;
      -        goto yy497;
      -      }
      -    }
      -  yy519:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 32) {
      -      goto yy519;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '=') {
      -        if (yych <= 0x00)
      -          goto yy497;
      -        if (yych <= ' ')
      -          goto yy502;
      -        goto yy497;
      -      } else {
      -        if (yych <= '>')
      -          goto yy505;
      -        if (yych <= 0xC1)
      -          goto yy497;
      -        if (yych <= 0xDF)
      -          goto yy525;
      -        goto yy526;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy528;
      -        goto yy527;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy529;
      -        if (yych <= 0xF3)
      -          goto yy530;
      -        if (yych <= 0xF4)
      -          goto yy531;
      -        goto yy497;
      -      }
      -    }
      -  yy521:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy521;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy497;
      -        if (yych <= '"')
      -          goto yy532;
      -        goto yy497;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy533;
      -        if (yych <= 0xE0)
      -          goto yy534;
      -        goto yy535;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy536;
      -        if (yych <= 0xEF)
      -          goto yy535;
      -        goto yy537;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy538;
      -        if (yych <= 0xF4)
      -          goto yy539;
      -        goto yy497;
      -      }
      -    }
      -  yy523:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy523;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy497;
      -        if (yych <= '\'')
      -          goto yy532;
      -        goto yy497;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy540;
      -        if (yych <= 0xE0)
      -          goto yy541;
      -        goto yy542;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy543;
      -        if (yych <= 0xEF)
      -          goto yy542;
      -        goto yy544;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy545;
      -        if (yych <= 0xF4)
      -          goto yy546;
      -        goto yy497;
      -      }
      -    }
      -  yy525:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy519;
      -    goto yy497;
      -  yy526:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy525;
      -    goto yy497;
      -  yy527:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy525;
      -    goto yy497;
      -  yy528:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0x9F)
      -      goto yy525;
      -    goto yy497;
      -  yy529:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy527;
      -    goto yy497;
      -  yy530:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy527;
      -    goto yy497;
      -  yy531:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0x8F)
      -      goto yy527;
      -    goto yy497;
      -  yy532:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 2) {
      -      goto yy502;
      -    }
      -    if (yych == '/')
      -      goto yy504;
      -    if (yych == '>')
      -      goto yy505;
      -    goto yy497;
      -  yy533:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy521;
      -    goto yy497;
      -  yy534:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy533;
      -    goto yy497;
      -  yy535:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy533;
      -    goto yy497;
      -  yy536:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0x9F)
      -      goto yy533;
      -    goto yy497;
      -  yy537:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy535;
      -    goto yy497;
      -  yy538:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy535;
      -    goto yy497;
      -  yy539:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0x8F)
      -      goto yy535;
      -    goto yy497;
      -  yy540:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy523;
      -    goto yy497;
      -  yy541:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy540;
      -    goto yy497;
      -  yy542:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy540;
      -    goto yy497;
      -  yy543:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0x9F)
      -      goto yy540;
      -    goto yy497;
      -  yy544:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy542;
      -    goto yy497;
      -  yy545:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0xBF)
      -      goto yy542;
      -    goto yy497;
      -  yy546:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy497;
      -    if (yych <= 0x8F)
      -      goto yy542;
      -    goto yy497;
      -  }
      +{
      +	unsigned char yych;
      +	unsigned int yyaccept = 0;
      +	static const unsigned char yybm[] = {
      +		  0, 224, 224, 224, 224, 224, 224, 224, 
      +		224, 198, 210, 194, 198, 194, 224, 224, 
      +		224, 224, 224, 224, 224, 224, 224, 224, 
      +		224, 224, 224, 224, 224, 224, 224, 224, 
      +		198, 224, 128, 224, 224, 224, 224,  64, 
      +		224, 224, 224, 224, 224, 233, 232, 224, 
      +		233, 233, 233, 233, 233, 233, 233, 233, 
      +		233, 233, 232, 224, 192, 192, 192, 224, 
      +		224, 233, 233, 233, 233, 233, 233, 233, 
      +		233, 233, 233, 233, 233, 233, 233, 233, 
      +		233, 233, 233, 233, 233, 233, 233, 233, 
      +		233, 233, 233, 224, 224, 224, 224, 232, 
      +		192, 233, 233, 233, 233, 233, 233, 233, 
      +		233, 233, 233, 233, 233, 233, 233, 233, 
      +		233, 233, 233, 233, 233, 233, 233, 233, 
      +		233, 233, 233, 224, 224, 224, 224, 224, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych == '<') goto yy520;
      +	++p;
      +yy519:
      +	{ return 0; }
      +yy520:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= '@') {
      +		if (yych != '/') goto yy519;
      +	} else {
      +		if (yych <= 'Z') goto yy523;
      +		if (yych <= '`') goto yy519;
      +		if (yych <= 'z') goto yy523;
      +		goto yy519;
      +	}
      +	yych = *++p;
      +	if (yych <= '@') goto yy522;
      +	if (yych <= 'Z') goto yy525;
      +	if (yych <= '`') goto yy522;
      +	if (yych <= 'z') goto yy525;
      +yy522:
      +	p = marker;
      +	if (yyaccept == 0) {
      +		goto yy519;
      +	} else {
      +		goto yy538;
      +	}
      +yy523:
      +	yych = *++p;
      +	if (yybm[0+yych] & 2) {
      +		goto yy527;
      +	}
      +	if (yych <= '=') {
      +		if (yych <= '.') {
      +			if (yych == '-') goto yy523;
      +			goto yy522;
      +		} else {
      +			if (yych <= '/') goto yy529;
      +			if (yych <= '9') goto yy523;
      +			goto yy522;
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '>') goto yy530;
      +			if (yych <= '@') goto yy522;
      +			goto yy523;
      +		} else {
      +			if (yych <= '`') goto yy522;
      +			if (yych <= 'z') goto yy523;
      +			goto yy522;
      +		}
      +	}
      +yy525:
      +	yych = *++p;
      +	if (yych <= '/') {
      +		if (yych <= 0x1F) {
      +			if (yych <= 0x08) goto yy522;
      +			if (yych <= '\r') goto yy532;
      +			goto yy522;
      +		} else {
      +			if (yych <= ' ') goto yy532;
      +			if (yych == '-') goto yy525;
      +			goto yy522;
      +		}
      +	} else {
      +		if (yych <= '@') {
      +			if (yych <= '9') goto yy525;
      +			if (yych == '>') goto yy530;
      +			goto yy522;
      +		} else {
      +			if (yych <= 'Z') goto yy525;
      +			if (yych <= '`') goto yy522;
      +			if (yych <= 'z') goto yy525;
      +			goto yy522;
      +		}
      +	}
      +yy527:
      +	yych = *++p;
      +	if (yybm[0+yych] & 2) {
      +		goto yy527;
      +	}
      +	if (yych <= '>') {
      +		if (yych <= '9') {
      +			if (yych != '/') goto yy522;
      +		} else {
      +			if (yych <= ':') goto yy534;
      +			if (yych <= '=') goto yy522;
      +			goto yy530;
      +		}
      +	} else {
      +		if (yych <= '^') {
      +			if (yych <= '@') goto yy522;
      +			if (yych <= 'Z') goto yy534;
      +			goto yy522;
      +		} else {
      +			if (yych == '`') goto yy522;
      +			if (yych <= 'z') goto yy534;
      +			goto yy522;
      +		}
      +	}
      +yy529:
      +	yych = *++p;
      +	if (yych != '>') goto yy522;
      +yy530:
      +	yych = *++p;
      +	if (yybm[0+yych] & 4) {
      +		goto yy530;
      +	}
      +	if (yych <= 0x08) goto yy522;
      +	if (yych <= '\n') goto yy536;
      +	if (yych <= '\v') goto yy522;
      +	if (yych <= '\r') goto yy539;
      +	goto yy522;
      +yy532:
      +	yych = *++p;
      +	if (yych <= 0x1F) {
      +		if (yych <= 0x08) goto yy522;
      +		if (yych <= '\r') goto yy532;
      +		goto yy522;
      +	} else {
      +		if (yych <= ' ') goto yy532;
      +		if (yych == '>') goto yy530;
      +		goto yy522;
      +	}
      +yy534:
      +	yych = *++p;
      +	if (yybm[0+yych] & 8) {
      +		goto yy534;
      +	}
      +	if (yych <= ',') {
      +		if (yych <= '\r') {
      +			if (yych <= 0x08) goto yy522;
      +			goto yy540;
      +		} else {
      +			if (yych == ' ') goto yy540;
      +			goto yy522;
      +		}
      +	} else {
      +		if (yych <= '<') {
      +			if (yych <= '/') goto yy529;
      +			goto yy522;
      +		} else {
      +			if (yych <= '=') goto yy542;
      +			if (yych <= '>') goto yy530;
      +			goto yy522;
      +		}
      +	}
      +yy536:
      +	yyaccept = 1;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 4) {
      +		goto yy530;
      +	}
      +	if (yych <= 0x08) goto yy538;
      +	if (yych <= '\n') goto yy536;
      +	if (yych <= '\v') goto yy538;
      +	if (yych <= '\r') goto yy539;
      +yy538:
      +	{ return 7; }
      +yy539:
      +	++p;
      +	goto yy538;
      +yy540:
      +	yych = *++p;
      +	if (yych <= '<') {
      +		if (yych <= ' ') {
      +			if (yych <= 0x08) goto yy522;
      +			if (yych <= '\r') goto yy540;
      +			if (yych <= 0x1F) goto yy522;
      +			goto yy540;
      +		} else {
      +			if (yych <= '/') {
      +				if (yych <= '.') goto yy522;
      +				goto yy529;
      +			} else {
      +				if (yych == ':') goto yy534;
      +				goto yy522;
      +			}
      +		}
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '=') goto yy542;
      +			if (yych <= '>') goto yy530;
      +			if (yych <= '@') goto yy522;
      +			goto yy534;
      +		} else {
      +			if (yych <= '_') {
      +				if (yych <= '^') goto yy522;
      +				goto yy534;
      +			} else {
      +				if (yych <= '`') goto yy522;
      +				if (yych <= 'z') goto yy534;
      +				goto yy522;
      +			}
      +		}
      +	}
      +yy542:
      +	yych = *++p;
      +	if (yybm[0+yych] & 32) {
      +		goto yy544;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '"') {
      +			if (yych <= 0x00) goto yy522;
      +			if (yych <= ' ') goto yy542;
      +			goto yy546;
      +		} else {
      +			if (yych <= '\'') goto yy548;
      +			if (yych <= 0xC1) goto yy522;
      +			if (yych <= 0xDF) goto yy550;
      +			goto yy551;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy553;
      +			goto yy552;
      +		} else {
      +			if (yych <= 0xF0) goto yy554;
      +			if (yych <= 0xF3) goto yy555;
      +			if (yych <= 0xF4) goto yy556;
      +			goto yy522;
      +		}
      +	}
      +yy544:
      +	yych = *++p;
      +	if (yybm[0+yych] & 32) {
      +		goto yy544;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '=') {
      +			if (yych <= 0x00) goto yy522;
      +			if (yych <= ' ') goto yy527;
      +			goto yy522;
      +		} else {
      +			if (yych <= '>') goto yy530;
      +			if (yych <= 0xC1) goto yy522;
      +			if (yych <= 0xDF) goto yy550;
      +			goto yy551;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy553;
      +			goto yy552;
      +		} else {
      +			if (yych <= 0xF0) goto yy554;
      +			if (yych <= 0xF3) goto yy555;
      +			if (yych <= 0xF4) goto yy556;
      +			goto yy522;
      +		}
      +	}
      +yy546:
      +	yych = *++p;
      +	if (yybm[0+yych] & 64) {
      +		goto yy546;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy522;
      +			if (yych <= '"') goto yy557;
      +			goto yy522;
      +		} else {
      +			if (yych <= 0xDF) goto yy558;
      +			if (yych <= 0xE0) goto yy559;
      +			goto yy560;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy561;
      +			if (yych <= 0xEF) goto yy560;
      +			goto yy562;
      +		} else {
      +			if (yych <= 0xF3) goto yy563;
      +			if (yych <= 0xF4) goto yy564;
      +			goto yy522;
      +		}
      +	}
      +yy548:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy548;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy522;
      +			if (yych <= '\'') goto yy557;
      +			goto yy522;
      +		} else {
      +			if (yych <= 0xDF) goto yy565;
      +			if (yych <= 0xE0) goto yy566;
      +			goto yy567;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy568;
      +			if (yych <= 0xEF) goto yy567;
      +			goto yy569;
      +		} else {
      +			if (yych <= 0xF3) goto yy570;
      +			if (yych <= 0xF4) goto yy571;
      +			goto yy522;
      +		}
      +	}
      +yy550:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0xBF) goto yy544;
      +	goto yy522;
      +yy551:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy522;
      +	if (yych <= 0xBF) goto yy550;
      +	goto yy522;
      +yy552:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0xBF) goto yy550;
      +	goto yy522;
      +yy553:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0x9F) goto yy550;
      +	goto yy522;
      +yy554:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy522;
      +	if (yych <= 0xBF) goto yy552;
      +	goto yy522;
      +yy555:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0xBF) goto yy552;
      +	goto yy522;
      +yy556:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0x8F) goto yy552;
      +	goto yy522;
      +yy557:
      +	yych = *++p;
      +	if (yybm[0+yych] & 2) {
      +		goto yy527;
      +	}
      +	if (yych == '/') goto yy529;
      +	if (yych == '>') goto yy530;
      +	goto yy522;
      +yy558:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0xBF) goto yy546;
      +	goto yy522;
      +yy559:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy522;
      +	if (yych <= 0xBF) goto yy558;
      +	goto yy522;
      +yy560:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0xBF) goto yy558;
      +	goto yy522;
      +yy561:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0x9F) goto yy558;
      +	goto yy522;
      +yy562:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy522;
      +	if (yych <= 0xBF) goto yy560;
      +	goto yy522;
      +yy563:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0xBF) goto yy560;
      +	goto yy522;
      +yy564:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0x8F) goto yy560;
      +	goto yy522;
      +yy565:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0xBF) goto yy548;
      +	goto yy522;
      +yy566:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy522;
      +	if (yych <= 0xBF) goto yy565;
      +	goto yy522;
      +yy567:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0xBF) goto yy565;
      +	goto yy522;
      +yy568:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0x9F) goto yy565;
      +	goto yy522;
      +yy569:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy522;
      +	if (yych <= 0xBF) goto yy567;
      +	goto yy522;
      +yy570:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0xBF) goto yy567;
      +	goto yy522;
      +yy571:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy522;
      +	if (yych <= 0x8F) goto yy567;
      +	goto yy522;
      +}
      +
       }
       
       // Try to match an HTML block end line of type 1
      -bufsize_t _scan_html_block_end_1(const unsigned char *p) {
      +bufsize_t _scan_html_block_end_1(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    unsigned int yyaccept = 0;
      -    static const unsigned char yybm[] = {
      -        0,  64, 64, 64, 64, 64, 64,  64, 64, 64, 0,  64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,
      -    };
      -    yych = *p;
      -    if (yych <= 0xDF) {
      -      if (yych <= ';') {
      -        if (yych <= 0x00)
      -          goto yy549;
      -        if (yych != '\n')
      -          goto yy551;
      -      } else {
      -        if (yych <= '<')
      -          goto yy552;
      -        if (yych <= 0x7F)
      -          goto yy551;
      -        if (yych >= 0xC2)
      -          goto yy553;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych <= 0xE0)
      -          goto yy554;
      -        if (yych == 0xED)
      -          goto yy556;
      -        goto yy555;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy557;
      -        if (yych <= 0xF3)
      -          goto yy558;
      -        if (yych <= 0xF4)
      -          goto yy559;
      -      }
      -    }
      -  yy549:
      -    ++p;
      -  yy550 : { return 0; }
      -  yy551:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= '\n') {
      -      if (yych <= 0x00)
      -        goto yy550;
      -      if (yych <= '\t')
      -        goto yy561;
      -      goto yy550;
      -    } else {
      -      if (yych <= 0x7F)
      -        goto yy561;
      -      if (yych <= 0xC1)
      -        goto yy550;
      -      if (yych <= 0xF4)
      -        goto yy561;
      -      goto yy550;
      -    }
      -  yy552:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= '.') {
      -      if (yych <= 0x00)
      -        goto yy550;
      -      if (yych == '\n')
      -        goto yy550;
      -      goto yy561;
      -    } else {
      -      if (yych <= 0x7F) {
      -        if (yych <= '/')
      -          goto yy572;
      -        goto yy561;
      -      } else {
      -        if (yych <= 0xC1)
      -          goto yy550;
      -        if (yych <= 0xF4)
      -          goto yy561;
      -        goto yy550;
      -      }
      -    }
      -  yy553:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy550;
      -    if (yych <= 0xBF)
      -      goto yy560;
      -    goto yy550;
      -  yy554:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x9F)
      -      goto yy550;
      -    if (yych <= 0xBF)
      -      goto yy565;
      -    goto yy550;
      -  yy555:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy550;
      -    if (yych <= 0xBF)
      -      goto yy565;
      -    goto yy550;
      -  yy556:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy550;
      -    if (yych <= 0x9F)
      -      goto yy565;
      -    goto yy550;
      -  yy557:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x8F)
      -      goto yy550;
      -    if (yych <= 0xBF)
      -      goto yy567;
      -    goto yy550;
      -  yy558:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy550;
      -    if (yych <= 0xBF)
      -      goto yy567;
      -    goto yy550;
      -  yy559:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy550;
      -    if (yych <= 0x8F)
      -      goto yy567;
      -    goto yy550;
      -  yy560:
      -    ++p;
      -    yych = *p;
      -  yy561:
      -    if (yybm[0 + yych] & 64) {
      -      goto yy560;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy562;
      -        if (yych <= '<')
      -          goto yy563;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy565;
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        goto yy567;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy568;
      -        if (yych <= 0xEF)
      -          goto yy567;
      -        goto yy569;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy570;
      -        if (yych <= 0xF4)
      -          goto yy571;
      -      }
      -    }
      -  yy562:
      -    p = marker;
      -    if (yyaccept == 0) {
      -      goto yy550;
      -    } else {
      -      goto yy582;
      -    }
      -  yy563:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 0xDF) {
      -      if (yych <= '.') {
      -        if (yych <= 0x00)
      -          goto yy562;
      -        if (yych == '\n')
      -          goto yy562;
      -        goto yy560;
      -      } else {
      -        if (yych <= '/')
      -          goto yy572;
      -        if (yych <= 0x7F)
      -          goto yy560;
      -        if (yych <= 0xC1)
      -          goto yy562;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        if (yych == 0xED)
      -          goto yy568;
      -        goto yy567;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy569;
      -        if (yych <= 0xF3)
      -          goto yy570;
      -        if (yych <= 0xF4)
      -          goto yy571;
      -        goto yy562;
      -      }
      -    }
      -  yy565:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy562;
      -    if (yych <= 0xBF)
      -      goto yy560;
      -    goto yy562;
      -  yy566:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy562;
      -    if (yych <= 0xBF)
      -      goto yy565;
      -    goto yy562;
      -  yy567:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy562;
      -    if (yych <= 0xBF)
      -      goto yy565;
      -    goto yy562;
      -  yy568:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy562;
      -    if (yych <= 0x9F)
      -      goto yy565;
      -    goto yy562;
      -  yy569:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy562;
      -    if (yych <= 0xBF)
      -      goto yy567;
      -    goto yy562;
      -  yy570:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy562;
      -    if (yych <= 0xBF)
      -      goto yy567;
      -    goto yy562;
      -  yy571:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy562;
      -    if (yych <= 0x8F)
      -      goto yy567;
      -    goto yy562;
      -  yy572:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 's') {
      -      if (yych <= 'P') {
      -        if (yych <= '\t') {
      -          if (yych <= 0x00)
      -            goto yy562;
      -          goto yy560;
      -        } else {
      -          if (yych <= '\n')
      -            goto yy562;
      -          if (yych <= 'O')
      -            goto yy560;
      -        }
      -      } else {
      -        if (yych <= 'o') {
      -          if (yych == 'S')
      -            goto yy574;
      -          goto yy560;
      -        } else {
      -          if (yych <= 'p')
      -            goto yy573;
      -          if (yych <= 'r')
      -            goto yy560;
      -          goto yy574;
      -        }
      -      }
      -    } else {
      -      if (yych <= 0xEC) {
      -        if (yych <= 0xC1) {
      -          if (yych <= 0x7F)
      -            goto yy560;
      -          goto yy562;
      -        } else {
      -          if (yych <= 0xDF)
      -            goto yy565;
      -          if (yych <= 0xE0)
      -            goto yy566;
      -          goto yy567;
      -        }
      -      } else {
      -        if (yych <= 0xF0) {
      -          if (yych <= 0xED)
      -            goto yy568;
      -          if (yych <= 0xEF)
      -            goto yy567;
      -          goto yy569;
      -        } else {
      -          if (yych <= 0xF3)
      -            goto yy570;
      -          if (yych <= 0xF4)
      -            goto yy571;
      -          goto yy562;
      -        }
      -      }
      -    }
      -  yy573:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 0xC1) {
      -      if (yych <= 'Q') {
      -        if (yych <= 0x00)
      -          goto yy562;
      -        if (yych == '\n')
      -          goto yy562;
      -        goto yy560;
      -      } else {
      -        if (yych <= 'q') {
      -          if (yych <= 'R')
      -            goto yy575;
      -          goto yy560;
      -        } else {
      -          if (yych <= 'r')
      -            goto yy575;
      -          if (yych <= 0x7F)
      -            goto yy560;
      -          goto yy562;
      -        }
      -      }
      -    } else {
      -      if (yych <= 0xED) {
      -        if (yych <= 0xDF)
      -          goto yy565;
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        if (yych <= 0xEC)
      -          goto yy567;
      -        goto yy568;
      -      } else {
      -        if (yych <= 0xF0) {
      -          if (yych <= 0xEF)
      -            goto yy567;
      -          goto yy569;
      -        } else {
      -          if (yych <= 0xF3)
      -            goto yy570;
      -          if (yych <= 0xF4)
      -            goto yy571;
      -          goto yy562;
      -        }
      -      }
      -    }
      -  yy574:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 't') {
      -      if (yych <= 'C') {
      -        if (yych <= '\t') {
      -          if (yych <= 0x00)
      -            goto yy562;
      -          goto yy560;
      -        } else {
      -          if (yych <= '\n')
      -            goto yy562;
      -          if (yych <= 'B')
      -            goto yy560;
      -          goto yy576;
      -        }
      -      } else {
      -        if (yych <= 'b') {
      -          if (yych == 'T')
      -            goto yy577;
      -          goto yy560;
      -        } else {
      -          if (yych <= 'c')
      -            goto yy576;
      -          if (yych <= 's')
      -            goto yy560;
      -          goto yy577;
      -        }
      -      }
      -    } else {
      -      if (yych <= 0xEC) {
      -        if (yych <= 0xC1) {
      -          if (yych <= 0x7F)
      -            goto yy560;
      -          goto yy562;
      -        } else {
      -          if (yych <= 0xDF)
      -            goto yy565;
      -          if (yych <= 0xE0)
      -            goto yy566;
      -          goto yy567;
      -        }
      -      } else {
      -        if (yych <= 0xF0) {
      -          if (yych <= 0xED)
      -            goto yy568;
      -          if (yych <= 0xEF)
      -            goto yy567;
      -          goto yy569;
      -        } else {
      -          if (yych <= 0xF3)
      -            goto yy570;
      -          if (yych <= 0xF4)
      -            goto yy571;
      -          goto yy562;
      -        }
      -      }
      -    }
      -  yy575:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 0xC1) {
      -      if (yych <= 'D') {
      -        if (yych <= 0x00)
      -          goto yy562;
      -        if (yych == '\n')
      -          goto yy562;
      -        goto yy560;
      -      } else {
      -        if (yych <= 'd') {
      -          if (yych <= 'E')
      -            goto yy578;
      -          goto yy560;
      -        } else {
      -          if (yych <= 'e')
      -            goto yy578;
      -          if (yych <= 0x7F)
      -            goto yy560;
      -          goto yy562;
      -        }
      -      }
      -    } else {
      -      if (yych <= 0xED) {
      -        if (yych <= 0xDF)
      -          goto yy565;
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        if (yych <= 0xEC)
      -          goto yy567;
      -        goto yy568;
      -      } else {
      -        if (yych <= 0xF0) {
      -          if (yych <= 0xEF)
      -            goto yy567;
      -          goto yy569;
      -        } else {
      -          if (yych <= 0xF3)
      -            goto yy570;
      -          if (yych <= 0xF4)
      -            goto yy571;
      -          goto yy562;
      -        }
      -      }
      -    }
      -  yy576:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 0xC1) {
      -      if (yych <= 'Q') {
      -        if (yych <= 0x00)
      -          goto yy562;
      -        if (yych == '\n')
      -          goto yy562;
      -        goto yy560;
      -      } else {
      -        if (yych <= 'q') {
      -          if (yych <= 'R')
      -            goto yy579;
      -          goto yy560;
      -        } else {
      -          if (yych <= 'r')
      -            goto yy579;
      -          if (yych <= 0x7F)
      -            goto yy560;
      -          goto yy562;
      -        }
      -      }
      -    } else {
      -      if (yych <= 0xED) {
      -        if (yych <= 0xDF)
      -          goto yy565;
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        if (yych <= 0xEC)
      -          goto yy567;
      -        goto yy568;
      -      } else {
      -        if (yych <= 0xF0) {
      -          if (yych <= 0xEF)
      -            goto yy567;
      -          goto yy569;
      -        } else {
      -          if (yych <= 0xF3)
      -            goto yy570;
      -          if (yych <= 0xF4)
      -            goto yy571;
      -          goto yy562;
      -        }
      -      }
      -    }
      -  yy577:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 0xC1) {
      -      if (yych <= 'X') {
      -        if (yych <= 0x00)
      -          goto yy562;
      -        if (yych == '\n')
      -          goto yy562;
      -        goto yy560;
      -      } else {
      -        if (yych <= 'x') {
      -          if (yych <= 'Y')
      -            goto yy580;
      -          goto yy560;
      -        } else {
      -          if (yych <= 'y')
      -            goto yy580;
      -          if (yych <= 0x7F)
      -            goto yy560;
      -          goto yy562;
      -        }
      -      }
      -    } else {
      -      if (yych <= 0xED) {
      -        if (yych <= 0xDF)
      -          goto yy565;
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        if (yych <= 0xEC)
      -          goto yy567;
      -        goto yy568;
      -      } else {
      -        if (yych <= 0xF0) {
      -          if (yych <= 0xEF)
      -            goto yy567;
      -          goto yy569;
      -        } else {
      -          if (yych <= 0xF3)
      -            goto yy570;
      -          if (yych <= 0xF4)
      -            goto yy571;
      -          goto yy562;
      -        }
      -      }
      -    }
      -  yy578:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 0xDF) {
      -      if (yych <= '=') {
      -        if (yych <= 0x00)
      -          goto yy562;
      -        if (yych == '\n')
      -          goto yy562;
      -        goto yy560;
      -      } else {
      -        if (yych <= '>')
      -          goto yy581;
      -        if (yych <= 0x7F)
      -          goto yy560;
      -        if (yych <= 0xC1)
      -          goto yy562;
      -        goto yy565;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        if (yych == 0xED)
      -          goto yy568;
      -        goto yy567;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy569;
      -        if (yych <= 0xF3)
      -          goto yy570;
      -        if (yych <= 0xF4)
      -          goto yy571;
      -        goto yy562;
      -      }
      -    }
      -  yy579:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 0xC1) {
      -      if (yych <= 'H') {
      -        if (yych <= 0x00)
      -          goto yy562;
      -        if (yych == '\n')
      -          goto yy562;
      -        goto yy560;
      -      } else {
      -        if (yych <= 'h') {
      -          if (yych <= 'I')
      -            goto yy583;
      -          goto yy560;
      -        } else {
      -          if (yych <= 'i')
      -            goto yy583;
      -          if (yych <= 0x7F)
      -            goto yy560;
      -          goto yy562;
      -        }
      -      }
      -    } else {
      -      if (yych <= 0xED) {
      -        if (yych <= 0xDF)
      -          goto yy565;
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        if (yych <= 0xEC)
      -          goto yy567;
      -        goto yy568;
      -      } else {
      -        if (yych <= 0xF0) {
      -          if (yych <= 0xEF)
      -            goto yy567;
      -          goto yy569;
      -        } else {
      -          if (yych <= 0xF3)
      -            goto yy570;
      -          if (yych <= 0xF4)
      -            goto yy571;
      -          goto yy562;
      -        }
      -      }
      -    }
      -  yy580:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 0xC1) {
      -      if (yych <= 'K') {
      -        if (yych <= 0x00)
      -          goto yy562;
      -        if (yych == '\n')
      -          goto yy562;
      -        goto yy560;
      -      } else {
      -        if (yych <= 'k') {
      -          if (yych <= 'L')
      -            goto yy575;
      -          goto yy560;
      -        } else {
      -          if (yych <= 'l')
      -            goto yy575;
      -          if (yych <= 0x7F)
      -            goto yy560;
      -          goto yy562;
      -        }
      -      }
      -    } else {
      -      if (yych <= 0xED) {
      -        if (yych <= 0xDF)
      -          goto yy565;
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        if (yych <= 0xEC)
      -          goto yy567;
      -        goto yy568;
      -      } else {
      -        if (yych <= 0xF0) {
      -          if (yych <= 0xEF)
      -            goto yy567;
      -          goto yy569;
      -        } else {
      -          if (yych <= 0xF3)
      -            goto yy570;
      -          if (yych <= 0xF4)
      -            goto yy571;
      -          goto yy562;
      -        }
      -      }
      -    }
      -  yy581:
      -    yyaccept = 1;
      -    marker = ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy560;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy582;
      -        if (yych <= '<')
      -          goto yy563;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy565;
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        goto yy567;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy568;
      -        if (yych <= 0xEF)
      -          goto yy567;
      -        goto yy569;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy570;
      -        if (yych <= 0xF4)
      -          goto yy571;
      -      }
      -    }
      -  yy582 : { return (bufsize_t)(p - start); }
      -  yy583:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 0xC1) {
      -      if (yych <= 'O') {
      -        if (yych <= 0x00)
      -          goto yy562;
      -        if (yych == '\n')
      -          goto yy562;
      -        goto yy560;
      -      } else {
      -        if (yych <= 'o') {
      -          if (yych >= 'Q')
      -            goto yy560;
      -        } else {
      -          if (yych <= 'p')
      -            goto yy584;
      -          if (yych <= 0x7F)
      -            goto yy560;
      -          goto yy562;
      -        }
      -      }
      -    } else {
      -      if (yych <= 0xED) {
      -        if (yych <= 0xDF)
      -          goto yy565;
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        if (yych <= 0xEC)
      -          goto yy567;
      -        goto yy568;
      -      } else {
      -        if (yych <= 0xF0) {
      -          if (yych <= 0xEF)
      -            goto yy567;
      -          goto yy569;
      -        } else {
      -          if (yych <= 0xF3)
      -            goto yy570;
      -          if (yych <= 0xF4)
      -            goto yy571;
      -          goto yy562;
      -        }
      -      }
      -    }
      -  yy584:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy563;
      -    }
      -    if (yych <= 0xC1) {
      -      if (yych <= 'S') {
      -        if (yych <= 0x00)
      -          goto yy562;
      -        if (yych == '\n')
      -          goto yy562;
      -        goto yy560;
      -      } else {
      -        if (yych <= 's') {
      -          if (yych <= 'T')
      -            goto yy578;
      -          goto yy560;
      -        } else {
      -          if (yych <= 't')
      -            goto yy578;
      -          if (yych <= 0x7F)
      -            goto yy560;
      -          goto yy562;
      -        }
      -      }
      -    } else {
      -      if (yych <= 0xED) {
      -        if (yych <= 0xDF)
      -          goto yy565;
      -        if (yych <= 0xE0)
      -          goto yy566;
      -        if (yych <= 0xEC)
      -          goto yy567;
      -        goto yy568;
      -      } else {
      -        if (yych <= 0xF0) {
      -          if (yych <= 0xEF)
      -            goto yy567;
      -          goto yy569;
      -        } else {
      -          if (yych <= 0xF3)
      -            goto yy570;
      -          if (yych <= 0xF4)
      -            goto yy571;
      -          goto yy562;
      -        }
      -      }
      -    }
      -  }
      +{
      +	unsigned char yych;
      +	unsigned int yyaccept = 0;
      +	static const unsigned char yybm[] = {
      +		  0,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,   0,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64, 128,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych <= 0xDF) {
      +		if (yych <= ';') {
      +			if (yych <= 0x00) goto yy574;
      +			if (yych != '\n') goto yy576;
      +		} else {
      +			if (yych <= '<') goto yy577;
      +			if (yych <= 0x7F) goto yy576;
      +			if (yych >= 0xC2) goto yy578;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) goto yy579;
      +			if (yych == 0xED) goto yy581;
      +			goto yy580;
      +		} else {
      +			if (yych <= 0xF0) goto yy582;
      +			if (yych <= 0xF3) goto yy583;
      +			if (yych <= 0xF4) goto yy584;
      +		}
      +	}
      +yy574:
      +	++p;
      +yy575:
      +	{ return 0; }
      +yy576:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= '\n') {
      +		if (yych <= 0x00) goto yy575;
      +		if (yych <= '\t') goto yy586;
      +		goto yy575;
      +	} else {
      +		if (yych <= 0x7F) goto yy586;
      +		if (yych <= 0xC1) goto yy575;
      +		if (yych <= 0xF4) goto yy586;
      +		goto yy575;
      +	}
      +yy577:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= '.') {
      +		if (yych <= 0x00) goto yy575;
      +		if (yych == '\n') goto yy575;
      +		goto yy586;
      +	} else {
      +		if (yych <= 0x7F) {
      +			if (yych <= '/') goto yy597;
      +			goto yy586;
      +		} else {
      +			if (yych <= 0xC1) goto yy575;
      +			if (yych <= 0xF4) goto yy586;
      +			goto yy575;
      +		}
      +	}
      +yy578:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy575;
      +	if (yych <= 0xBF) goto yy585;
      +	goto yy575;
      +yy579:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x9F) goto yy575;
      +	if (yych <= 0xBF) goto yy590;
      +	goto yy575;
      +yy580:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy575;
      +	if (yych <= 0xBF) goto yy590;
      +	goto yy575;
      +yy581:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy575;
      +	if (yych <= 0x9F) goto yy590;
      +	goto yy575;
      +yy582:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x8F) goto yy575;
      +	if (yych <= 0xBF) goto yy592;
      +	goto yy575;
      +yy583:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy575;
      +	if (yych <= 0xBF) goto yy592;
      +	goto yy575;
      +yy584:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy575;
      +	if (yych <= 0x8F) goto yy592;
      +	goto yy575;
      +yy585:
      +	yych = *++p;
      +yy586:
      +	if (yybm[0+yych] & 64) {
      +		goto yy585;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy587;
      +			if (yych <= '<') goto yy588;
      +		} else {
      +			if (yych <= 0xDF) goto yy590;
      +			if (yych <= 0xE0) goto yy591;
      +			goto yy592;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy593;
      +			if (yych <= 0xEF) goto yy592;
      +			goto yy594;
      +		} else {
      +			if (yych <= 0xF3) goto yy595;
      +			if (yych <= 0xF4) goto yy596;
      +		}
      +	}
      +yy587:
      +	p = marker;
      +	if (yyaccept == 0) {
      +		goto yy575;
      +	} else {
      +		goto yy607;
      +	}
      +yy588:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 0xDF) {
      +		if (yych <= '.') {
      +			if (yych <= 0x00) goto yy587;
      +			if (yych == '\n') goto yy587;
      +			goto yy585;
      +		} else {
      +			if (yych <= '/') goto yy597;
      +			if (yych <= 0x7F) goto yy585;
      +			if (yych <= 0xC1) goto yy587;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) goto yy591;
      +			if (yych == 0xED) goto yy593;
      +			goto yy592;
      +		} else {
      +			if (yych <= 0xF0) goto yy594;
      +			if (yych <= 0xF3) goto yy595;
      +			if (yych <= 0xF4) goto yy596;
      +			goto yy587;
      +		}
      +	}
      +yy590:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy587;
      +	if (yych <= 0xBF) goto yy585;
      +	goto yy587;
      +yy591:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy587;
      +	if (yych <= 0xBF) goto yy590;
      +	goto yy587;
      +yy592:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy587;
      +	if (yych <= 0xBF) goto yy590;
      +	goto yy587;
      +yy593:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy587;
      +	if (yych <= 0x9F) goto yy590;
      +	goto yy587;
      +yy594:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy587;
      +	if (yych <= 0xBF) goto yy592;
      +	goto yy587;
      +yy595:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy587;
      +	if (yych <= 0xBF) goto yy592;
      +	goto yy587;
      +yy596:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy587;
      +	if (yych <= 0x8F) goto yy592;
      +	goto yy587;
      +yy597:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 's') {
      +		if (yych <= 'P') {
      +			if (yych <= '\t') {
      +				if (yych <= 0x00) goto yy587;
      +				goto yy585;
      +			} else {
      +				if (yych <= '\n') goto yy587;
      +				if (yych <= 'O') goto yy585;
      +			}
      +		} else {
      +			if (yych <= 'o') {
      +				if (yych == 'S') goto yy599;
      +				goto yy585;
      +			} else {
      +				if (yych <= 'p') goto yy598;
      +				if (yych <= 'r') goto yy585;
      +				goto yy599;
      +			}
      +		}
      +	} else {
      +		if (yych <= 0xEC) {
      +			if (yych <= 0xC1) {
      +				if (yych <= 0x7F) goto yy585;
      +				goto yy587;
      +			} else {
      +				if (yych <= 0xDF) goto yy590;
      +				if (yych <= 0xE0) goto yy591;
      +				goto yy592;
      +			}
      +		} else {
      +			if (yych <= 0xF0) {
      +				if (yych <= 0xED) goto yy593;
      +				if (yych <= 0xEF) goto yy592;
      +				goto yy594;
      +			} else {
      +				if (yych <= 0xF3) goto yy595;
      +				if (yych <= 0xF4) goto yy596;
      +				goto yy587;
      +			}
      +		}
      +	}
      +yy598:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 0xC1) {
      +		if (yych <= 'Q') {
      +			if (yych <= 0x00) goto yy587;
      +			if (yych == '\n') goto yy587;
      +			goto yy585;
      +		} else {
      +			if (yych <= 'q') {
      +				if (yych <= 'R') goto yy600;
      +				goto yy585;
      +			} else {
      +				if (yych <= 'r') goto yy600;
      +				if (yych <= 0x7F) goto yy585;
      +				goto yy587;
      +			}
      +		}
      +	} else {
      +		if (yych <= 0xED) {
      +			if (yych <= 0xDF) goto yy590;
      +			if (yych <= 0xE0) goto yy591;
      +			if (yych <= 0xEC) goto yy592;
      +			goto yy593;
      +		} else {
      +			if (yych <= 0xF0) {
      +				if (yych <= 0xEF) goto yy592;
      +				goto yy594;
      +			} else {
      +				if (yych <= 0xF3) goto yy595;
      +				if (yych <= 0xF4) goto yy596;
      +				goto yy587;
      +			}
      +		}
      +	}
      +yy599:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 't') {
      +		if (yych <= 'C') {
      +			if (yych <= '\t') {
      +				if (yych <= 0x00) goto yy587;
      +				goto yy585;
      +			} else {
      +				if (yych <= '\n') goto yy587;
      +				if (yych <= 'B') goto yy585;
      +				goto yy601;
      +			}
      +		} else {
      +			if (yych <= 'b') {
      +				if (yych == 'T') goto yy602;
      +				goto yy585;
      +			} else {
      +				if (yych <= 'c') goto yy601;
      +				if (yych <= 's') goto yy585;
      +				goto yy602;
      +			}
      +		}
      +	} else {
      +		if (yych <= 0xEC) {
      +			if (yych <= 0xC1) {
      +				if (yych <= 0x7F) goto yy585;
      +				goto yy587;
      +			} else {
      +				if (yych <= 0xDF) goto yy590;
      +				if (yych <= 0xE0) goto yy591;
      +				goto yy592;
      +			}
      +		} else {
      +			if (yych <= 0xF0) {
      +				if (yych <= 0xED) goto yy593;
      +				if (yych <= 0xEF) goto yy592;
      +				goto yy594;
      +			} else {
      +				if (yych <= 0xF3) goto yy595;
      +				if (yych <= 0xF4) goto yy596;
      +				goto yy587;
      +			}
      +		}
      +	}
      +yy600:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 0xC1) {
      +		if (yych <= 'D') {
      +			if (yych <= 0x00) goto yy587;
      +			if (yych == '\n') goto yy587;
      +			goto yy585;
      +		} else {
      +			if (yych <= 'd') {
      +				if (yych <= 'E') goto yy603;
      +				goto yy585;
      +			} else {
      +				if (yych <= 'e') goto yy603;
      +				if (yych <= 0x7F) goto yy585;
      +				goto yy587;
      +			}
      +		}
      +	} else {
      +		if (yych <= 0xED) {
      +			if (yych <= 0xDF) goto yy590;
      +			if (yych <= 0xE0) goto yy591;
      +			if (yych <= 0xEC) goto yy592;
      +			goto yy593;
      +		} else {
      +			if (yych <= 0xF0) {
      +				if (yych <= 0xEF) goto yy592;
      +				goto yy594;
      +			} else {
      +				if (yych <= 0xF3) goto yy595;
      +				if (yych <= 0xF4) goto yy596;
      +				goto yy587;
      +			}
      +		}
      +	}
      +yy601:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 0xC1) {
      +		if (yych <= 'Q') {
      +			if (yych <= 0x00) goto yy587;
      +			if (yych == '\n') goto yy587;
      +			goto yy585;
      +		} else {
      +			if (yych <= 'q') {
      +				if (yych <= 'R') goto yy604;
      +				goto yy585;
      +			} else {
      +				if (yych <= 'r') goto yy604;
      +				if (yych <= 0x7F) goto yy585;
      +				goto yy587;
      +			}
      +		}
      +	} else {
      +		if (yych <= 0xED) {
      +			if (yych <= 0xDF) goto yy590;
      +			if (yych <= 0xE0) goto yy591;
      +			if (yych <= 0xEC) goto yy592;
      +			goto yy593;
      +		} else {
      +			if (yych <= 0xF0) {
      +				if (yych <= 0xEF) goto yy592;
      +				goto yy594;
      +			} else {
      +				if (yych <= 0xF3) goto yy595;
      +				if (yych <= 0xF4) goto yy596;
      +				goto yy587;
      +			}
      +		}
      +	}
      +yy602:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 0xC1) {
      +		if (yych <= 'X') {
      +			if (yych <= 0x00) goto yy587;
      +			if (yych == '\n') goto yy587;
      +			goto yy585;
      +		} else {
      +			if (yych <= 'x') {
      +				if (yych <= 'Y') goto yy605;
      +				goto yy585;
      +			} else {
      +				if (yych <= 'y') goto yy605;
      +				if (yych <= 0x7F) goto yy585;
      +				goto yy587;
      +			}
      +		}
      +	} else {
      +		if (yych <= 0xED) {
      +			if (yych <= 0xDF) goto yy590;
      +			if (yych <= 0xE0) goto yy591;
      +			if (yych <= 0xEC) goto yy592;
      +			goto yy593;
      +		} else {
      +			if (yych <= 0xF0) {
      +				if (yych <= 0xEF) goto yy592;
      +				goto yy594;
      +			} else {
      +				if (yych <= 0xF3) goto yy595;
      +				if (yych <= 0xF4) goto yy596;
      +				goto yy587;
      +			}
      +		}
      +	}
      +yy603:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 0xDF) {
      +		if (yych <= '=') {
      +			if (yych <= 0x00) goto yy587;
      +			if (yych == '\n') goto yy587;
      +			goto yy585;
      +		} else {
      +			if (yych <= '>') goto yy606;
      +			if (yych <= 0x7F) goto yy585;
      +			if (yych <= 0xC1) goto yy587;
      +			goto yy590;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) goto yy591;
      +			if (yych == 0xED) goto yy593;
      +			goto yy592;
      +		} else {
      +			if (yych <= 0xF0) goto yy594;
      +			if (yych <= 0xF3) goto yy595;
      +			if (yych <= 0xF4) goto yy596;
      +			goto yy587;
      +		}
      +	}
      +yy604:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 0xC1) {
      +		if (yych <= 'H') {
      +			if (yych <= 0x00) goto yy587;
      +			if (yych == '\n') goto yy587;
      +			goto yy585;
      +		} else {
      +			if (yych <= 'h') {
      +				if (yych <= 'I') goto yy608;
      +				goto yy585;
      +			} else {
      +				if (yych <= 'i') goto yy608;
      +				if (yych <= 0x7F) goto yy585;
      +				goto yy587;
      +			}
      +		}
      +	} else {
      +		if (yych <= 0xED) {
      +			if (yych <= 0xDF) goto yy590;
      +			if (yych <= 0xE0) goto yy591;
      +			if (yych <= 0xEC) goto yy592;
      +			goto yy593;
      +		} else {
      +			if (yych <= 0xF0) {
      +				if (yych <= 0xEF) goto yy592;
      +				goto yy594;
      +			} else {
      +				if (yych <= 0xF3) goto yy595;
      +				if (yych <= 0xF4) goto yy596;
      +				goto yy587;
      +			}
      +		}
      +	}
      +yy605:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 0xC1) {
      +		if (yych <= 'K') {
      +			if (yych <= 0x00) goto yy587;
      +			if (yych == '\n') goto yy587;
      +			goto yy585;
      +		} else {
      +			if (yych <= 'k') {
      +				if (yych <= 'L') goto yy600;
      +				goto yy585;
      +			} else {
      +				if (yych <= 'l') goto yy600;
      +				if (yych <= 0x7F) goto yy585;
      +				goto yy587;
      +			}
      +		}
      +	} else {
      +		if (yych <= 0xED) {
      +			if (yych <= 0xDF) goto yy590;
      +			if (yych <= 0xE0) goto yy591;
      +			if (yych <= 0xEC) goto yy592;
      +			goto yy593;
      +		} else {
      +			if (yych <= 0xF0) {
      +				if (yych <= 0xEF) goto yy592;
      +				goto yy594;
      +			} else {
      +				if (yych <= 0xF3) goto yy595;
      +				if (yych <= 0xF4) goto yy596;
      +				goto yy587;
      +			}
      +		}
      +	}
      +yy606:
      +	yyaccept = 1;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 64) {
      +		goto yy585;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy607;
      +			if (yych <= '<') goto yy588;
      +		} else {
      +			if (yych <= 0xDF) goto yy590;
      +			if (yych <= 0xE0) goto yy591;
      +			goto yy592;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy593;
      +			if (yych <= 0xEF) goto yy592;
      +			goto yy594;
      +		} else {
      +			if (yych <= 0xF3) goto yy595;
      +			if (yych <= 0xF4) goto yy596;
      +		}
      +	}
      +yy607:
      +	{ return (bufsize_t)(p - start); }
      +yy608:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 0xC1) {
      +		if (yych <= 'O') {
      +			if (yych <= 0x00) goto yy587;
      +			if (yych == '\n') goto yy587;
      +			goto yy585;
      +		} else {
      +			if (yych <= 'o') {
      +				if (yych >= 'Q') goto yy585;
      +			} else {
      +				if (yych <= 'p') goto yy609;
      +				if (yych <= 0x7F) goto yy585;
      +				goto yy587;
      +			}
      +		}
      +	} else {
      +		if (yych <= 0xED) {
      +			if (yych <= 0xDF) goto yy590;
      +			if (yych <= 0xE0) goto yy591;
      +			if (yych <= 0xEC) goto yy592;
      +			goto yy593;
      +		} else {
      +			if (yych <= 0xF0) {
      +				if (yych <= 0xEF) goto yy592;
      +				goto yy594;
      +			} else {
      +				if (yych <= 0xF3) goto yy595;
      +				if (yych <= 0xF4) goto yy596;
      +				goto yy587;
      +			}
      +		}
      +	}
      +yy609:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy588;
      +	}
      +	if (yych <= 0xC1) {
      +		if (yych <= 'S') {
      +			if (yych <= 0x00) goto yy587;
      +			if (yych == '\n') goto yy587;
      +			goto yy585;
      +		} else {
      +			if (yych <= 's') {
      +				if (yych <= 'T') goto yy603;
      +				goto yy585;
      +			} else {
      +				if (yych <= 't') goto yy603;
      +				if (yych <= 0x7F) goto yy585;
      +				goto yy587;
      +			}
      +		}
      +	} else {
      +		if (yych <= 0xED) {
      +			if (yych <= 0xDF) goto yy590;
      +			if (yych <= 0xE0) goto yy591;
      +			if (yych <= 0xEC) goto yy592;
      +			goto yy593;
      +		} else {
      +			if (yych <= 0xF0) {
      +				if (yych <= 0xEF) goto yy592;
      +				goto yy594;
      +			} else {
      +				if (yych <= 0xF3) goto yy595;
      +				if (yych <= 0xF4) goto yy596;
      +				goto yy587;
      +			}
      +		}
      +	}
      +}
      +
       }
       
       // Try to match an HTML block end line of type 2
      -bufsize_t _scan_html_block_end_2(const unsigned char *p) {
      +bufsize_t _scan_html_block_end_2(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    unsigned int yyaccept = 0;
      -    static const unsigned char yybm[] = {
      -        0,  64, 64, 64, 64, 64, 64, 64, 64, 64,  0,  64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,
      -    };
      -    yych = *p;
      -    if (yych <= 0xDF) {
      -      if (yych <= ',') {
      -        if (yych <= 0x00)
      -          goto yy587;
      -        if (yych != '\n')
      -          goto yy589;
      -      } else {
      -        if (yych <= '-')
      -          goto yy590;
      -        if (yych <= 0x7F)
      -          goto yy589;
      -        if (yych >= 0xC2)
      -          goto yy591;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych <= 0xE0)
      -          goto yy592;
      -        if (yych == 0xED)
      -          goto yy594;
      -        goto yy593;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy595;
      -        if (yych <= 0xF3)
      -          goto yy596;
      -        if (yych <= 0xF4)
      -          goto yy597;
      -      }
      -    }
      -  yy587:
      -    ++p;
      -  yy588 : { return 0; }
      -  yy589:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= '\n') {
      -      if (yych <= 0x00)
      -        goto yy588;
      -      if (yych <= '\t')
      -        goto yy599;
      -      goto yy588;
      -    } else {
      -      if (yych <= 0x7F)
      -        goto yy599;
      -      if (yych <= 0xC1)
      -        goto yy588;
      -      if (yych <= 0xF4)
      -        goto yy599;
      -      goto yy588;
      -    }
      -  yy590:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yybm[0 + yych] & 128) {
      -      goto yy609;
      -    }
      -    if (yych <= '\n') {
      -      if (yych <= 0x00)
      -        goto yy588;
      -      if (yych <= '\t')
      -        goto yy599;
      -      goto yy588;
      -    } else {
      -      if (yych <= 0x7F)
      -        goto yy599;
      -      if (yych <= 0xC1)
      -        goto yy588;
      -      if (yych <= 0xF4)
      -        goto yy599;
      -      goto yy588;
      -    }
      -  yy591:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy588;
      -    if (yych <= 0xBF)
      -      goto yy598;
      -    goto yy588;
      -  yy592:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x9F)
      -      goto yy588;
      -    if (yych <= 0xBF)
      -      goto yy602;
      -    goto yy588;
      -  yy593:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy588;
      -    if (yych <= 0xBF)
      -      goto yy602;
      -    goto yy588;
      -  yy594:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy588;
      -    if (yych <= 0x9F)
      -      goto yy602;
      -    goto yy588;
      -  yy595:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x8F)
      -      goto yy588;
      -    if (yych <= 0xBF)
      -      goto yy604;
      -    goto yy588;
      -  yy596:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy588;
      -    if (yych <= 0xBF)
      -      goto yy604;
      -    goto yy588;
      -  yy597:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy588;
      -    if (yych <= 0x8F)
      -      goto yy604;
      -    goto yy588;
      -  yy598:
      -    ++p;
      -    yych = *p;
      -  yy599:
      -    if (yybm[0 + yych] & 64) {
      -      goto yy598;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy600;
      -        if (yych <= '-')
      -          goto yy601;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy602;
      -        if (yych <= 0xE0)
      -          goto yy603;
      -        goto yy604;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy605;
      -        if (yych <= 0xEF)
      -          goto yy604;
      -        goto yy606;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy607;
      -        if (yych <= 0xF4)
      -          goto yy608;
      -      }
      -    }
      -  yy600:
      -    p = marker;
      -    if (yyaccept == 0) {
      -      goto yy588;
      -    } else {
      -      goto yy612;
      -    }
      -  yy601:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy598;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy600;
      -        if (yych <= '-')
      -          goto yy609;
      -        goto yy600;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy602;
      -        if (yych <= 0xE0)
      -          goto yy603;
      -        goto yy604;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy605;
      -        if (yych <= 0xEF)
      -          goto yy604;
      -        goto yy606;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy607;
      -        if (yych <= 0xF4)
      -          goto yy608;
      -        goto yy600;
      -      }
      -    }
      -  yy602:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy600;
      -    if (yych <= 0xBF)
      -      goto yy598;
      -    goto yy600;
      -  yy603:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy600;
      -    if (yych <= 0xBF)
      -      goto yy602;
      -    goto yy600;
      -  yy604:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy600;
      -    if (yych <= 0xBF)
      -      goto yy602;
      -    goto yy600;
      -  yy605:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy600;
      -    if (yych <= 0x9F)
      -      goto yy602;
      -    goto yy600;
      -  yy606:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy600;
      -    if (yych <= 0xBF)
      -      goto yy604;
      -    goto yy600;
      -  yy607:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy600;
      -    if (yych <= 0xBF)
      -      goto yy604;
      -    goto yy600;
      -  yy608:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy600;
      -    if (yych <= 0x8F)
      -      goto yy604;
      -    goto yy600;
      -  yy609:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy609;
      -    }
      -    if (yych <= 0xDF) {
      -      if (yych <= '=') {
      -        if (yych <= 0x00)
      -          goto yy600;
      -        if (yych == '\n')
      -          goto yy600;
      -        goto yy598;
      -      } else {
      -        if (yych <= '>')
      -          goto yy611;
      -        if (yych <= 0x7F)
      -          goto yy598;
      -        if (yych <= 0xC1)
      -          goto yy600;
      -        goto yy602;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych <= 0xE0)
      -          goto yy603;
      -        if (yych == 0xED)
      -          goto yy605;
      -        goto yy604;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy606;
      -        if (yych <= 0xF3)
      -          goto yy607;
      -        if (yych <= 0xF4)
      -          goto yy608;
      -        goto yy600;
      -      }
      -    }
      -  yy611:
      -    yyaccept = 1;
      -    marker = ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy598;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy612;
      -        if (yych <= '-')
      -          goto yy601;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy602;
      -        if (yych <= 0xE0)
      -          goto yy603;
      -        goto yy604;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy605;
      -        if (yych <= 0xEF)
      -          goto yy604;
      -        goto yy606;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy607;
      -        if (yych <= 0xF4)
      -          goto yy608;
      -      }
      -    }
      -  yy612 : { return (bufsize_t)(p - start); }
      -  }
      +{
      +	unsigned char yych;
      +	unsigned int yyaccept = 0;
      +	static const unsigned char yybm[] = {
      +		  0,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,   0,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64, 128,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych <= 0xDF) {
      +		if (yych <= ',') {
      +			if (yych <= 0x00) goto yy612;
      +			if (yych != '\n') goto yy614;
      +		} else {
      +			if (yych <= '-') goto yy615;
      +			if (yych <= 0x7F) goto yy614;
      +			if (yych >= 0xC2) goto yy616;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) goto yy617;
      +			if (yych == 0xED) goto yy619;
      +			goto yy618;
      +		} else {
      +			if (yych <= 0xF0) goto yy620;
      +			if (yych <= 0xF3) goto yy621;
      +			if (yych <= 0xF4) goto yy622;
      +		}
      +	}
      +yy612:
      +	++p;
      +yy613:
      +	{ return 0; }
      +yy614:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= '\n') {
      +		if (yych <= 0x00) goto yy613;
      +		if (yych <= '\t') goto yy624;
      +		goto yy613;
      +	} else {
      +		if (yych <= 0x7F) goto yy624;
      +		if (yych <= 0xC1) goto yy613;
      +		if (yych <= 0xF4) goto yy624;
      +		goto yy613;
      +	}
      +yy615:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 128) {
      +		goto yy634;
      +	}
      +	if (yych <= '\n') {
      +		if (yych <= 0x00) goto yy613;
      +		if (yych <= '\t') goto yy624;
      +		goto yy613;
      +	} else {
      +		if (yych <= 0x7F) goto yy624;
      +		if (yych <= 0xC1) goto yy613;
      +		if (yych <= 0xF4) goto yy624;
      +		goto yy613;
      +	}
      +yy616:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy613;
      +	if (yych <= 0xBF) goto yy623;
      +	goto yy613;
      +yy617:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x9F) goto yy613;
      +	if (yych <= 0xBF) goto yy627;
      +	goto yy613;
      +yy618:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy613;
      +	if (yych <= 0xBF) goto yy627;
      +	goto yy613;
      +yy619:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy613;
      +	if (yych <= 0x9F) goto yy627;
      +	goto yy613;
      +yy620:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x8F) goto yy613;
      +	if (yych <= 0xBF) goto yy629;
      +	goto yy613;
      +yy621:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy613;
      +	if (yych <= 0xBF) goto yy629;
      +	goto yy613;
      +yy622:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy613;
      +	if (yych <= 0x8F) goto yy629;
      +	goto yy613;
      +yy623:
      +	yych = *++p;
      +yy624:
      +	if (yybm[0+yych] & 64) {
      +		goto yy623;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy625;
      +			if (yych <= '-') goto yy626;
      +		} else {
      +			if (yych <= 0xDF) goto yy627;
      +			if (yych <= 0xE0) goto yy628;
      +			goto yy629;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy630;
      +			if (yych <= 0xEF) goto yy629;
      +			goto yy631;
      +		} else {
      +			if (yych <= 0xF3) goto yy632;
      +			if (yych <= 0xF4) goto yy633;
      +		}
      +	}
      +yy625:
      +	p = marker;
      +	if (yyaccept == 0) {
      +		goto yy613;
      +	} else {
      +		goto yy637;
      +	}
      +yy626:
      +	yych = *++p;
      +	if (yybm[0+yych] & 64) {
      +		goto yy623;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy625;
      +			if (yych <= '-') goto yy634;
      +			goto yy625;
      +		} else {
      +			if (yych <= 0xDF) goto yy627;
      +			if (yych <= 0xE0) goto yy628;
      +			goto yy629;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy630;
      +			if (yych <= 0xEF) goto yy629;
      +			goto yy631;
      +		} else {
      +			if (yych <= 0xF3) goto yy632;
      +			if (yych <= 0xF4) goto yy633;
      +			goto yy625;
      +		}
      +	}
      +yy627:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy625;
      +	if (yych <= 0xBF) goto yy623;
      +	goto yy625;
      +yy628:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy625;
      +	if (yych <= 0xBF) goto yy627;
      +	goto yy625;
      +yy629:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy625;
      +	if (yych <= 0xBF) goto yy627;
      +	goto yy625;
      +yy630:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy625;
      +	if (yych <= 0x9F) goto yy627;
      +	goto yy625;
      +yy631:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy625;
      +	if (yych <= 0xBF) goto yy629;
      +	goto yy625;
      +yy632:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy625;
      +	if (yych <= 0xBF) goto yy629;
      +	goto yy625;
      +yy633:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy625;
      +	if (yych <= 0x8F) goto yy629;
      +	goto yy625;
      +yy634:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy634;
      +	}
      +	if (yych <= 0xDF) {
      +		if (yych <= '=') {
      +			if (yych <= 0x00) goto yy625;
      +			if (yych == '\n') goto yy625;
      +			goto yy623;
      +		} else {
      +			if (yych <= '>') goto yy636;
      +			if (yych <= 0x7F) goto yy623;
      +			if (yych <= 0xC1) goto yy625;
      +			goto yy627;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) goto yy628;
      +			if (yych == 0xED) goto yy630;
      +			goto yy629;
      +		} else {
      +			if (yych <= 0xF0) goto yy631;
      +			if (yych <= 0xF3) goto yy632;
      +			if (yych <= 0xF4) goto yy633;
      +			goto yy625;
      +		}
      +	}
      +yy636:
      +	yyaccept = 1;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 64) {
      +		goto yy623;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy637;
      +			if (yych <= '-') goto yy626;
      +		} else {
      +			if (yych <= 0xDF) goto yy627;
      +			if (yych <= 0xE0) goto yy628;
      +			goto yy629;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy630;
      +			if (yych <= 0xEF) goto yy629;
      +			goto yy631;
      +		} else {
      +			if (yych <= 0xF3) goto yy632;
      +			if (yych <= 0xF4) goto yy633;
      +		}
      +	}
      +yy637:
      +	{ return (bufsize_t)(p - start); }
      +}
      +
       }
       
       // Try to match an HTML block end line of type 3
      -bufsize_t _scan_html_block_end_3(const unsigned char *p) {
      +bufsize_t _scan_html_block_end_3(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    unsigned int yyaccept = 0;
      -    static const unsigned char yybm[] = {
      -        0,  64, 64, 64, 64, 64, 64, 64, 64, 64,  0,  64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,
      -    };
      -    yych = *p;
      -    if (yych <= 0xDF) {
      -      if (yych <= '>') {
      -        if (yych <= 0x00)
      -          goto yy615;
      -        if (yych != '\n')
      -          goto yy617;
      -      } else {
      -        if (yych <= '?')
      -          goto yy618;
      -        if (yych <= 0x7F)
      -          goto yy617;
      -        if (yych >= 0xC2)
      -          goto yy619;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych <= 0xE0)
      -          goto yy620;
      -        if (yych == 0xED)
      -          goto yy622;
      -        goto yy621;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy623;
      -        if (yych <= 0xF3)
      -          goto yy624;
      -        if (yych <= 0xF4)
      -          goto yy625;
      -      }
      -    }
      -  yy615:
      -    ++p;
      -  yy616 : { return 0; }
      -  yy617:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= '\n') {
      -      if (yych <= 0x00)
      -        goto yy616;
      -      if (yych <= '\t')
      -        goto yy627;
      -      goto yy616;
      -    } else {
      -      if (yych <= 0x7F)
      -        goto yy627;
      -      if (yych <= 0xC1)
      -        goto yy616;
      -      if (yych <= 0xF4)
      -        goto yy627;
      -      goto yy616;
      -    }
      -  yy618:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= '=') {
      -      if (yych <= 0x00)
      -        goto yy616;
      -      if (yych == '\n')
      -        goto yy616;
      -      goto yy627;
      -    } else {
      -      if (yych <= 0x7F) {
      -        if (yych <= '>')
      -          goto yy638;
      -        goto yy627;
      -      } else {
      -        if (yych <= 0xC1)
      -          goto yy616;
      -        if (yych <= 0xF4)
      -          goto yy627;
      -        goto yy616;
      -      }
      -    }
      -  yy619:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy616;
      -    if (yych <= 0xBF)
      -      goto yy626;
      -    goto yy616;
      -  yy620:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x9F)
      -      goto yy616;
      -    if (yych <= 0xBF)
      -      goto yy631;
      -    goto yy616;
      -  yy621:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy616;
      -    if (yych <= 0xBF)
      -      goto yy631;
      -    goto yy616;
      -  yy622:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy616;
      -    if (yych <= 0x9F)
      -      goto yy631;
      -    goto yy616;
      -  yy623:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x8F)
      -      goto yy616;
      -    if (yych <= 0xBF)
      -      goto yy633;
      -    goto yy616;
      -  yy624:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy616;
      -    if (yych <= 0xBF)
      -      goto yy633;
      -    goto yy616;
      -  yy625:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy616;
      -    if (yych <= 0x8F)
      -      goto yy633;
      -    goto yy616;
      -  yy626:
      -    ++p;
      -    yych = *p;
      -  yy627:
      -    if (yybm[0 + yych] & 64) {
      -      goto yy626;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy628;
      -        if (yych <= '?')
      -          goto yy629;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy631;
      -        if (yych <= 0xE0)
      -          goto yy632;
      -        goto yy633;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy634;
      -        if (yych <= 0xEF)
      -          goto yy633;
      -        goto yy635;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy636;
      -        if (yych <= 0xF4)
      -          goto yy637;
      -      }
      -    }
      -  yy628:
      -    p = marker;
      -    if (yyaccept == 0) {
      -      goto yy616;
      -    } else {
      -      goto yy639;
      -    }
      -  yy629:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy629;
      -    }
      -    if (yych <= 0xDF) {
      -      if (yych <= '=') {
      -        if (yych <= 0x00)
      -          goto yy628;
      -        if (yych == '\n')
      -          goto yy628;
      -        goto yy626;
      -      } else {
      -        if (yych <= '>')
      -          goto yy638;
      -        if (yych <= 0x7F)
      -          goto yy626;
      -        if (yych <= 0xC1)
      -          goto yy628;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych <= 0xE0)
      -          goto yy632;
      -        if (yych == 0xED)
      -          goto yy634;
      -        goto yy633;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy635;
      -        if (yych <= 0xF3)
      -          goto yy636;
      -        if (yych <= 0xF4)
      -          goto yy637;
      -        goto yy628;
      -      }
      -    }
      -  yy631:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy628;
      -    if (yych <= 0xBF)
      -      goto yy626;
      -    goto yy628;
      -  yy632:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy628;
      -    if (yych <= 0xBF)
      -      goto yy631;
      -    goto yy628;
      -  yy633:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy628;
      -    if (yych <= 0xBF)
      -      goto yy631;
      -    goto yy628;
      -  yy634:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy628;
      -    if (yych <= 0x9F)
      -      goto yy631;
      -    goto yy628;
      -  yy635:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy628;
      -    if (yych <= 0xBF)
      -      goto yy633;
      -    goto yy628;
      -  yy636:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy628;
      -    if (yych <= 0xBF)
      -      goto yy633;
      -    goto yy628;
      -  yy637:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy628;
      -    if (yych <= 0x8F)
      -      goto yy633;
      -    goto yy628;
      -  yy638:
      -    yyaccept = 1;
      -    marker = ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy626;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy639;
      -        if (yych <= '?')
      -          goto yy629;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy631;
      -        if (yych <= 0xE0)
      -          goto yy632;
      -        goto yy633;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy634;
      -        if (yych <= 0xEF)
      -          goto yy633;
      -        goto yy635;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy636;
      -        if (yych <= 0xF4)
      -          goto yy637;
      -      }
      -    }
      -  yy639 : { return (bufsize_t)(p - start); }
      -  }
      +{
      +	unsigned char yych;
      +	unsigned int yyaccept = 0;
      +	static const unsigned char yybm[] = {
      +		  0,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,   0,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64, 128, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych <= 0xDF) {
      +		if (yych <= '>') {
      +			if (yych <= 0x00) goto yy640;
      +			if (yych != '\n') goto yy642;
      +		} else {
      +			if (yych <= '?') goto yy643;
      +			if (yych <= 0x7F) goto yy642;
      +			if (yych >= 0xC2) goto yy644;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) goto yy645;
      +			if (yych == 0xED) goto yy647;
      +			goto yy646;
      +		} else {
      +			if (yych <= 0xF0) goto yy648;
      +			if (yych <= 0xF3) goto yy649;
      +			if (yych <= 0xF4) goto yy650;
      +		}
      +	}
      +yy640:
      +	++p;
      +yy641:
      +	{ return 0; }
      +yy642:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= '\n') {
      +		if (yych <= 0x00) goto yy641;
      +		if (yych <= '\t') goto yy652;
      +		goto yy641;
      +	} else {
      +		if (yych <= 0x7F) goto yy652;
      +		if (yych <= 0xC1) goto yy641;
      +		if (yych <= 0xF4) goto yy652;
      +		goto yy641;
      +	}
      +yy643:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= '=') {
      +		if (yych <= 0x00) goto yy641;
      +		if (yych == '\n') goto yy641;
      +		goto yy652;
      +	} else {
      +		if (yych <= 0x7F) {
      +			if (yych <= '>') goto yy663;
      +			goto yy652;
      +		} else {
      +			if (yych <= 0xC1) goto yy641;
      +			if (yych <= 0xF4) goto yy652;
      +			goto yy641;
      +		}
      +	}
      +yy644:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy641;
      +	if (yych <= 0xBF) goto yy651;
      +	goto yy641;
      +yy645:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x9F) goto yy641;
      +	if (yych <= 0xBF) goto yy656;
      +	goto yy641;
      +yy646:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy641;
      +	if (yych <= 0xBF) goto yy656;
      +	goto yy641;
      +yy647:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy641;
      +	if (yych <= 0x9F) goto yy656;
      +	goto yy641;
      +yy648:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x8F) goto yy641;
      +	if (yych <= 0xBF) goto yy658;
      +	goto yy641;
      +yy649:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy641;
      +	if (yych <= 0xBF) goto yy658;
      +	goto yy641;
      +yy650:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy641;
      +	if (yych <= 0x8F) goto yy658;
      +	goto yy641;
      +yy651:
      +	yych = *++p;
      +yy652:
      +	if (yybm[0+yych] & 64) {
      +		goto yy651;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy653;
      +			if (yych <= '?') goto yy654;
      +		} else {
      +			if (yych <= 0xDF) goto yy656;
      +			if (yych <= 0xE0) goto yy657;
      +			goto yy658;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy659;
      +			if (yych <= 0xEF) goto yy658;
      +			goto yy660;
      +		} else {
      +			if (yych <= 0xF3) goto yy661;
      +			if (yych <= 0xF4) goto yy662;
      +		}
      +	}
      +yy653:
      +	p = marker;
      +	if (yyaccept == 0) {
      +		goto yy641;
      +	} else {
      +		goto yy664;
      +	}
      +yy654:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy654;
      +	}
      +	if (yych <= 0xDF) {
      +		if (yych <= '=') {
      +			if (yych <= 0x00) goto yy653;
      +			if (yych == '\n') goto yy653;
      +			goto yy651;
      +		} else {
      +			if (yych <= '>') goto yy663;
      +			if (yych <= 0x7F) goto yy651;
      +			if (yych <= 0xC1) goto yy653;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) goto yy657;
      +			if (yych == 0xED) goto yy659;
      +			goto yy658;
      +		} else {
      +			if (yych <= 0xF0) goto yy660;
      +			if (yych <= 0xF3) goto yy661;
      +			if (yych <= 0xF4) goto yy662;
      +			goto yy653;
      +		}
      +	}
      +yy656:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy653;
      +	if (yych <= 0xBF) goto yy651;
      +	goto yy653;
      +yy657:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy653;
      +	if (yych <= 0xBF) goto yy656;
      +	goto yy653;
      +yy658:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy653;
      +	if (yych <= 0xBF) goto yy656;
      +	goto yy653;
      +yy659:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy653;
      +	if (yych <= 0x9F) goto yy656;
      +	goto yy653;
      +yy660:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy653;
      +	if (yych <= 0xBF) goto yy658;
      +	goto yy653;
      +yy661:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy653;
      +	if (yych <= 0xBF) goto yy658;
      +	goto yy653;
      +yy662:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy653;
      +	if (yych <= 0x8F) goto yy658;
      +	goto yy653;
      +yy663:
      +	yyaccept = 1;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 64) {
      +		goto yy651;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy664;
      +			if (yych <= '?') goto yy654;
      +		} else {
      +			if (yych <= 0xDF) goto yy656;
      +			if (yych <= 0xE0) goto yy657;
      +			goto yy658;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy659;
      +			if (yych <= 0xEF) goto yy658;
      +			goto yy660;
      +		} else {
      +			if (yych <= 0xF3) goto yy661;
      +			if (yych <= 0xF4) goto yy662;
      +		}
      +	}
      +yy664:
      +	{ return (bufsize_t)(p - start); }
      +}
      +
       }
       
       // Try to match an HTML block end line of type 4
      -bufsize_t _scan_html_block_end_4(const unsigned char *p) {
      +bufsize_t _scan_html_block_end_4(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    unsigned int yyaccept = 0;
      -    static const unsigned char yybm[] = {
      -        0,   128, 128, 128, 128, 128, 128, 128, 128, 128, 0,   128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 64,  128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
      -        128, 128, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,
      -    };
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy645;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '\n') {
      -        if (yych <= 0x00)
      -          goto yy642;
      -        if (yych <= '\t')
      -          goto yy644;
      -      } else {
      -        if (yych <= 0x7F)
      -          goto yy644;
      -        if (yych <= 0xC1)
      -          goto yy642;
      -        if (yych <= 0xDF)
      -          goto yy648;
      -        goto yy649;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy651;
      -        goto yy650;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy652;
      -        if (yych <= 0xF3)
      -          goto yy653;
      -        if (yych <= 0xF4)
      -          goto yy654;
      -      }
      -    }
      -  yy642:
      -    ++p;
      -  yy643 : { return 0; }
      -  yy644:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= '\n') {
      -      if (yych <= 0x00)
      -        goto yy643;
      -      if (yych <= '\t')
      -        goto yy656;
      -      goto yy643;
      -    } else {
      -      if (yych <= 0x7F)
      -        goto yy656;
      -      if (yych <= 0xC1)
      -        goto yy643;
      -      if (yych <= 0xF4)
      -        goto yy656;
      -      goto yy643;
      -    }
      -  yy645:
      -    yyaccept = 1;
      -    marker = ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy655;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy647;
      -        if (yych <= '>')
      -          goto yy645;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy658;
      -        if (yych <= 0xE0)
      -          goto yy659;
      -        goto yy660;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy661;
      -        if (yych <= 0xEF)
      -          goto yy660;
      -        goto yy662;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy663;
      -        if (yych <= 0xF4)
      -          goto yy664;
      -      }
      -    }
      -  yy647 : { return (bufsize_t)(p - start); }
      -  yy648:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy643;
      -    if (yych <= 0xBF)
      -      goto yy655;
      -    goto yy643;
      -  yy649:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x9F)
      -      goto yy643;
      -    if (yych <= 0xBF)
      -      goto yy658;
      -    goto yy643;
      -  yy650:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy643;
      -    if (yych <= 0xBF)
      -      goto yy658;
      -    goto yy643;
      -  yy651:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy643;
      -    if (yych <= 0x9F)
      -      goto yy658;
      -    goto yy643;
      -  yy652:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x8F)
      -      goto yy643;
      -    if (yych <= 0xBF)
      -      goto yy660;
      -    goto yy643;
      -  yy653:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy643;
      -    if (yych <= 0xBF)
      -      goto yy660;
      -    goto yy643;
      -  yy654:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy643;
      -    if (yych <= 0x8F)
      -      goto yy660;
      -    goto yy643;
      -  yy655:
      -    ++p;
      -    yych = *p;
      -  yy656:
      -    if (yybm[0 + yych] & 128) {
      -      goto yy655;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy657;
      -        if (yych <= '>')
      -          goto yy645;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy658;
      -        if (yych <= 0xE0)
      -          goto yy659;
      -        goto yy660;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy661;
      -        if (yych <= 0xEF)
      -          goto yy660;
      -        goto yy662;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy663;
      -        if (yych <= 0xF4)
      -          goto yy664;
      -      }
      -    }
      -  yy657:
      -    p = marker;
      -    if (yyaccept == 0) {
      -      goto yy643;
      -    } else {
      -      goto yy647;
      -    }
      -  yy658:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy657;
      -    if (yych <= 0xBF)
      -      goto yy655;
      -    goto yy657;
      -  yy659:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy657;
      -    if (yych <= 0xBF)
      -      goto yy658;
      -    goto yy657;
      -  yy660:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy657;
      -    if (yych <= 0xBF)
      -      goto yy658;
      -    goto yy657;
      -  yy661:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy657;
      -    if (yych <= 0x9F)
      -      goto yy658;
      -    goto yy657;
      -  yy662:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy657;
      -    if (yych <= 0xBF)
      -      goto yy660;
      -    goto yy657;
      -  yy663:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy657;
      -    if (yych <= 0xBF)
      -      goto yy660;
      -    goto yy657;
      -  yy664:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy657;
      -    if (yych <= 0x8F)
      -      goto yy660;
      -    goto yy657;
      -  }
      +{
      +	unsigned char yych;
      +	unsigned int yyaccept = 0;
      +	static const unsigned char yybm[] = {
      +		  0, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128,   0, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128,  64, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		128, 128, 128, 128, 128, 128, 128, 128, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yybm[0+yych] & 64) {
      +		goto yy670;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '\n') {
      +			if (yych <= 0x00) goto yy667;
      +			if (yych <= '\t') goto yy669;
      +		} else {
      +			if (yych <= 0x7F) goto yy669;
      +			if (yych <= 0xC1) goto yy667;
      +			if (yych <= 0xDF) goto yy673;
      +			goto yy674;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy676;
      +			goto yy675;
      +		} else {
      +			if (yych <= 0xF0) goto yy677;
      +			if (yych <= 0xF3) goto yy678;
      +			if (yych <= 0xF4) goto yy679;
      +		}
      +	}
      +yy667:
      +	++p;
      +yy668:
      +	{ return 0; }
      +yy669:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= '\n') {
      +		if (yych <= 0x00) goto yy668;
      +		if (yych <= '\t') goto yy681;
      +		goto yy668;
      +	} else {
      +		if (yych <= 0x7F) goto yy681;
      +		if (yych <= 0xC1) goto yy668;
      +		if (yych <= 0xF4) goto yy681;
      +		goto yy668;
      +	}
      +yy670:
      +	yyaccept = 1;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 128) {
      +		goto yy680;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy672;
      +			if (yych <= '>') goto yy670;
      +		} else {
      +			if (yych <= 0xDF) goto yy683;
      +			if (yych <= 0xE0) goto yy684;
      +			goto yy685;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy686;
      +			if (yych <= 0xEF) goto yy685;
      +			goto yy687;
      +		} else {
      +			if (yych <= 0xF3) goto yy688;
      +			if (yych <= 0xF4) goto yy689;
      +		}
      +	}
      +yy672:
      +	{ return (bufsize_t)(p - start); }
      +yy673:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy668;
      +	if (yych <= 0xBF) goto yy680;
      +	goto yy668;
      +yy674:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x9F) goto yy668;
      +	if (yych <= 0xBF) goto yy683;
      +	goto yy668;
      +yy675:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy668;
      +	if (yych <= 0xBF) goto yy683;
      +	goto yy668;
      +yy676:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy668;
      +	if (yych <= 0x9F) goto yy683;
      +	goto yy668;
      +yy677:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x8F) goto yy668;
      +	if (yych <= 0xBF) goto yy685;
      +	goto yy668;
      +yy678:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy668;
      +	if (yych <= 0xBF) goto yy685;
      +	goto yy668;
      +yy679:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy668;
      +	if (yych <= 0x8F) goto yy685;
      +	goto yy668;
      +yy680:
      +	yych = *++p;
      +yy681:
      +	if (yybm[0+yych] & 128) {
      +		goto yy680;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy682;
      +			if (yych <= '>') goto yy670;
      +		} else {
      +			if (yych <= 0xDF) goto yy683;
      +			if (yych <= 0xE0) goto yy684;
      +			goto yy685;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy686;
      +			if (yych <= 0xEF) goto yy685;
      +			goto yy687;
      +		} else {
      +			if (yych <= 0xF3) goto yy688;
      +			if (yych <= 0xF4) goto yy689;
      +		}
      +	}
      +yy682:
      +	p = marker;
      +	if (yyaccept == 0) {
      +		goto yy668;
      +	} else {
      +		goto yy672;
      +	}
      +yy683:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy682;
      +	if (yych <= 0xBF) goto yy680;
      +	goto yy682;
      +yy684:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy682;
      +	if (yych <= 0xBF) goto yy683;
      +	goto yy682;
      +yy685:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy682;
      +	if (yych <= 0xBF) goto yy683;
      +	goto yy682;
      +yy686:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy682;
      +	if (yych <= 0x9F) goto yy683;
      +	goto yy682;
      +yy687:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy682;
      +	if (yych <= 0xBF) goto yy685;
      +	goto yy682;
      +yy688:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy682;
      +	if (yych <= 0xBF) goto yy685;
      +	goto yy682;
      +yy689:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy682;
      +	if (yych <= 0x8F) goto yy685;
      +	goto yy682;
      +}
      +
       }
       
       // Try to match an HTML block end line of type 5
      -bufsize_t _scan_html_block_end_5(const unsigned char *p) {
      +bufsize_t _scan_html_block_end_5(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    unsigned int yyaccept = 0;
      -    static const unsigned char yybm[] = {
      -        0,  64, 64, 64,  64, 64, 64, 64, 64, 64, 0,  64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      -        64, 64, 0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      -        0,  0,  0,  0,
      -    };
      -    yych = *p;
      -    if (yych <= 0xDF) {
      -      if (yych <= '\\') {
      -        if (yych <= 0x00)
      -          goto yy667;
      -        if (yych != '\n')
      -          goto yy669;
      -      } else {
      -        if (yych <= ']')
      -          goto yy670;
      -        if (yych <= 0x7F)
      -          goto yy669;
      -        if (yych >= 0xC2)
      -          goto yy671;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych <= 0xE0)
      -          goto yy672;
      -        if (yych == 0xED)
      -          goto yy674;
      -        goto yy673;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy675;
      -        if (yych <= 0xF3)
      -          goto yy676;
      -        if (yych <= 0xF4)
      -          goto yy677;
      -      }
      -    }
      -  yy667:
      -    ++p;
      -  yy668 : { return 0; }
      -  yy669:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= '\n') {
      -      if (yych <= 0x00)
      -        goto yy668;
      -      if (yych <= '\t')
      -        goto yy679;
      -      goto yy668;
      -    } else {
      -      if (yych <= 0x7F)
      -        goto yy679;
      -      if (yych <= 0xC1)
      -        goto yy668;
      -      if (yych <= 0xF4)
      -        goto yy679;
      -      goto yy668;
      -    }
      -  yy670:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yybm[0 + yych] & 128) {
      -      goto yy689;
      -    }
      -    if (yych <= '\n') {
      -      if (yych <= 0x00)
      -        goto yy668;
      -      if (yych <= '\t')
      -        goto yy679;
      -      goto yy668;
      -    } else {
      -      if (yych <= 0x7F)
      -        goto yy679;
      -      if (yych <= 0xC1)
      -        goto yy668;
      -      if (yych <= 0xF4)
      -        goto yy679;
      -      goto yy668;
      -    }
      -  yy671:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy668;
      -    if (yych <= 0xBF)
      -      goto yy678;
      -    goto yy668;
      -  yy672:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x9F)
      -      goto yy668;
      -    if (yych <= 0xBF)
      -      goto yy682;
      -    goto yy668;
      -  yy673:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy668;
      -    if (yych <= 0xBF)
      -      goto yy682;
      -    goto yy668;
      -  yy674:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy668;
      -    if (yych <= 0x9F)
      -      goto yy682;
      -    goto yy668;
      -  yy675:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x8F)
      -      goto yy668;
      -    if (yych <= 0xBF)
      -      goto yy684;
      -    goto yy668;
      -  yy676:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy668;
      -    if (yych <= 0xBF)
      -      goto yy684;
      -    goto yy668;
      -  yy677:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x7F)
      -      goto yy668;
      -    if (yych <= 0x8F)
      -      goto yy684;
      -    goto yy668;
      -  yy678:
      -    ++p;
      -    yych = *p;
      -  yy679:
      -    if (yybm[0 + yych] & 64) {
      -      goto yy678;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy680;
      -        if (yych <= ']')
      -          goto yy681;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy682;
      -        if (yych <= 0xE0)
      -          goto yy683;
      -        goto yy684;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy685;
      -        if (yych <= 0xEF)
      -          goto yy684;
      -        goto yy686;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy687;
      -        if (yych <= 0xF4)
      -          goto yy688;
      -      }
      -    }
      -  yy680:
      -    p = marker;
      -    if (yyaccept == 0) {
      -      goto yy668;
      -    } else {
      -      goto yy692;
      -    }
      -  yy681:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy678;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy680;
      -        if (yych <= ']')
      -          goto yy689;
      -        goto yy680;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy682;
      -        if (yych <= 0xE0)
      -          goto yy683;
      -        goto yy684;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy685;
      -        if (yych <= 0xEF)
      -          goto yy684;
      -        goto yy686;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy687;
      -        if (yych <= 0xF4)
      -          goto yy688;
      -        goto yy680;
      -      }
      -    }
      -  yy682:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy680;
      -    if (yych <= 0xBF)
      -      goto yy678;
      -    goto yy680;
      -  yy683:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy680;
      -    if (yych <= 0xBF)
      -      goto yy682;
      -    goto yy680;
      -  yy684:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy680;
      -    if (yych <= 0xBF)
      -      goto yy682;
      -    goto yy680;
      -  yy685:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy680;
      -    if (yych <= 0x9F)
      -      goto yy682;
      -    goto yy680;
      -  yy686:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy680;
      -    if (yych <= 0xBF)
      -      goto yy684;
      -    goto yy680;
      -  yy687:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy680;
      -    if (yych <= 0xBF)
      -      goto yy684;
      -    goto yy680;
      -  yy688:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy680;
      -    if (yych <= 0x8F)
      -      goto yy684;
      -    goto yy680;
      -  yy689:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy689;
      -    }
      -    if (yych <= 0xDF) {
      -      if (yych <= '=') {
      -        if (yych <= 0x00)
      -          goto yy680;
      -        if (yych == '\n')
      -          goto yy680;
      -        goto yy678;
      -      } else {
      -        if (yych <= '>')
      -          goto yy691;
      -        if (yych <= 0x7F)
      -          goto yy678;
      -        if (yych <= 0xC1)
      -          goto yy680;
      -        goto yy682;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych <= 0xE0)
      -          goto yy683;
      -        if (yych == 0xED)
      -          goto yy685;
      -        goto yy684;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy686;
      -        if (yych <= 0xF3)
      -          goto yy687;
      -        if (yych <= 0xF4)
      -          goto yy688;
      -        goto yy680;
      -      }
      -    }
      -  yy691:
      -    yyaccept = 1;
      -    marker = ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy678;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= '\n')
      -          goto yy692;
      -        if (yych <= ']')
      -          goto yy681;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy682;
      -        if (yych <= 0xE0)
      -          goto yy683;
      -        goto yy684;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy685;
      -        if (yych <= 0xEF)
      -          goto yy684;
      -        goto yy686;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy687;
      -        if (yych <= 0xF4)
      -          goto yy688;
      -      }
      -    }
      -  yy692 : { return (bufsize_t)(p - start); }
      -  }
      +{
      +	unsigned char yych;
      +	unsigned int yyaccept = 0;
      +	static const unsigned char yybm[] = {
      +		  0,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,   0,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64, 128,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych <= 0xDF) {
      +		if (yych <= '\\') {
      +			if (yych <= 0x00) goto yy692;
      +			if (yych != '\n') goto yy694;
      +		} else {
      +			if (yych <= ']') goto yy695;
      +			if (yych <= 0x7F) goto yy694;
      +			if (yych >= 0xC2) goto yy696;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) goto yy697;
      +			if (yych == 0xED) goto yy699;
      +			goto yy698;
      +		} else {
      +			if (yych <= 0xF0) goto yy700;
      +			if (yych <= 0xF3) goto yy701;
      +			if (yych <= 0xF4) goto yy702;
      +		}
      +	}
      +yy692:
      +	++p;
      +yy693:
      +	{ return 0; }
      +yy694:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= '\n') {
      +		if (yych <= 0x00) goto yy693;
      +		if (yych <= '\t') goto yy704;
      +		goto yy693;
      +	} else {
      +		if (yych <= 0x7F) goto yy704;
      +		if (yych <= 0xC1) goto yy693;
      +		if (yych <= 0xF4) goto yy704;
      +		goto yy693;
      +	}
      +yy695:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 128) {
      +		goto yy714;
      +	}
      +	if (yych <= '\n') {
      +		if (yych <= 0x00) goto yy693;
      +		if (yych <= '\t') goto yy704;
      +		goto yy693;
      +	} else {
      +		if (yych <= 0x7F) goto yy704;
      +		if (yych <= 0xC1) goto yy693;
      +		if (yych <= 0xF4) goto yy704;
      +		goto yy693;
      +	}
      +yy696:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy693;
      +	if (yych <= 0xBF) goto yy703;
      +	goto yy693;
      +yy697:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x9F) goto yy693;
      +	if (yych <= 0xBF) goto yy707;
      +	goto yy693;
      +yy698:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy693;
      +	if (yych <= 0xBF) goto yy707;
      +	goto yy693;
      +yy699:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy693;
      +	if (yych <= 0x9F) goto yy707;
      +	goto yy693;
      +yy700:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x8F) goto yy693;
      +	if (yych <= 0xBF) goto yy709;
      +	goto yy693;
      +yy701:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy693;
      +	if (yych <= 0xBF) goto yy709;
      +	goto yy693;
      +yy702:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x7F) goto yy693;
      +	if (yych <= 0x8F) goto yy709;
      +	goto yy693;
      +yy703:
      +	yych = *++p;
      +yy704:
      +	if (yybm[0+yych] & 64) {
      +		goto yy703;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy705;
      +			if (yych <= ']') goto yy706;
      +		} else {
      +			if (yych <= 0xDF) goto yy707;
      +			if (yych <= 0xE0) goto yy708;
      +			goto yy709;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy710;
      +			if (yych <= 0xEF) goto yy709;
      +			goto yy711;
      +		} else {
      +			if (yych <= 0xF3) goto yy712;
      +			if (yych <= 0xF4) goto yy713;
      +		}
      +	}
      +yy705:
      +	p = marker;
      +	if (yyaccept == 0) {
      +		goto yy693;
      +	} else {
      +		goto yy717;
      +	}
      +yy706:
      +	yych = *++p;
      +	if (yybm[0+yych] & 64) {
      +		goto yy703;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy705;
      +			if (yych <= ']') goto yy714;
      +			goto yy705;
      +		} else {
      +			if (yych <= 0xDF) goto yy707;
      +			if (yych <= 0xE0) goto yy708;
      +			goto yy709;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy710;
      +			if (yych <= 0xEF) goto yy709;
      +			goto yy711;
      +		} else {
      +			if (yych <= 0xF3) goto yy712;
      +			if (yych <= 0xF4) goto yy713;
      +			goto yy705;
      +		}
      +	}
      +yy707:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy705;
      +	if (yych <= 0xBF) goto yy703;
      +	goto yy705;
      +yy708:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy705;
      +	if (yych <= 0xBF) goto yy707;
      +	goto yy705;
      +yy709:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy705;
      +	if (yych <= 0xBF) goto yy707;
      +	goto yy705;
      +yy710:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy705;
      +	if (yych <= 0x9F) goto yy707;
      +	goto yy705;
      +yy711:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy705;
      +	if (yych <= 0xBF) goto yy709;
      +	goto yy705;
      +yy712:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy705;
      +	if (yych <= 0xBF) goto yy709;
      +	goto yy705;
      +yy713:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy705;
      +	if (yych <= 0x8F) goto yy709;
      +	goto yy705;
      +yy714:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy714;
      +	}
      +	if (yych <= 0xDF) {
      +		if (yych <= '=') {
      +			if (yych <= 0x00) goto yy705;
      +			if (yych == '\n') goto yy705;
      +			goto yy703;
      +		} else {
      +			if (yych <= '>') goto yy716;
      +			if (yych <= 0x7F) goto yy703;
      +			if (yych <= 0xC1) goto yy705;
      +			goto yy707;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) goto yy708;
      +			if (yych == 0xED) goto yy710;
      +			goto yy709;
      +		} else {
      +			if (yych <= 0xF0) goto yy711;
      +			if (yych <= 0xF3) goto yy712;
      +			if (yych <= 0xF4) goto yy713;
      +			goto yy705;
      +		}
      +	}
      +yy716:
      +	yyaccept = 1;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 64) {
      +		goto yy703;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= '\n') goto yy717;
      +			if (yych <= ']') goto yy706;
      +		} else {
      +			if (yych <= 0xDF) goto yy707;
      +			if (yych <= 0xE0) goto yy708;
      +			goto yy709;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy710;
      +			if (yych <= 0xEF) goto yy709;
      +			goto yy711;
      +		} else {
      +			if (yych <= 0xF3) goto yy712;
      +			if (yych <= 0xF4) goto yy713;
      +		}
      +	}
      +yy717:
      +	{ return (bufsize_t)(p - start); }
      +}
      +
       }
       
       // Try to match a link title (in single quotes, in double quotes, or
       // in parentheses), returning number of chars matched.  Allow one
       // level of internal nesting (quotes within quotes).
      -bufsize_t _scan_link_title(const unsigned char *p) {
      +bufsize_t _scan_link_title(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    unsigned int yyaccept = 0;
      -    static const unsigned char yybm[] = {
      -        0,   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
      -        208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
      -        208, 208, 208, 208, 208, 208, 192, 208, 208, 208, 208, 144, 80,  80,
      -        208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
      -        208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
      -        208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
      -        208, 208, 208, 208, 208, 208, 208, 208, 32,  208, 208, 208, 208, 208,
      -        208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
      -        208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
      -        208, 208, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,
      -    };
      -    yych = *p;
      -    if (yych <= '&') {
      -      if (yych == '"')
      -        goto yy697;
      -    } else {
      -      if (yych <= '\'')
      -        goto yy698;
      -      if (yych <= '(')
      -        goto yy699;
      -    }
      -    ++p;
      -  yy696 : { return 0; }
      -  yy697:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x00)
      -      goto yy696;
      -    if (yych <= 0x7F)
      -      goto yy701;
      -    if (yych <= 0xC1)
      -      goto yy696;
      -    if (yych <= 0xF4)
      -      goto yy701;
      -    goto yy696;
      -  yy698:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= 0x00)
      -      goto yy696;
      -    if (yych <= 0x7F)
      -      goto yy715;
      -    if (yych <= 0xC1)
      -      goto yy696;
      -    if (yych <= 0xF4)
      -      goto yy715;
      -    goto yy696;
      -  yy699:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych <= '(') {
      -      if (yych <= 0x00)
      -        goto yy696;
      -      if (yych <= '\'')
      -        goto yy728;
      -      goto yy696;
      -    } else {
      -      if (yych <= 0x7F)
      -        goto yy728;
      -      if (yych <= 0xC1)
      -        goto yy696;
      -      if (yych <= 0xF4)
      -        goto yy728;
      -      goto yy696;
      -    }
      -  yy700:
      -    ++p;
      -    yych = *p;
      -  yy701:
      -    if (yybm[0 + yych] & 16) {
      -      goto yy700;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '\\') {
      -        if (yych <= 0x00)
      -          goto yy702;
      -        if (yych <= '"')
      -          goto yy703;
      -        goto yy705;
      -      } else {
      -        if (yych <= 0xC1)
      -          goto yy702;
      -        if (yych <= 0xDF)
      -          goto yy707;
      -        goto yy708;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy710;
      -        goto yy709;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy711;
      -        if (yych <= 0xF3)
      -          goto yy712;
      -        if (yych <= 0xF4)
      -          goto yy713;
      -      }
      -    }
      -  yy702:
      -    p = marker;
      -    if (yyaccept <= 1) {
      -      if (yyaccept == 0) {
      -        goto yy696;
      -      } else {
      -        goto yy704;
      -      }
      -    } else {
      -      if (yyaccept == 2) {
      -        goto yy717;
      -      } else {
      -        goto yy730;
      -      }
      -    }
      -  yy703:
      -    ++p;
      -  yy704 : { return (bufsize_t)(p - start); }
      -  yy705:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 16) {
      -      goto yy700;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '\\') {
      -        if (yych <= 0x00)
      -          goto yy702;
      -        if (yych <= '"')
      -          goto yy740;
      -        goto yy705;
      -      } else {
      -        if (yych <= 0xC1)
      -          goto yy702;
      -        if (yych >= 0xE0)
      -          goto yy708;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy710;
      -        goto yy709;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy711;
      -        if (yych <= 0xF3)
      -          goto yy712;
      -        if (yych <= 0xF4)
      -          goto yy713;
      -        goto yy702;
      -      }
      -    }
      -  yy707:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy700;
      -    goto yy702;
      -  yy708:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy707;
      -    goto yy702;
      -  yy709:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy707;
      -    goto yy702;
      -  yy710:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0x9F)
      -      goto yy707;
      -    goto yy702;
      -  yy711:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy709;
      -    goto yy702;
      -  yy712:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy709;
      -    goto yy702;
      -  yy713:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0x8F)
      -      goto yy709;
      -    goto yy702;
      -  yy714:
      -    ++p;
      -    yych = *p;
      -  yy715:
      -    if (yybm[0 + yych] & 64) {
      -      goto yy714;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '\\') {
      -        if (yych <= 0x00)
      -          goto yy702;
      -        if (yych >= '(')
      -          goto yy718;
      -      } else {
      -        if (yych <= 0xC1)
      -          goto yy702;
      -        if (yych <= 0xDF)
      -          goto yy720;
      -        goto yy721;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy723;
      -        goto yy722;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy724;
      -        if (yych <= 0xF3)
      -          goto yy725;
      -        if (yych <= 0xF4)
      -          goto yy726;
      -        goto yy702;
      -      }
      -    }
      -  yy716:
      -    ++p;
      -  yy717 : { return (bufsize_t)(p - start); }
      -  yy718:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy714;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '\\') {
      -        if (yych <= 0x00)
      -          goto yy702;
      -        if (yych <= '\'')
      -          goto yy741;
      -        goto yy718;
      -      } else {
      -        if (yych <= 0xC1)
      -          goto yy702;
      -        if (yych >= 0xE0)
      -          goto yy721;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy723;
      -        goto yy722;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy724;
      -        if (yych <= 0xF3)
      -          goto yy725;
      -        if (yych <= 0xF4)
      -          goto yy726;
      -        goto yy702;
      -      }
      -    }
      -  yy720:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy714;
      -    goto yy702;
      -  yy721:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy720;
      -    goto yy702;
      -  yy722:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy720;
      -    goto yy702;
      -  yy723:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0x9F)
      -      goto yy720;
      -    goto yy702;
      -  yy724:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy722;
      -    goto yy702;
      -  yy725:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy722;
      -    goto yy702;
      -  yy726:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0x8F)
      -      goto yy722;
      -    goto yy702;
      -  yy727:
      -    ++p;
      -    yych = *p;
      -  yy728:
      -    if (yybm[0 + yych] & 128) {
      -      goto yy727;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '\\') {
      -        if (yych <= '(')
      -          goto yy702;
      -        if (yych >= '*')
      -          goto yy731;
      -      } else {
      -        if (yych <= 0xC1)
      -          goto yy702;
      -        if (yych <= 0xDF)
      -          goto yy733;
      -        goto yy734;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy736;
      -        goto yy735;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy737;
      -        if (yych <= 0xF3)
      -          goto yy738;
      -        if (yych <= 0xF4)
      -          goto yy739;
      -        goto yy702;
      -      }
      -    }
      -  yy729:
      -    ++p;
      -  yy730 : { return (bufsize_t)(p - start); }
      -  yy731:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0xDF) {
      -      if (yych <= '[') {
      -        if (yych <= 0x00)
      -          goto yy702;
      -        if (yych == ')')
      -          goto yy742;
      -        goto yy727;
      -      } else {
      -        if (yych <= '\\')
      -          goto yy731;
      -        if (yych <= 0x7F)
      -          goto yy727;
      -        if (yych <= 0xC1)
      -          goto yy702;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych <= 0xE0)
      -          goto yy734;
      -        if (yych == 0xED)
      -          goto yy736;
      -        goto yy735;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy737;
      -        if (yych <= 0xF3)
      -          goto yy738;
      -        if (yych <= 0xF4)
      -          goto yy739;
      -        goto yy702;
      -      }
      -    }
      -  yy733:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy727;
      -    goto yy702;
      -  yy734:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy733;
      -    goto yy702;
      -  yy735:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy733;
      -    goto yy702;
      -  yy736:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0x9F)
      -      goto yy733;
      -    goto yy702;
      -  yy737:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy735;
      -    goto yy702;
      -  yy738:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0xBF)
      -      goto yy735;
      -    goto yy702;
      -  yy739:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy702;
      -    if (yych <= 0x8F)
      -      goto yy735;
      -    goto yy702;
      -  yy740:
      -    yyaccept = 1;
      -    marker = ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 16) {
      -      goto yy700;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '\\') {
      -        if (yych <= 0x00)
      -          goto yy704;
      -        if (yych <= '"')
      -          goto yy703;
      -        goto yy705;
      -      } else {
      -        if (yych <= 0xC1)
      -          goto yy704;
      -        if (yych <= 0xDF)
      -          goto yy707;
      -        goto yy708;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy710;
      -        goto yy709;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy711;
      -        if (yych <= 0xF3)
      -          goto yy712;
      -        if (yych <= 0xF4)
      -          goto yy713;
      -        goto yy704;
      -      }
      -    }
      -  yy741:
      -    yyaccept = 2;
      -    marker = ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy714;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '\\') {
      -        if (yych <= 0x00)
      -          goto yy717;
      -        if (yych <= '\'')
      -          goto yy716;
      -        goto yy718;
      -      } else {
      -        if (yych <= 0xC1)
      -          goto yy717;
      -        if (yych <= 0xDF)
      -          goto yy720;
      -        goto yy721;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy723;
      -        goto yy722;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy724;
      -        if (yych <= 0xF3)
      -          goto yy725;
      -        if (yych <= 0xF4)
      -          goto yy726;
      -        goto yy717;
      -      }
      -    }
      -  yy742:
      -    yyaccept = 3;
      -    marker = ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy727;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '\\') {
      -        if (yych <= '(')
      -          goto yy730;
      -        if (yych <= ')')
      -          goto yy729;
      -        goto yy731;
      -      } else {
      -        if (yych <= 0xC1)
      -          goto yy730;
      -        if (yych <= 0xDF)
      -          goto yy733;
      -        goto yy734;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy736;
      -        goto yy735;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy737;
      -        if (yych <= 0xF3)
      -          goto yy738;
      -        if (yych <= 0xF4)
      -          goto yy739;
      -        goto yy730;
      -      }
      -    }
      -  }
      +{
      +	unsigned char yych;
      +	unsigned int yyaccept = 0;
      +	static const unsigned char yybm[] = {
      +		  0, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 192, 208, 208, 208, 208, 144, 
      +		 80,  80, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208,  32, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		208, 208, 208, 208, 208, 208, 208, 208, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych <= '&') {
      +		if (yych == '"') goto yy722;
      +	} else {
      +		if (yych <= '\'') goto yy723;
      +		if (yych <= '(') goto yy724;
      +	}
      +	++p;
      +yy721:
      +	{ return 0; }
      +yy722:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x00) goto yy721;
      +	if (yych <= 0x7F) goto yy726;
      +	if (yych <= 0xC1) goto yy721;
      +	if (yych <= 0xF4) goto yy726;
      +	goto yy721;
      +yy723:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= 0x00) goto yy721;
      +	if (yych <= 0x7F) goto yy740;
      +	if (yych <= 0xC1) goto yy721;
      +	if (yych <= 0xF4) goto yy740;
      +	goto yy721;
      +yy724:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych <= '(') {
      +		if (yych <= 0x00) goto yy721;
      +		if (yych <= '\'') goto yy753;
      +		goto yy721;
      +	} else {
      +		if (yych <= 0x7F) goto yy753;
      +		if (yych <= 0xC1) goto yy721;
      +		if (yych <= 0xF4) goto yy753;
      +		goto yy721;
      +	}
      +yy725:
      +	yych = *++p;
      +yy726:
      +	if (yybm[0+yych] & 16) {
      +		goto yy725;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '\\') {
      +			if (yych <= 0x00) goto yy727;
      +			if (yych <= '"') goto yy728;
      +			goto yy730;
      +		} else {
      +			if (yych <= 0xC1) goto yy727;
      +			if (yych <= 0xDF) goto yy732;
      +			goto yy733;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy735;
      +			goto yy734;
      +		} else {
      +			if (yych <= 0xF0) goto yy736;
      +			if (yych <= 0xF3) goto yy737;
      +			if (yych <= 0xF4) goto yy738;
      +		}
      +	}
      +yy727:
      +	p = marker;
      +	if (yyaccept <= 1) {
      +		if (yyaccept == 0) {
      +			goto yy721;
      +		} else {
      +			goto yy729;
      +		}
      +	} else {
      +		if (yyaccept == 2) {
      +			goto yy742;
      +		} else {
      +			goto yy755;
      +		}
      +	}
      +yy728:
      +	++p;
      +yy729:
      +	{ return (bufsize_t)(p - start); }
      +yy730:
      +	yych = *++p;
      +	if (yybm[0+yych] & 16) {
      +		goto yy725;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '\\') {
      +			if (yych <= 0x00) goto yy727;
      +			if (yych <= '"') goto yy765;
      +			goto yy730;
      +		} else {
      +			if (yych <= 0xC1) goto yy727;
      +			if (yych >= 0xE0) goto yy733;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy735;
      +			goto yy734;
      +		} else {
      +			if (yych <= 0xF0) goto yy736;
      +			if (yych <= 0xF3) goto yy737;
      +			if (yych <= 0xF4) goto yy738;
      +			goto yy727;
      +		}
      +	}
      +yy732:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0xBF) goto yy725;
      +	goto yy727;
      +yy733:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy727;
      +	if (yych <= 0xBF) goto yy732;
      +	goto yy727;
      +yy734:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0xBF) goto yy732;
      +	goto yy727;
      +yy735:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0x9F) goto yy732;
      +	goto yy727;
      +yy736:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy727;
      +	if (yych <= 0xBF) goto yy734;
      +	goto yy727;
      +yy737:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0xBF) goto yy734;
      +	goto yy727;
      +yy738:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0x8F) goto yy734;
      +	goto yy727;
      +yy739:
      +	yych = *++p;
      +yy740:
      +	if (yybm[0+yych] & 64) {
      +		goto yy739;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '\\') {
      +			if (yych <= 0x00) goto yy727;
      +			if (yych >= '(') goto yy743;
      +		} else {
      +			if (yych <= 0xC1) goto yy727;
      +			if (yych <= 0xDF) goto yy745;
      +			goto yy746;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy748;
      +			goto yy747;
      +		} else {
      +			if (yych <= 0xF0) goto yy749;
      +			if (yych <= 0xF3) goto yy750;
      +			if (yych <= 0xF4) goto yy751;
      +			goto yy727;
      +		}
      +	}
      +yy741:
      +	++p;
      +yy742:
      +	{ return (bufsize_t)(p - start); }
      +yy743:
      +	yych = *++p;
      +	if (yybm[0+yych] & 64) {
      +		goto yy739;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '\\') {
      +			if (yych <= 0x00) goto yy727;
      +			if (yych <= '\'') goto yy766;
      +			goto yy743;
      +		} else {
      +			if (yych <= 0xC1) goto yy727;
      +			if (yych >= 0xE0) goto yy746;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy748;
      +			goto yy747;
      +		} else {
      +			if (yych <= 0xF0) goto yy749;
      +			if (yych <= 0xF3) goto yy750;
      +			if (yych <= 0xF4) goto yy751;
      +			goto yy727;
      +		}
      +	}
      +yy745:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0xBF) goto yy739;
      +	goto yy727;
      +yy746:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy727;
      +	if (yych <= 0xBF) goto yy745;
      +	goto yy727;
      +yy747:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0xBF) goto yy745;
      +	goto yy727;
      +yy748:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0x9F) goto yy745;
      +	goto yy727;
      +yy749:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy727;
      +	if (yych <= 0xBF) goto yy747;
      +	goto yy727;
      +yy750:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0xBF) goto yy747;
      +	goto yy727;
      +yy751:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0x8F) goto yy747;
      +	goto yy727;
      +yy752:
      +	yych = *++p;
      +yy753:
      +	if (yybm[0+yych] & 128) {
      +		goto yy752;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '\\') {
      +			if (yych <= '(') goto yy727;
      +			if (yych >= '*') goto yy756;
      +		} else {
      +			if (yych <= 0xC1) goto yy727;
      +			if (yych <= 0xDF) goto yy758;
      +			goto yy759;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy761;
      +			goto yy760;
      +		} else {
      +			if (yych <= 0xF0) goto yy762;
      +			if (yych <= 0xF3) goto yy763;
      +			if (yych <= 0xF4) goto yy764;
      +			goto yy727;
      +		}
      +	}
      +yy754:
      +	++p;
      +yy755:
      +	{ return (bufsize_t)(p - start); }
      +yy756:
      +	yych = *++p;
      +	if (yych <= 0xDF) {
      +		if (yych <= '[') {
      +			if (yych <= 0x00) goto yy727;
      +			if (yych == ')') goto yy767;
      +			goto yy752;
      +		} else {
      +			if (yych <= '\\') goto yy756;
      +			if (yych <= 0x7F) goto yy752;
      +			if (yych <= 0xC1) goto yy727;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) goto yy759;
      +			if (yych == 0xED) goto yy761;
      +			goto yy760;
      +		} else {
      +			if (yych <= 0xF0) goto yy762;
      +			if (yych <= 0xF3) goto yy763;
      +			if (yych <= 0xF4) goto yy764;
      +			goto yy727;
      +		}
      +	}
      +yy758:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0xBF) goto yy752;
      +	goto yy727;
      +yy759:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy727;
      +	if (yych <= 0xBF) goto yy758;
      +	goto yy727;
      +yy760:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0xBF) goto yy758;
      +	goto yy727;
      +yy761:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0x9F) goto yy758;
      +	goto yy727;
      +yy762:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy727;
      +	if (yych <= 0xBF) goto yy760;
      +	goto yy727;
      +yy763:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0xBF) goto yy760;
      +	goto yy727;
      +yy764:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy727;
      +	if (yych <= 0x8F) goto yy760;
      +	goto yy727;
      +yy765:
      +	yyaccept = 1;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 16) {
      +		goto yy725;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '\\') {
      +			if (yych <= 0x00) goto yy729;
      +			if (yych <= '"') goto yy728;
      +			goto yy730;
      +		} else {
      +			if (yych <= 0xC1) goto yy729;
      +			if (yych <= 0xDF) goto yy732;
      +			goto yy733;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy735;
      +			goto yy734;
      +		} else {
      +			if (yych <= 0xF0) goto yy736;
      +			if (yych <= 0xF3) goto yy737;
      +			if (yych <= 0xF4) goto yy738;
      +			goto yy729;
      +		}
      +	}
      +yy766:
      +	yyaccept = 2;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 64) {
      +		goto yy739;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '\\') {
      +			if (yych <= 0x00) goto yy742;
      +			if (yych <= '\'') goto yy741;
      +			goto yy743;
      +		} else {
      +			if (yych <= 0xC1) goto yy742;
      +			if (yych <= 0xDF) goto yy745;
      +			goto yy746;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy748;
      +			goto yy747;
      +		} else {
      +			if (yych <= 0xF0) goto yy749;
      +			if (yych <= 0xF3) goto yy750;
      +			if (yych <= 0xF4) goto yy751;
      +			goto yy742;
      +		}
      +	}
      +yy767:
      +	yyaccept = 3;
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 128) {
      +		goto yy752;
      +	}
      +	if (yych <= 0xE0) {
      +		if (yych <= '\\') {
      +			if (yych <= '(') goto yy755;
      +			if (yych <= ')') goto yy754;
      +			goto yy756;
      +		} else {
      +			if (yych <= 0xC1) goto yy755;
      +			if (yych <= 0xDF) goto yy758;
      +			goto yy759;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych == 0xED) goto yy761;
      +			goto yy760;
      +		} else {
      +			if (yych <= 0xF0) goto yy762;
      +			if (yych <= 0xF3) goto yy763;
      +			if (yych <= 0xF4) goto yy764;
      +			goto yy755;
      +		}
      +	}
      +}
      +
       }
       
       // Match space characters, including newlines.
      -bufsize_t _scan_spacechars(const unsigned char *p) {
      -  const unsigned char *start = p;
      +bufsize_t _scan_spacechars(const unsigned char *p)
      +{
      +  const unsigned char *start = p; \
      +
      +{
      +	unsigned char yych;
      +	static const unsigned char yybm[] = {
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0, 128, 128, 128, 128, 128,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		128,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy772;
      +	}
      +	++p;
      +	{ return 0; }
      +yy772:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy772;
      +	}
      +	{ return (bufsize_t)(p - start); }
      +}
       
      -  {
      -    unsigned char yych;
      -    static const unsigned char yybm[] = {
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   128, 0,   0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0,
      -    };
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy747;
      -    }
      -    ++p;
      -    { return 0; }
      -  yy747:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy747;
      -    }
      -    { return (bufsize_t)(p - start); }
      -  }
       }
       
       // Match ATX heading start.
      -bufsize_t _scan_atx_heading_start(const unsigned char *p) {
      +bufsize_t _scan_atx_heading_start(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    static const unsigned char yybm[] = {
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,
      -    };
      -    yych = *p;
      -    if (yych == '#')
      -      goto yy754;
      -    ++p;
      -  yy753 : { return 0; }
      -  yy754:
      -    yych = *(marker = ++p);
      -    if (yybm[0 + yych] & 128) {
      -      goto yy755;
      -    }
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy753;
      -      if (yych <= '\n')
      -        goto yy758;
      -      goto yy753;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy758;
      -      if (yych == '#')
      -        goto yy759;
      -      goto yy753;
      -    }
      -  yy755:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy755;
      -    }
      -  yy757 : { return (bufsize_t)(p - start); }
      -  yy758:
      -    yych = *++p;
      -    goto yy757;
      -  yy759:
      -    yych = *++p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy755;
      -    }
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy760;
      -      if (yych <= '\n')
      -        goto yy758;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy758;
      -      if (yych == '#')
      -        goto yy761;
      -    }
      -  yy760:
      -    p = marker;
      -    goto yy753;
      -  yy761:
      -    yych = *++p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy755;
      -    }
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy760;
      -      if (yych <= '\n')
      -        goto yy758;
      -      goto yy760;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy758;
      -      if (yych != '#')
      -        goto yy760;
      -    }
      -    yych = *++p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy755;
      -    }
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy760;
      -      if (yych <= '\n')
      -        goto yy758;
      -      goto yy760;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy758;
      -      if (yych != '#')
      -        goto yy760;
      -    }
      -    yych = *++p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy755;
      -    }
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy760;
      -      if (yych <= '\n')
      -        goto yy758;
      -      goto yy760;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy758;
      -      if (yych != '#')
      -        goto yy760;
      -    }
      -    ++p;
      -    if (yybm[0 + (yych = *p)] & 128) {
      -      goto yy755;
      -    }
      -    if (yych <= 0x08)
      -      goto yy760;
      -    if (yych <= '\n')
      -      goto yy758;
      -    if (yych == '\r')
      -      goto yy758;
      -    goto yy760;
      -  }
      +{
      +	unsigned char yych;
      +	static const unsigned char yybm[] = {
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0, 128,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		128,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych == '#') goto yy779;
      +	++p;
      +yy778:
      +	{ return 0; }
      +yy779:
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 128) {
      +		goto yy780;
      +	}
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy778;
      +		if (yych <= '\n') goto yy783;
      +		goto yy778;
      +	} else {
      +		if (yych <= '\r') goto yy783;
      +		if (yych == '#') goto yy784;
      +		goto yy778;
      +	}
      +yy780:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy780;
      +	}
      +yy782:
      +	{ return (bufsize_t)(p - start); }
      +yy783:
      +	++p;
      +	goto yy782;
      +yy784:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy780;
      +	}
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy785;
      +		if (yych <= '\n') goto yy783;
      +	} else {
      +		if (yych <= '\r') goto yy783;
      +		if (yych == '#') goto yy786;
      +	}
      +yy785:
      +	p = marker;
      +	goto yy778;
      +yy786:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy780;
      +	}
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy785;
      +		if (yych <= '\n') goto yy783;
      +		goto yy785;
      +	} else {
      +		if (yych <= '\r') goto yy783;
      +		if (yych != '#') goto yy785;
      +	}
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy780;
      +	}
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy785;
      +		if (yych <= '\n') goto yy783;
      +		goto yy785;
      +	} else {
      +		if (yych <= '\r') goto yy783;
      +		if (yych != '#') goto yy785;
      +	}
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy780;
      +	}
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy785;
      +		if (yych <= '\n') goto yy783;
      +		goto yy785;
      +	} else {
      +		if (yych <= '\r') goto yy783;
      +		if (yych != '#') goto yy785;
      +	}
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy780;
      +	}
      +	if (yych <= 0x08) goto yy785;
      +	if (yych <= '\n') goto yy783;
      +	if (yych == '\r') goto yy783;
      +	goto yy785;
      +}
      +
       }
       
       // Match setext heading line.  Return 1 for level-1 heading,
       // 2 for level-2, 0 for no match.
      -bufsize_t _scan_setext_heading_line(const unsigned char *p) {
      +bufsize_t _scan_setext_heading_line(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
       
      -  {
      -    unsigned char yych;
      -    static const unsigned char yybm[] = {
      -        0, 0,  0, 0, 0, 0, 0, 0, 0, 32, 0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
      -        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  32, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
      -        0, 64, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0,
      -        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
      -        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
      -        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
      -        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
      -        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
      -        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
      -        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
      -        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
      -        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0,
      -    };
      -    yych = *p;
      -    if (yych == '-')
      -      goto yy769;
      -    if (yych == '=')
      -      goto yy770;
      -    ++p;
      -  yy768 : { return 0; }
      -  yy769:
      -    yych = *(marker = ++p);
      -    if (yybm[0 + yych] & 64) {
      -      goto yy776;
      -    }
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy768;
      -      if (yych <= '\n')
      -        goto yy772;
      -      goto yy768;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy772;
      -      if (yych == ' ')
      -        goto yy772;
      -      goto yy768;
      -    }
      -  yy770:
      -    yych = *(marker = ++p);
      -    if (yybm[0 + yych] & 128) {
      -      goto yy782;
      -    }
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy768;
      -      if (yych <= '\n')
      -        goto yy779;
      -      goto yy768;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy779;
      -      if (yych == ' ')
      -        goto yy779;
      -      goto yy768;
      -    }
      -  yy771:
      -    ++p;
      -    yych = *p;
      -  yy772:
      -    if (yybm[0 + yych] & 32) {
      -      goto yy771;
      -    }
      -    if (yych <= 0x08)
      -      goto yy773;
      -    if (yych <= '\n')
      -      goto yy774;
      -    if (yych == '\r')
      -      goto yy774;
      -  yy773:
      -    p = marker;
      -    goto yy768;
      -  yy774:
      -    ++p;
      -    { return 2; }
      -  yy776:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 32) {
      -      goto yy771;
      -    }
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy773;
      -      if (yych <= '\n')
      -        goto yy774;
      -      goto yy773;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy774;
      -      if (yych == '-')
      -        goto yy776;
      -      goto yy773;
      -    }
      -  yy778:
      -    ++p;
      -    yych = *p;
      -  yy779:
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy773;
      -      if (yych <= '\t')
      -        goto yy778;
      -      if (yych >= '\v')
      -        goto yy773;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy780;
      -      if (yych == ' ')
      -        goto yy778;
      -      goto yy773;
      -    }
      -  yy780:
      -    ++p;
      -    { return 1; }
      -  yy782:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy782;
      -    }
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy773;
      -      if (yych <= '\t')
      -        goto yy778;
      -      if (yych <= '\n')
      -        goto yy780;
      -      goto yy773;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy780;
      -      if (yych == ' ')
      -        goto yy778;
      -      goto yy773;
      -    }
      -  }
      +{
      +	unsigned char yych;
      +	static const unsigned char yybm[] = {
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,  32,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		 32,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,  64,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0, 128,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych == '-') goto yy794;
      +	if (yych == '=') goto yy795;
      +	++p;
      +yy793:
      +	{ return 0; }
      +yy794:
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 64) {
      +		goto yy801;
      +	}
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy793;
      +		if (yych <= '\n') goto yy797;
      +		goto yy793;
      +	} else {
      +		if (yych <= '\r') goto yy797;
      +		if (yych == ' ') goto yy797;
      +		goto yy793;
      +	}
      +yy795:
      +	yych = *(marker = ++p);
      +	if (yybm[0+yych] & 128) {
      +		goto yy807;
      +	}
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy793;
      +		if (yych <= '\n') goto yy804;
      +		goto yy793;
      +	} else {
      +		if (yych <= '\r') goto yy804;
      +		if (yych == ' ') goto yy804;
      +		goto yy793;
      +	}
      +yy796:
      +	yych = *++p;
      +yy797:
      +	if (yybm[0+yych] & 32) {
      +		goto yy796;
      +	}
      +	if (yych <= 0x08) goto yy798;
      +	if (yych <= '\n') goto yy799;
      +	if (yych == '\r') goto yy799;
      +yy798:
      +	p = marker;
      +	goto yy793;
      +yy799:
      +	++p;
      +	{ return 2; }
      +yy801:
      +	yych = *++p;
      +	if (yybm[0+yych] & 32) {
      +		goto yy796;
      +	}
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy798;
      +		if (yych <= '\n') goto yy799;
      +		goto yy798;
      +	} else {
      +		if (yych <= '\r') goto yy799;
      +		if (yych == '-') goto yy801;
      +		goto yy798;
      +	}
      +yy803:
      +	yych = *++p;
      +yy804:
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy798;
      +		if (yych <= '\t') goto yy803;
      +		if (yych >= '\v') goto yy798;
      +	} else {
      +		if (yych <= '\r') goto yy805;
      +		if (yych == ' ') goto yy803;
      +		goto yy798;
      +	}
      +yy805:
      +	++p;
      +	{ return 1; }
      +yy807:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy807;
      +	}
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy798;
      +		if (yych <= '\t') goto yy803;
      +		if (yych <= '\n') goto yy805;
      +		goto yy798;
      +	} else {
      +		if (yych <= '\r') goto yy805;
      +		if (yych == ' ') goto yy803;
      +		goto yy798;
      +	}
      +}
      +
       }
       
       // Scan an opening code fence.
      -bufsize_t _scan_open_code_fence(const unsigned char *p) {
      +bufsize_t _scan_open_code_fence(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    static const unsigned char yybm[] = {
      -        0,   192, 192, 192, 192, 192, 192, 192, 192, 192, 0,   192, 192, 0,
      -        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
      -        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
      -        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
      -        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
      -        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
      -        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 144, 192,
      -        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
      -        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
      -        224, 192, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
      -        0,   0,   0,   0,
      -    };
      -    yych = *p;
      -    if (yych == '`')
      -      goto yy788;
      -    if (yych == '~')
      -      goto yy789;
      -    ++p;
      -  yy787 : { return 0; }
      -  yy788:
      -    yych = *(marker = ++p);
      -    if (yych == '`')
      -      goto yy790;
      -    goto yy787;
      -  yy789:
      -    yych = *(marker = ++p);
      -    if (yych == '~')
      -      goto yy792;
      -    goto yy787;
      -  yy790:
      -    yych = *++p;
      -    if (yybm[0 + yych] & 16) {
      -      goto yy793;
      -    }
      -  yy791:
      -    p = marker;
      -    goto yy787;
      -  yy792:
      -    yych = *++p;
      -    if (yybm[0 + yych] & 32) {
      -      goto yy795;
      -    }
      -    goto yy791;
      -  yy793:
      -    ++p;
      -    yych = *p;
      -    marker = p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy797;
      -    }
      -    if (yych <= 0xE0) {
      -      if (yych <= '`') {
      -        if (yych <= 0x00)
      -          goto yy791;
      -        if (yych <= '\r')
      -          goto yy799;
      -        goto yy793;
      -      } else {
      -        if (yych <= 0xC1)
      -          goto yy791;
      -        if (yych <= 0xDF)
      -          goto yy801;
      -        goto yy802;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych == 0xED)
      -          goto yy804;
      -        goto yy803;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy805;
      -        if (yych <= 0xF3)
      -          goto yy806;
      -        if (yych <= 0xF4)
      -          goto yy807;
      -        goto yy791;
      -      }
      -    }
      -  yy795:
      -    ++p;
      -    yych = *p;
      -    marker = p;
      -    if (yybm[0 + yych] & 32) {
      -      goto yy795;
      -    }
      -    if (yych <= 0xDF) {
      -      if (yych <= '\f') {
      -        if (yych <= 0x00)
      -          goto yy791;
      -        if (yych == '\n')
      -          goto yy810;
      -        goto yy808;
      -      } else {
      -        if (yych <= '\r')
      -          goto yy810;
      -        if (yych <= 0x7F)
      -          goto yy808;
      -        if (yych <= 0xC1)
      -          goto yy791;
      -        goto yy812;
      -      }
      -    } else {
      -      if (yych <= 0xEF) {
      -        if (yych <= 0xE0)
      -          goto yy813;
      -        if (yych == 0xED)
      -          goto yy815;
      -        goto yy814;
      -      } else {
      -        if (yych <= 0xF0)
      -          goto yy816;
      -        if (yych <= 0xF3)
      -          goto yy817;
      -        if (yych <= 0xF4)
      -          goto yy818;
      -        goto yy791;
      -      }
      -    }
      -  yy797:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy797;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy791;
      -        if (yych >= 0x0E)
      -          goto yy791;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy801;
      -        if (yych <= 0xE0)
      -          goto yy802;
      -        goto yy803;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy804;
      -        if (yych <= 0xEF)
      -          goto yy803;
      -        goto yy805;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy806;
      -        if (yych <= 0xF4)
      -          goto yy807;
      -        goto yy791;
      -      }
      -    }
      -  yy799:
      -    ++p;
      -    p = marker;
      -    { return (bufsize_t)(p - start); }
      -  yy801:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy791;
      -    if (yych <= 0xBF)
      -      goto yy797;
      -    goto yy791;
      -  yy802:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy791;
      -    if (yych <= 0xBF)
      -      goto yy801;
      -    goto yy791;
      -  yy803:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy791;
      -    if (yych <= 0xBF)
      -      goto yy801;
      -    goto yy791;
      -  yy804:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy791;
      -    if (yych <= 0x9F)
      -      goto yy801;
      -    goto yy791;
      -  yy805:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy791;
      -    if (yych <= 0xBF)
      -      goto yy803;
      -    goto yy791;
      -  yy806:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy791;
      -    if (yych <= 0xBF)
      -      goto yy803;
      -    goto yy791;
      -  yy807:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy791;
      -    if (yych <= 0x8F)
      -      goto yy803;
      -    goto yy791;
      -  yy808:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy808;
      -    }
      -    if (yych <= 0xEC) {
      -      if (yych <= 0xC1) {
      -        if (yych <= 0x00)
      -          goto yy791;
      -        if (yych >= 0x0E)
      -          goto yy791;
      -      } else {
      -        if (yych <= 0xDF)
      -          goto yy812;
      -        if (yych <= 0xE0)
      -          goto yy813;
      -        goto yy814;
      -      }
      -    } else {
      -      if (yych <= 0xF0) {
      -        if (yych <= 0xED)
      -          goto yy815;
      -        if (yych <= 0xEF)
      -          goto yy814;
      -        goto yy816;
      -      } else {
      -        if (yych <= 0xF3)
      -          goto yy817;
      -        if (yych <= 0xF4)
      -          goto yy818;
      -        goto yy791;
      -      }
      -    }
      -  yy810:
      -    ++p;
      -    p = marker;
      -    { return (bufsize_t)(p - start); }
      -  yy812:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy791;
      -    if (yych <= 0xBF)
      -      goto yy808;
      -    goto yy791;
      -  yy813:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x9F)
      -      goto yy791;
      -    if (yych <= 0xBF)
      -      goto yy812;
      -    goto yy791;
      -  yy814:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy791;
      -    if (yych <= 0xBF)
      -      goto yy812;
      -    goto yy791;
      -  yy815:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy791;
      -    if (yych <= 0x9F)
      -      goto yy812;
      -    goto yy791;
      -  yy816:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x8F)
      -      goto yy791;
      -    if (yych <= 0xBF)
      -      goto yy814;
      -    goto yy791;
      -  yy817:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy791;
      -    if (yych <= 0xBF)
      -      goto yy814;
      -    goto yy791;
      -  yy818:
      -    ++p;
      -    yych = *p;
      -    if (yych <= 0x7F)
      -      goto yy791;
      -    if (yych <= 0x8F)
      -      goto yy814;
      -    goto yy791;
      -  }
      +{
      +	unsigned char yych;
      +	static const unsigned char yybm[] = {
      +		  0, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192,   0, 192, 192,   0, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		144, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 192, 192, 
      +		192, 192, 192, 192, 192, 192, 224, 192, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych == '`') goto yy813;
      +	if (yych == '~') goto yy814;
      +	++p;
      +yy812:
      +	{ return 0; }
      +yy813:
      +	yych = *(marker = ++p);
      +	if (yych == '`') goto yy815;
      +	goto yy812;
      +yy814:
      +	yych = *(marker = ++p);
      +	if (yych == '~') goto yy817;
      +	goto yy812;
      +yy815:
      +	yych = *++p;
      +	if (yybm[0+yych] & 16) {
      +		goto yy818;
      +	}
      +yy816:
      +	p = marker;
      +	goto yy812;
      +yy817:
      +	yych = *++p;
      +	if (yybm[0+yych] & 32) {
      +		goto yy820;
      +	}
      +	goto yy816;
      +yy818:
      +	yych = *++p;
      +	if (yybm[0+yych] & 16) {
      +		goto yy818;
      +	}
      +	if (yych <= 0xDF) {
      +		if (yych <= '\f') {
      +			if (yych <= 0x00) goto yy816;
      +			if (yych == '\n') {
      +				marker = p;
      +				goto yy824;
      +			}
      +			marker = p;
      +			goto yy822;
      +		} else {
      +			if (yych <= '\r') {
      +				marker = p;
      +				goto yy824;
      +			}
      +			if (yych <= 0x7F) {
      +				marker = p;
      +				goto yy822;
      +			}
      +			if (yych <= 0xC1) goto yy816;
      +			marker = p;
      +			goto yy826;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) {
      +				marker = p;
      +				goto yy827;
      +			}
      +			if (yych == 0xED) {
      +				marker = p;
      +				goto yy829;
      +			}
      +			marker = p;
      +			goto yy828;
      +		} else {
      +			if (yych <= 0xF0) {
      +				marker = p;
      +				goto yy830;
      +			}
      +			if (yych <= 0xF3) {
      +				marker = p;
      +				goto yy831;
      +			}
      +			if (yych <= 0xF4) {
      +				marker = p;
      +				goto yy832;
      +			}
      +			goto yy816;
      +		}
      +	}
      +yy820:
      +	yych = *++p;
      +	if (yybm[0+yych] & 32) {
      +		goto yy820;
      +	}
      +	if (yych <= 0xDF) {
      +		if (yych <= '\f') {
      +			if (yych <= 0x00) goto yy816;
      +			if (yych == '\n') {
      +				marker = p;
      +				goto yy835;
      +			}
      +			marker = p;
      +			goto yy833;
      +		} else {
      +			if (yych <= '\r') {
      +				marker = p;
      +				goto yy835;
      +			}
      +			if (yych <= 0x7F) {
      +				marker = p;
      +				goto yy833;
      +			}
      +			if (yych <= 0xC1) goto yy816;
      +			marker = p;
      +			goto yy837;
      +		}
      +	} else {
      +		if (yych <= 0xEF) {
      +			if (yych <= 0xE0) {
      +				marker = p;
      +				goto yy838;
      +			}
      +			if (yych == 0xED) {
      +				marker = p;
      +				goto yy840;
      +			}
      +			marker = p;
      +			goto yy839;
      +		} else {
      +			if (yych <= 0xF0) {
      +				marker = p;
      +				goto yy841;
      +			}
      +			if (yych <= 0xF3) {
      +				marker = p;
      +				goto yy842;
      +			}
      +			if (yych <= 0xF4) {
      +				marker = p;
      +				goto yy843;
      +			}
      +			goto yy816;
      +		}
      +	}
      +yy822:
      +	yych = *++p;
      +	if (yybm[0+yych] & 64) {
      +		goto yy822;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy816;
      +			if (yych >= 0x0E) goto yy816;
      +		} else {
      +			if (yych <= 0xDF) goto yy826;
      +			if (yych <= 0xE0) goto yy827;
      +			goto yy828;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy829;
      +			if (yych <= 0xEF) goto yy828;
      +			goto yy830;
      +		} else {
      +			if (yych <= 0xF3) goto yy831;
      +			if (yych <= 0xF4) goto yy832;
      +			goto yy816;
      +		}
      +	}
      +yy824:
      +	++p;
      +	p = marker;
      +	{ return (bufsize_t)(p - start); }
      +yy826:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy816;
      +	if (yych <= 0xBF) goto yy822;
      +	goto yy816;
      +yy827:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy816;
      +	if (yych <= 0xBF) goto yy826;
      +	goto yy816;
      +yy828:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy816;
      +	if (yych <= 0xBF) goto yy826;
      +	goto yy816;
      +yy829:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy816;
      +	if (yych <= 0x9F) goto yy826;
      +	goto yy816;
      +yy830:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy816;
      +	if (yych <= 0xBF) goto yy828;
      +	goto yy816;
      +yy831:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy816;
      +	if (yych <= 0xBF) goto yy828;
      +	goto yy816;
      +yy832:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy816;
      +	if (yych <= 0x8F) goto yy828;
      +	goto yy816;
      +yy833:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy833;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= 0x00) goto yy816;
      +			if (yych >= 0x0E) goto yy816;
      +		} else {
      +			if (yych <= 0xDF) goto yy837;
      +			if (yych <= 0xE0) goto yy838;
      +			goto yy839;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy840;
      +			if (yych <= 0xEF) goto yy839;
      +			goto yy841;
      +		} else {
      +			if (yych <= 0xF3) goto yy842;
      +			if (yych <= 0xF4) goto yy843;
      +			goto yy816;
      +		}
      +	}
      +yy835:
      +	++p;
      +	p = marker;
      +	{ return (bufsize_t)(p - start); }
      +yy837:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy816;
      +	if (yych <= 0xBF) goto yy833;
      +	goto yy816;
      +yy838:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy816;
      +	if (yych <= 0xBF) goto yy837;
      +	goto yy816;
      +yy839:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy816;
      +	if (yych <= 0xBF) goto yy837;
      +	goto yy816;
      +yy840:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy816;
      +	if (yych <= 0x9F) goto yy837;
      +	goto yy816;
      +yy841:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy816;
      +	if (yych <= 0xBF) goto yy839;
      +	goto yy816;
      +yy842:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy816;
      +	if (yych <= 0xBF) goto yy839;
      +	goto yy816;
      +yy843:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy816;
      +	if (yych <= 0x8F) goto yy839;
      +	goto yy816;
      +}
      +
       }
       
       // Scan a closing code fence with length at least len.
      -bufsize_t _scan_close_code_fence(const unsigned char *p) {
      +bufsize_t _scan_close_code_fence(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    static const unsigned char yybm[] = {
      -        0, 0, 0, 0, 0, 0, 0, 0, 0,  128, 0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   128, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 32, 0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
      -        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0,
      -    };
      -    yych = *p;
      -    if (yych == '`')
      -      goto yy823;
      -    if (yych == '~')
      -      goto yy824;
      -    ++p;
      -  yy822 : { return 0; }
      -  yy823:
      -    yych = *(marker = ++p);
      -    if (yych == '`')
      -      goto yy825;
      -    goto yy822;
      -  yy824:
      -    yych = *(marker = ++p);
      -    if (yych == '~')
      -      goto yy827;
      -    goto yy822;
      -  yy825:
      -    yych = *++p;
      -    if (yybm[0 + yych] & 32) {
      -      goto yy828;
      -    }
      -  yy826:
      -    p = marker;
      -    goto yy822;
      -  yy827:
      -    yych = *++p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy830;
      -    }
      -    goto yy826;
      -  yy828:
      -    ++p;
      -    yych = *p;
      -    marker = p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy832;
      -    }
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy826;
      -      if (yych <= '\n')
      -        goto yy834;
      -      goto yy826;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy834;
      -      if (yych == '`')
      -        goto yy828;
      -      goto yy826;
      -    }
      -  yy830:
      -    ++p;
      -    yych = *p;
      -    marker = p;
      -    if (yybm[0 + yych] & 64) {
      -      goto yy830;
      -    }
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy826;
      -      if (yych <= '\t')
      -        goto yy836;
      -      if (yych <= '\n')
      -        goto yy838;
      -      goto yy826;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy838;
      -      if (yych == ' ')
      -        goto yy836;
      -      goto yy826;
      -    }
      -  yy832:
      -    ++p;
      -    yych = *p;
      -    if (yybm[0 + yych] & 128) {
      -      goto yy832;
      -    }
      -    if (yych <= 0x08)
      -      goto yy826;
      -    if (yych <= '\n')
      -      goto yy834;
      -    if (yych != '\r')
      -      goto yy826;
      -  yy834:
      -    ++p;
      -    p = marker;
      -    { return (bufsize_t)(p - start); }
      -  yy836:
      -    ++p;
      -    yych = *p;
      -    if (yych <= '\f') {
      -      if (yych <= 0x08)
      -        goto yy826;
      -      if (yych <= '\t')
      -        goto yy836;
      -      if (yych >= '\v')
      -        goto yy826;
      -    } else {
      -      if (yych <= '\r')
      -        goto yy838;
      -      if (yych == ' ')
      -        goto yy836;
      -      goto yy826;
      -    }
      -  yy838:
      -    ++p;
      -    p = marker;
      -    { return (bufsize_t)(p - start); }
      -  }
      +{
      +	unsigned char yych;
      +	static const unsigned char yybm[] = {
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0, 128,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		128,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		 32,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,  64,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych == '`') goto yy848;
      +	if (yych == '~') goto yy849;
      +	++p;
      +yy847:
      +	{ return 0; }
      +yy848:
      +	yych = *(marker = ++p);
      +	if (yych == '`') goto yy850;
      +	goto yy847;
      +yy849:
      +	yych = *(marker = ++p);
      +	if (yych == '~') goto yy852;
      +	goto yy847;
      +yy850:
      +	yych = *++p;
      +	if (yybm[0+yych] & 32) {
      +		goto yy853;
      +	}
      +yy851:
      +	p = marker;
      +	goto yy847;
      +yy852:
      +	yych = *++p;
      +	if (yybm[0+yych] & 64) {
      +		goto yy855;
      +	}
      +	goto yy851;
      +yy853:
      +	yych = *++p;
      +	if (yybm[0+yych] & 32) {
      +		goto yy853;
      +	}
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy851;
      +		if (yych <= '\t') {
      +			marker = p;
      +			goto yy857;
      +		}
      +		if (yych <= '\n') {
      +			marker = p;
      +			goto yy859;
      +		}
      +		goto yy851;
      +	} else {
      +		if (yych <= '\r') {
      +			marker = p;
      +			goto yy859;
      +		}
      +		if (yych == ' ') {
      +			marker = p;
      +			goto yy857;
      +		}
      +		goto yy851;
      +	}
      +yy855:
      +	yych = *++p;
      +	if (yybm[0+yych] & 64) {
      +		goto yy855;
      +	}
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy851;
      +		if (yych <= '\t') {
      +			marker = p;
      +			goto yy861;
      +		}
      +		if (yych <= '\n') {
      +			marker = p;
      +			goto yy863;
      +		}
      +		goto yy851;
      +	} else {
      +		if (yych <= '\r') {
      +			marker = p;
      +			goto yy863;
      +		}
      +		if (yych == ' ') {
      +			marker = p;
      +			goto yy861;
      +		}
      +		goto yy851;
      +	}
      +yy857:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy857;
      +	}
      +	if (yych <= 0x08) goto yy851;
      +	if (yych <= '\n') goto yy859;
      +	if (yych != '\r') goto yy851;
      +yy859:
      +	++p;
      +	p = marker;
      +	{ return (bufsize_t)(p - start); }
      +yy861:
      +	yych = *++p;
      +	if (yych <= '\f') {
      +		if (yych <= 0x08) goto yy851;
      +		if (yych <= '\t') goto yy861;
      +		if (yych >= '\v') goto yy851;
      +	} else {
      +		if (yych <= '\r') goto yy863;
      +		if (yych == ' ') goto yy861;
      +		goto yy851;
      +	}
      +yy863:
      +	++p;
      +	p = marker;
      +	{ return (bufsize_t)(p - start); }
      +}
      +
       }
       
       // Scans an entity.
       // Returns number of chars matched.
      -bufsize_t _scan_entity(const unsigned char *p) {
      +bufsize_t _scan_entity(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    yych = *p;
      -    if (yych == '&')
      -      goto yy844;
      -    ++p;
      -  yy843 : { return 0; }
      -  yy844:
      -    yych = *(marker = ++p);
      -    if (yych <= '@') {
      -      if (yych != '#')
      -        goto yy843;
      -    } else {
      -      if (yych <= 'Z')
      -        goto yy847;
      -      if (yych <= '`')
      -        goto yy843;
      -      if (yych <= 'z')
      -        goto yy847;
      -      goto yy843;
      -    }
      -    yych = *++p;
      -    if (yych <= 'W') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy848;
      -    } else {
      -      if (yych <= 'X')
      -        goto yy849;
      -      if (yych == 'x')
      -        goto yy849;
      -    }
      -  yy846:
      -    p = marker;
      -    goto yy843;
      -  yy847:
      -    yych = *++p;
      -    if (yych <= '@') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy850;
      -      goto yy846;
      -    } else {
      -      if (yych <= 'Z')
      -        goto yy850;
      -      if (yych <= '`')
      -        goto yy846;
      -      if (yych <= 'z')
      -        goto yy850;
      -      goto yy846;
      -    }
      -  yy848:
      -    yych = *++p;
      -    if (yych <= '/')
      -      goto yy846;
      -    if (yych <= '9')
      -      goto yy851;
      -    if (yych == ';')
      -      goto yy852;
      -    goto yy846;
      -  yy849:
      -    yych = *++p;
      -    if (yych <= '@') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy854;
      -      goto yy846;
      -    } else {
      -      if (yych <= 'F')
      -        goto yy854;
      -      if (yych <= '`')
      -        goto yy846;
      -      if (yych <= 'f')
      -        goto yy854;
      -      goto yy846;
      -    }
      -  yy850:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy855;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy855;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'z')
      -          goto yy855;
      -        goto yy846;
      -      }
      -    }
      -  yy851:
      -    yych = *++p;
      -    if (yych <= '/')
      -      goto yy846;
      -    if (yych <= '9')
      -      goto yy856;
      -    if (yych != ';')
      -      goto yy846;
      -  yy852:
      -    ++p;
      -    { return (bufsize_t)(p - start); }
      -  yy854:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy857;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'F') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy857;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'f')
      -          goto yy857;
      -        goto yy846;
      -      }
      -    }
      -  yy855:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy858;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy858;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'z')
      -          goto yy858;
      -        goto yy846;
      -      }
      -    }
      -  yy856:
      -    yych = *++p;
      -    if (yych <= '/')
      -      goto yy846;
      -    if (yych <= '9')
      -      goto yy859;
      -    if (yych == ';')
      -      goto yy852;
      -    goto yy846;
      -  yy857:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy860;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'F') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy860;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'f')
      -          goto yy860;
      -        goto yy846;
      -      }
      -    }
      -  yy858:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy861;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy861;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'z')
      -          goto yy861;
      -        goto yy846;
      -      }
      -    }
      -  yy859:
      -    yych = *++p;
      -    if (yych <= '/')
      -      goto yy846;
      -    if (yych <= '9')
      -      goto yy862;
      -    if (yych == ';')
      -      goto yy852;
      -    goto yy846;
      -  yy860:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy863;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'F') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy863;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'f')
      -          goto yy863;
      -        goto yy846;
      -      }
      -    }
      -  yy861:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy864;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy864;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'z')
      -          goto yy864;
      -        goto yy846;
      -      }
      -    }
      -  yy862:
      -    yych = *++p;
      -    if (yych <= '/')
      -      goto yy846;
      -    if (yych <= '9')
      -      goto yy865;
      -    if (yych == ';')
      -      goto yy852;
      -    goto yy846;
      -  yy863:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy866;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'F') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy866;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'f')
      -          goto yy866;
      -        goto yy846;
      -      }
      -    }
      -  yy864:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy867;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy867;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'z')
      -          goto yy867;
      -        goto yy846;
      -      }
      -    }
      -  yy865:
      -    yych = *++p;
      -    if (yych <= '/')
      -      goto yy846;
      -    if (yych <= '9')
      -      goto yy868;
      -    if (yych == ';')
      -      goto yy852;
      -    goto yy846;
      -  yy866:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy868;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'F') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy868;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'f')
      -          goto yy868;
      -        goto yy846;
      -      }
      -    }
      -  yy867:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy869;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy869;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'z')
      -          goto yy869;
      -        goto yy846;
      -      }
      -    }
      -  yy868:
      -    yych = *++p;
      -    if (yych == ';')
      -      goto yy852;
      -    goto yy846;
      -  yy869:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy870;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy870:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy871;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy871:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy872;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy872:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy873;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy873:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy874;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy874:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy875;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy875:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy876;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy876:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy877;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy877:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy878;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy878:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy879;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy879:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy880;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy880:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy881;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy881:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy882;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy882:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy883;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy883:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy884;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy884:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy885;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy885:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy886;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy886:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy887;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy887:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy888;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy888:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy889;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy889:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy890;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy890:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy891;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy891:
      -    yych = *++p;
      -    if (yych <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy892;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych >= '{')
      -          goto yy846;
      -      }
      -    }
      -  yy892:
      -    ++p;
      -    if ((yych = *p) <= ';') {
      -      if (yych <= '/')
      -        goto yy846;
      -      if (yych <= '9')
      -        goto yy868;
      -      if (yych <= ':')
      -        goto yy846;
      -      goto yy852;
      -    } else {
      -      if (yych <= 'Z') {
      -        if (yych <= '@')
      -          goto yy846;
      -        goto yy868;
      -      } else {
      -        if (yych <= '`')
      -          goto yy846;
      -        if (yych <= 'z')
      -          goto yy868;
      -        goto yy846;
      -      }
      -    }
      -  }
      +{
      +	unsigned char yych;
      +	yych = *p;
      +	if (yych == '&') goto yy869;
      +	++p;
      +yy868:
      +	{ return 0; }
      +yy869:
      +	yych = *(marker = ++p);
      +	if (yych <= '@') {
      +		if (yych != '#') goto yy868;
      +	} else {
      +		if (yych <= 'Z') goto yy872;
      +		if (yych <= '`') goto yy868;
      +		if (yych <= 'z') goto yy872;
      +		goto yy868;
      +	}
      +	yych = *++p;
      +	if (yych <= 'W') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy873;
      +	} else {
      +		if (yych <= 'X') goto yy874;
      +		if (yych == 'x') goto yy874;
      +	}
      +yy871:
      +	p = marker;
      +	goto yy868;
      +yy872:
      +	yych = *++p;
      +	if (yych <= '@') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy875;
      +		goto yy871;
      +	} else {
      +		if (yych <= 'Z') goto yy875;
      +		if (yych <= '`') goto yy871;
      +		if (yych <= 'z') goto yy875;
      +		goto yy871;
      +	}
      +yy873:
      +	yych = *++p;
      +	if (yych <= '/') goto yy871;
      +	if (yych <= '9') goto yy876;
      +	if (yych == ';') goto yy877;
      +	goto yy871;
      +yy874:
      +	yych = *++p;
      +	if (yych <= '@') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy879;
      +		goto yy871;
      +	} else {
      +		if (yych <= 'F') goto yy879;
      +		if (yych <= '`') goto yy871;
      +		if (yych <= 'f') goto yy879;
      +		goto yy871;
      +	}
      +yy875:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy880;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +			goto yy880;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'z') goto yy880;
      +			goto yy871;
      +		}
      +	}
      +yy876:
      +	yych = *++p;
      +	if (yych <= '/') goto yy871;
      +	if (yych <= '9') goto yy881;
      +	if (yych != ';') goto yy871;
      +yy877:
      +	++p;
      +	{ return (bufsize_t)(p - start); }
      +yy879:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy882;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'F') {
      +			if (yych <= '@') goto yy871;
      +			goto yy882;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'f') goto yy882;
      +			goto yy871;
      +		}
      +	}
      +yy880:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy883;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +			goto yy883;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'z') goto yy883;
      +			goto yy871;
      +		}
      +	}
      +yy881:
      +	yych = *++p;
      +	if (yych <= '/') goto yy871;
      +	if (yych <= '9') goto yy884;
      +	if (yych == ';') goto yy877;
      +	goto yy871;
      +yy882:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy885;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'F') {
      +			if (yych <= '@') goto yy871;
      +			goto yy885;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'f') goto yy885;
      +			goto yy871;
      +		}
      +	}
      +yy883:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy886;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +			goto yy886;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'z') goto yy886;
      +			goto yy871;
      +		}
      +	}
      +yy884:
      +	yych = *++p;
      +	if (yych <= '/') goto yy871;
      +	if (yych <= '9') goto yy887;
      +	if (yych == ';') goto yy877;
      +	goto yy871;
      +yy885:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy888;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'F') {
      +			if (yych <= '@') goto yy871;
      +			goto yy888;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'f') goto yy888;
      +			goto yy871;
      +		}
      +	}
      +yy886:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy889;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +			goto yy889;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'z') goto yy889;
      +			goto yy871;
      +		}
      +	}
      +yy887:
      +	yych = *++p;
      +	if (yych <= '/') goto yy871;
      +	if (yych <= '9') goto yy890;
      +	if (yych == ';') goto yy877;
      +	goto yy871;
      +yy888:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy891;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'F') {
      +			if (yych <= '@') goto yy871;
      +			goto yy891;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'f') goto yy891;
      +			goto yy871;
      +		}
      +	}
      +yy889:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy892;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +			goto yy892;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'z') goto yy892;
      +			goto yy871;
      +		}
      +	}
      +yy890:
      +	yych = *++p;
      +	if (yych <= '/') goto yy871;
      +	if (yych <= '9') goto yy893;
      +	if (yych == ';') goto yy877;
      +	goto yy871;
      +yy891:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy893;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'F') {
      +			if (yych <= '@') goto yy871;
      +			goto yy893;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'f') goto yy893;
      +			goto yy871;
      +		}
      +	}
      +yy892:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy894;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +			goto yy894;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'z') goto yy894;
      +			goto yy871;
      +		}
      +	}
      +yy893:
      +	yych = *++p;
      +	if (yych == ';') goto yy877;
      +	goto yy871;
      +yy894:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy895;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy895:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy896;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy896:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy897;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy897:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy898;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy898:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy899;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy899:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy900;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy900:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy901;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy901:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy902;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy902:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy903;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy903:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy904;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy904:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy905;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy905:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy906;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy906:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy907;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy907:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy908;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy908:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy909;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy909:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy910;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy910:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy911;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy911:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy912;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy912:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy913;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy913:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy914;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy914:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy915;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy915:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy916;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy916:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy917;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych >= '{') goto yy871;
      +		}
      +	}
      +yy917:
      +	yych = *++p;
      +	if (yych <= ';') {
      +		if (yych <= '/') goto yy871;
      +		if (yych <= '9') goto yy893;
      +		if (yych <= ':') goto yy871;
      +		goto yy877;
      +	} else {
      +		if (yych <= 'Z') {
      +			if (yych <= '@') goto yy871;
      +			goto yy893;
      +		} else {
      +			if (yych <= '`') goto yy871;
      +			if (yych <= 'z') goto yy893;
      +			goto yy871;
      +		}
      +	}
      +}
      +
       }
       
       // Returns positive value if a URL begins in a way that is potentially
       // dangerous, with javascript:, vbscript:, file:, or data:, otherwise 0.
      -bufsize_t _scan_dangerous_url(const unsigned char *p) {
      +bufsize_t _scan_dangerous_url(const unsigned char *p)
      +{
         const unsigned char *marker = NULL;
         const unsigned char *start = p;
       
      -  {
      -    unsigned char yych;
      -    unsigned int yyaccept = 0;
      -    yych = *p;
      -    if (yych <= 'V') {
      -      if (yych <= 'F') {
      -        if (yych == 'D')
      -          goto yy897;
      -        if (yych >= 'F')
      -          goto yy898;
      -      } else {
      -        if (yych == 'J')
      -          goto yy899;
      -        if (yych >= 'V')
      -          goto yy900;
      -      }
      -    } else {
      -      if (yych <= 'f') {
      -        if (yych == 'd')
      -          goto yy897;
      -        if (yych >= 'f')
      -          goto yy898;
      -      } else {
      -        if (yych <= 'j') {
      -          if (yych >= 'j')
      -            goto yy899;
      -        } else {
      -          if (yych == 'v')
      -            goto yy900;
      -        }
      -      }
      -    }
      -    ++p;
      -  yy896 : { return 0; }
      -  yy897:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych == 'A')
      -      goto yy901;
      -    if (yych == 'a')
      -      goto yy901;
      -    goto yy896;
      -  yy898:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych == 'I')
      -      goto yy903;
      -    if (yych == 'i')
      -      goto yy903;
      -    goto yy896;
      -  yy899:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych == 'A')
      -      goto yy904;
      -    if (yych == 'a')
      -      goto yy904;
      -    goto yy896;
      -  yy900:
      -    yyaccept = 0;
      -    yych = *(marker = ++p);
      -    if (yych == 'B')
      -      goto yy905;
      -    if (yych == 'b')
      -      goto yy905;
      -    goto yy896;
      -  yy901:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy906;
      -    if (yych == 't')
      -      goto yy906;
      -  yy902:
      -    p = marker;
      -    if (yyaccept == 0) {
      -      goto yy896;
      -    } else {
      -      goto yy914;
      -    }
      -  yy903:
      -    yych = *++p;
      -    if (yych == 'L')
      -      goto yy907;
      -    if (yych == 'l')
      -      goto yy907;
      -    goto yy902;
      -  yy904:
      -    yych = *++p;
      -    if (yych == 'V')
      -      goto yy908;
      -    if (yych == 'v')
      -      goto yy908;
      -    goto yy902;
      -  yy905:
      -    yych = *++p;
      -    if (yych == 'S')
      -      goto yy909;
      -    if (yych == 's')
      -      goto yy909;
      -    goto yy902;
      -  yy906:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy910;
      -    if (yych == 'a')
      -      goto yy910;
      -    goto yy902;
      -  yy907:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy911;
      -    if (yych == 'e')
      -      goto yy911;
      -    goto yy902;
      -  yy908:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy905;
      -    if (yych == 'a')
      -      goto yy905;
      -    goto yy902;
      -  yy909:
      -    yych = *++p;
      -    if (yych == 'C')
      -      goto yy912;
      -    if (yych == 'c')
      -      goto yy912;
      -    goto yy902;
      -  yy910:
      -    yych = *++p;
      -    if (yych == ':')
      -      goto yy913;
      -    goto yy902;
      -  yy911:
      -    yych = *++p;
      -    if (yych == ':')
      -      goto yy915;
      -    goto yy902;
      -  yy912:
      -    yych = *++p;
      -    if (yych == 'R')
      -      goto yy916;
      -    if (yych == 'r')
      -      goto yy916;
      -    goto yy902;
      -  yy913:
      -    yyaccept = 1;
      -    yych = *(marker = ++p);
      -    if (yych == 'I')
      -      goto yy917;
      -    if (yych == 'i')
      -      goto yy917;
      -  yy914 : { return (bufsize_t)(p - start); }
      -  yy915:
      -    yych = *++p;
      -    goto yy914;
      -  yy916:
      -    yych = *++p;
      -    if (yych == 'I')
      -      goto yy918;
      -    if (yych == 'i')
      -      goto yy918;
      -    goto yy902;
      -  yy917:
      -    yych = *++p;
      -    if (yych == 'M')
      -      goto yy919;
      -    if (yych == 'm')
      -      goto yy919;
      -    goto yy902;
      -  yy918:
      -    yych = *++p;
      -    if (yych == 'P')
      -      goto yy920;
      -    if (yych == 'p')
      -      goto yy920;
      -    goto yy902;
      -  yy919:
      -    yych = *++p;
      -    if (yych == 'A')
      -      goto yy921;
      -    if (yych == 'a')
      -      goto yy921;
      -    goto yy902;
      -  yy920:
      -    yych = *++p;
      -    if (yych == 'T')
      -      goto yy911;
      -    if (yych == 't')
      -      goto yy911;
      -    goto yy902;
      -  yy921:
      -    yych = *++p;
      -    if (yych == 'G')
      -      goto yy922;
      -    if (yych != 'g')
      -      goto yy902;
      -  yy922:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy923;
      -    if (yych != 'e')
      -      goto yy902;
      -  yy923:
      -    yych = *++p;
      -    if (yych != '/')
      -      goto yy902;
      -    yych = *++p;
      -    if (yych <= 'W') {
      -      if (yych <= 'J') {
      -        if (yych == 'G')
      -          goto yy925;
      -        if (yych <= 'I')
      -          goto yy902;
      -        goto yy926;
      -      } else {
      -        if (yych == 'P')
      -          goto yy927;
      -        if (yych <= 'V')
      -          goto yy902;
      -        goto yy928;
      -      }
      -    } else {
      -      if (yych <= 'j') {
      -        if (yych == 'g')
      -          goto yy925;
      -        if (yych <= 'i')
      -          goto yy902;
      -        goto yy926;
      -      } else {
      -        if (yych <= 'p') {
      -          if (yych <= 'o')
      -            goto yy902;
      -          goto yy927;
      -        } else {
      -          if (yych == 'w')
      -            goto yy928;
      -          goto yy902;
      -        }
      -      }
      -    }
      -  yy925:
      -    yych = *++p;
      -    if (yych == 'I')
      -      goto yy929;
      -    if (yych == 'i')
      -      goto yy929;
      -    goto yy902;
      -  yy926:
      -    yych = *++p;
      -    if (yych == 'P')
      -      goto yy930;
      -    if (yych == 'p')
      -      goto yy930;
      -    goto yy902;
      -  yy927:
      -    yych = *++p;
      -    if (yych == 'N')
      -      goto yy931;
      -    if (yych == 'n')
      -      goto yy931;
      -    goto yy902;
      -  yy928:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy932;
      -    if (yych == 'e')
      -      goto yy932;
      -    goto yy902;
      -  yy929:
      -    yych = *++p;
      -    if (yych == 'F')
      -      goto yy933;
      -    if (yych == 'f')
      -      goto yy933;
      -    goto yy902;
      -  yy930:
      -    yych = *++p;
      -    if (yych == 'E')
      -      goto yy931;
      -    if (yych != 'e')
      -      goto yy902;
      -  yy931:
      -    yych = *++p;
      -    if (yych == 'G')
      -      goto yy933;
      -    if (yych == 'g')
      -      goto yy933;
      -    goto yy902;
      -  yy932:
      -    yych = *++p;
      -    if (yych == 'B')
      -      goto yy935;
      -    if (yych == 'b')
      -      goto yy935;
      -    goto yy902;
      -  yy933:
      -    ++p;
      -    { return 0; }
      -  yy935:
      -    ++p;
      -    if ((yych = *p) == 'P')
      -      goto yy933;
      -    if (yych == 'p')
      -      goto yy933;
      -    goto yy902;
      -  }
      +{
      +	unsigned char yych;
      +	unsigned int yyaccept = 0;
      +	yych = *p;
      +	if (yych <= 'V') {
      +		if (yych <= 'F') {
      +			if (yych == 'D') goto yy922;
      +			if (yych >= 'F') goto yy923;
      +		} else {
      +			if (yych == 'J') goto yy924;
      +			if (yych >= 'V') goto yy925;
      +		}
      +	} else {
      +		if (yych <= 'f') {
      +			if (yych == 'd') goto yy922;
      +			if (yych >= 'f') goto yy923;
      +		} else {
      +			if (yych <= 'j') {
      +				if (yych >= 'j') goto yy924;
      +			} else {
      +				if (yych == 'v') goto yy925;
      +			}
      +		}
      +	}
      +	++p;
      +yy921:
      +	{ return 0; }
      +yy922:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych == 'A') goto yy926;
      +	if (yych == 'a') goto yy926;
      +	goto yy921;
      +yy923:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych == 'I') goto yy928;
      +	if (yych == 'i') goto yy928;
      +	goto yy921;
      +yy924:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych == 'A') goto yy929;
      +	if (yych == 'a') goto yy929;
      +	goto yy921;
      +yy925:
      +	yyaccept = 0;
      +	yych = *(marker = ++p);
      +	if (yych == 'B') goto yy930;
      +	if (yych == 'b') goto yy930;
      +	goto yy921;
      +yy926:
      +	yych = *++p;
      +	if (yych == 'T') goto yy931;
      +	if (yych == 't') goto yy931;
      +yy927:
      +	p = marker;
      +	if (yyaccept == 0) {
      +		goto yy921;
      +	} else {
      +		goto yy939;
      +	}
      +yy928:
      +	yych = *++p;
      +	if (yych == 'L') goto yy932;
      +	if (yych == 'l') goto yy932;
      +	goto yy927;
      +yy929:
      +	yych = *++p;
      +	if (yych == 'V') goto yy933;
      +	if (yych == 'v') goto yy933;
      +	goto yy927;
      +yy930:
      +	yych = *++p;
      +	if (yych == 'S') goto yy934;
      +	if (yych == 's') goto yy934;
      +	goto yy927;
      +yy931:
      +	yych = *++p;
      +	if (yych == 'A') goto yy935;
      +	if (yych == 'a') goto yy935;
      +	goto yy927;
      +yy932:
      +	yych = *++p;
      +	if (yych == 'E') goto yy936;
      +	if (yych == 'e') goto yy936;
      +	goto yy927;
      +yy933:
      +	yych = *++p;
      +	if (yych == 'A') goto yy930;
      +	if (yych == 'a') goto yy930;
      +	goto yy927;
      +yy934:
      +	yych = *++p;
      +	if (yych == 'C') goto yy937;
      +	if (yych == 'c') goto yy937;
      +	goto yy927;
      +yy935:
      +	yych = *++p;
      +	if (yych == ':') goto yy938;
      +	goto yy927;
      +yy936:
      +	yych = *++p;
      +	if (yych == ':') goto yy940;
      +	goto yy927;
      +yy937:
      +	yych = *++p;
      +	if (yych == 'R') goto yy941;
      +	if (yych == 'r') goto yy941;
      +	goto yy927;
      +yy938:
      +	yyaccept = 1;
      +	yych = *(marker = ++p);
      +	if (yych == 'I') goto yy942;
      +	if (yych == 'i') goto yy942;
      +yy939:
      +	{ return (bufsize_t)(p - start); }
      +yy940:
      +	++p;
      +	goto yy939;
      +yy941:
      +	yych = *++p;
      +	if (yych == 'I') goto yy943;
      +	if (yych == 'i') goto yy943;
      +	goto yy927;
      +yy942:
      +	yych = *++p;
      +	if (yych == 'M') goto yy944;
      +	if (yych == 'm') goto yy944;
      +	goto yy927;
      +yy943:
      +	yych = *++p;
      +	if (yych == 'P') goto yy945;
      +	if (yych == 'p') goto yy945;
      +	goto yy927;
      +yy944:
      +	yych = *++p;
      +	if (yych == 'A') goto yy946;
      +	if (yych == 'a') goto yy946;
      +	goto yy927;
      +yy945:
      +	yych = *++p;
      +	if (yych == 'T') goto yy936;
      +	if (yych == 't') goto yy936;
      +	goto yy927;
      +yy946:
      +	yych = *++p;
      +	if (yych == 'G') goto yy947;
      +	if (yych != 'g') goto yy927;
      +yy947:
      +	yych = *++p;
      +	if (yych == 'E') goto yy948;
      +	if (yych != 'e') goto yy927;
      +yy948:
      +	yych = *++p;
      +	if (yych != '/') goto yy927;
      +	yych = *++p;
      +	if (yych <= 'W') {
      +		if (yych <= 'J') {
      +			if (yych == 'G') goto yy950;
      +			if (yych <= 'I') goto yy927;
      +			goto yy951;
      +		} else {
      +			if (yych == 'P') goto yy952;
      +			if (yych <= 'V') goto yy927;
      +			goto yy953;
      +		}
      +	} else {
      +		if (yych <= 'j') {
      +			if (yych == 'g') goto yy950;
      +			if (yych <= 'i') goto yy927;
      +			goto yy951;
      +		} else {
      +			if (yych <= 'p') {
      +				if (yych <= 'o') goto yy927;
      +				goto yy952;
      +			} else {
      +				if (yych == 'w') goto yy953;
      +				goto yy927;
      +			}
      +		}
      +	}
      +yy950:
      +	yych = *++p;
      +	if (yych == 'I') goto yy954;
      +	if (yych == 'i') goto yy954;
      +	goto yy927;
      +yy951:
      +	yych = *++p;
      +	if (yych == 'P') goto yy955;
      +	if (yych == 'p') goto yy955;
      +	goto yy927;
      +yy952:
      +	yych = *++p;
      +	if (yych == 'N') goto yy956;
      +	if (yych == 'n') goto yy956;
      +	goto yy927;
      +yy953:
      +	yych = *++p;
      +	if (yych == 'E') goto yy957;
      +	if (yych == 'e') goto yy957;
      +	goto yy927;
      +yy954:
      +	yych = *++p;
      +	if (yych == 'F') goto yy958;
      +	if (yych == 'f') goto yy958;
      +	goto yy927;
      +yy955:
      +	yych = *++p;
      +	if (yych == 'E') goto yy956;
      +	if (yych != 'e') goto yy927;
      +yy956:
      +	yych = *++p;
      +	if (yych == 'G') goto yy958;
      +	if (yych == 'g') goto yy958;
      +	goto yy927;
      +yy957:
      +	yych = *++p;
      +	if (yych == 'B') goto yy960;
      +	if (yych == 'b') goto yy960;
      +	goto yy927;
      +yy958:
      +	++p;
      +	{ return 0; }
      +yy960:
      +	yych = *++p;
      +	if (yych == 'P') goto yy958;
      +	if (yych == 'p') goto yy958;
      +	goto yy927;
      +}
      +
      +}
      +
      +// Scans a footnote definition opening.
      +bufsize_t _scan_footnote_definition(const unsigned char *p)
      +{
      +  const unsigned char *marker = NULL;
      +  const unsigned char *start = p;
      +
      +{
      +	unsigned char yych;
      +	static const unsigned char yybm[] = {
      +		  0,  64,  64,  64,  64,  64,  64,  64, 
      +		 64, 128,   0,  64,  64,   0,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		128,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,   0,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		 64,  64,  64,  64,  64,  64,  64,  64, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +		  0,   0,   0,   0,   0,   0,   0,   0, 
      +	};
      +	yych = *p;
      +	if (yych == '[') goto yy965;
      +	++p;
      +yy964:
      +	{ return 0; }
      +yy965:
      +	yych = *(marker = ++p);
      +	if (yych != '^') goto yy964;
      +	yych = *++p;
      +	if (yych != ']') goto yy969;
      +yy967:
      +	p = marker;
      +	goto yy964;
      +yy968:
      +	yych = *++p;
      +yy969:
      +	if (yybm[0+yych] & 64) {
      +		goto yy968;
      +	}
      +	if (yych <= 0xEC) {
      +		if (yych <= 0xC1) {
      +			if (yych <= ' ') goto yy967;
      +			if (yych <= ']') goto yy977;
      +			goto yy967;
      +		} else {
      +			if (yych <= 0xDF) goto yy970;
      +			if (yych <= 0xE0) goto yy971;
      +			goto yy972;
      +		}
      +	} else {
      +		if (yych <= 0xF0) {
      +			if (yych <= 0xED) goto yy973;
      +			if (yych <= 0xEF) goto yy972;
      +			goto yy974;
      +		} else {
      +			if (yych <= 0xF3) goto yy975;
      +			if (yych <= 0xF4) goto yy976;
      +			goto yy967;
      +		}
      +	}
      +yy970:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy967;
      +	if (yych <= 0xBF) goto yy968;
      +	goto yy967;
      +yy971:
      +	yych = *++p;
      +	if (yych <= 0x9F) goto yy967;
      +	if (yych <= 0xBF) goto yy970;
      +	goto yy967;
      +yy972:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy967;
      +	if (yych <= 0xBF) goto yy970;
      +	goto yy967;
      +yy973:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy967;
      +	if (yych <= 0x9F) goto yy970;
      +	goto yy967;
      +yy974:
      +	yych = *++p;
      +	if (yych <= 0x8F) goto yy967;
      +	if (yych <= 0xBF) goto yy972;
      +	goto yy967;
      +yy975:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy967;
      +	if (yych <= 0xBF) goto yy972;
      +	goto yy967;
      +yy976:
      +	yych = *++p;
      +	if (yych <= 0x7F) goto yy967;
      +	if (yych <= 0x8F) goto yy972;
      +	goto yy967;
      +yy977:
      +	yych = *++p;
      +	if (yych != ':') goto yy967;
      +yy978:
      +	yych = *++p;
      +	if (yybm[0+yych] & 128) {
      +		goto yy978;
      +	}
      +	{ return (bufsize_t)(p - start); }
      +}
      +
       }
      diff --git a/src/scanners.re b/src/scanners.re
      index 447147b4b..c486f362e 100644
      --- a/src/scanners.re
      +++ b/src/scanners.re
      @@ -122,6 +122,17 @@ bufsize_t _scan_html_tag(const unsigned char *p)
       */
       }
       
      +// Try to (liberally) match an HTML tag after first <, returning num of chars matched.
      +bufsize_t _scan_liberal_html_tag(const unsigned char *p)
      +{
      +  const unsigned char *marker = NULL;
      +  const unsigned char *start = p;
      +/*!re2c
      +  [^\n\x00]+ [>] { return (bufsize_t)(p - start); }
      +  * { return 0; }
      +*/
      +}
      +
       // Try to match an HTML block tag start line, returning
       // an integer code for the type of block (1-6, matching the spec).
       // #7 is handled by a separate function, below.
      @@ -303,3 +314,13 @@ bufsize_t _scan_dangerous_url(const unsigned char *p)
       */
       }
       
      +// Scans a footnote definition opening.
      +bufsize_t _scan_footnote_definition(const unsigned char *p)
      +{
      +  const unsigned char *marker = NULL;
      +  const unsigned char *start = p;
      +/*!re2c
      +  '[^' ([^\] \r\n\x00\t]+) ']:' [ \t]* { return (bufsize_t)(p - start); }
      +  * { return 0; }
      +*/
      +}
      diff --git a/src/syntax_extension.c b/src/syntax_extension.c
      new file mode 100644
      index 000000000..d24fe43e6
      --- /dev/null
      +++ b/src/syntax_extension.c
      @@ -0,0 +1,149 @@
      +#include 
      +#include 
      +
      +#include "cmark-gfm.h"
      +#include "syntax_extension.h"
      +#include "buffer.h"
      +
      +extern cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR;
      +
      +static cmark_mem *_mem = &CMARK_DEFAULT_MEM_ALLOCATOR;
      +
      +void cmark_syntax_extension_free(cmark_mem *mem, cmark_syntax_extension *extension) {
      +  if (extension->free_function && extension->priv) {
      +    extension->free_function(mem, extension->priv);
      +  }
      +
      +  cmark_llist_free(mem, extension->special_inline_chars);
      +  mem->free(extension->name);
      +  mem->free(extension);
      +}
      +
      +cmark_syntax_extension *cmark_syntax_extension_new(const char *name) {
      +  cmark_syntax_extension *res = (cmark_syntax_extension *) _mem->calloc(1, sizeof(cmark_syntax_extension));
      +  res->name = (char *) _mem->calloc(1, sizeof(char) * (strlen(name)) + 1);
      +  strcpy(res->name, name);
      +  return res;
      +}
      +
      +cmark_node_type cmark_syntax_extension_add_node(int is_inline) {
      +  cmark_node_type *ref = !is_inline ? &CMARK_NODE_LAST_BLOCK : &CMARK_NODE_LAST_INLINE;
      +
      +  if ((*ref & CMARK_NODE_VALUE_MASK) == CMARK_NODE_VALUE_MASK) {
      +    assert(false);
      +    return (cmark_node_type) 0;
      +  }
      +
      +  return *ref = (cmark_node_type) ((int) *ref + 1);
      +}
      +
      +void cmark_syntax_extension_set_emphasis(cmark_syntax_extension *extension,
      +                                         int emphasis) {
      +  extension->emphasis = emphasis == 1;
      +}
      +
      +void cmark_syntax_extension_set_open_block_func(cmark_syntax_extension *extension,
      +                                                cmark_open_block_func func) {
      +  extension->try_opening_block = func;
      +}
      +
      +void cmark_syntax_extension_set_match_block_func(cmark_syntax_extension *extension,
      +                                                 cmark_match_block_func func) {
      +  extension->last_block_matches = func;
      +}
      +
      +void cmark_syntax_extension_set_match_inline_func(cmark_syntax_extension *extension,
      +                                                  cmark_match_inline_func func) {
      +  extension->match_inline = func;
      +}
      +
      +void cmark_syntax_extension_set_inline_from_delim_func(cmark_syntax_extension *extension,
      +                                                       cmark_inline_from_delim_func func) {
      +  extension->insert_inline_from_delim = func;
      +}
      +
      +void cmark_syntax_extension_set_special_inline_chars(cmark_syntax_extension *extension,
      +                                                     cmark_llist *special_chars) {
      +  extension->special_inline_chars = special_chars;
      +}
      +
      +void cmark_syntax_extension_set_get_type_string_func(cmark_syntax_extension *extension,
      +                                                     cmark_get_type_string_func func) {
      +  extension->get_type_string_func = func;
      +}
      +
      +void cmark_syntax_extension_set_can_contain_func(cmark_syntax_extension *extension,
      +                                                 cmark_can_contain_func func) {
      +  extension->can_contain_func = func;
      +}
      +
      +void cmark_syntax_extension_set_contains_inlines_func(cmark_syntax_extension *extension,
      +                                                      cmark_contains_inlines_func func) {
      +  extension->contains_inlines_func = func;
      +}
      +
      +void cmark_syntax_extension_set_commonmark_render_func(cmark_syntax_extension *extension,
      +                                                       cmark_common_render_func func) {
      +  extension->commonmark_render_func = func;
      +}
      +
      +void cmark_syntax_extension_set_plaintext_render_func(cmark_syntax_extension *extension,
      +                                                      cmark_common_render_func func) {
      +  extension->plaintext_render_func = func;
      +}
      +
      +void cmark_syntax_extension_set_latex_render_func(cmark_syntax_extension *extension,
      +                                                  cmark_common_render_func func) {
      +  extension->latex_render_func = func;
      +}
      +
      +void cmark_syntax_extension_set_xml_attr_func(cmark_syntax_extension *extension,
      +                                              cmark_xml_attr_func func) {
      +  extension->xml_attr_func = func;
      +}
      +
      +void cmark_syntax_extension_set_man_render_func(cmark_syntax_extension *extension,
      +                                                cmark_common_render_func func) {
      +  extension->man_render_func = func;
      +}
      +
      +void cmark_syntax_extension_set_html_render_func(cmark_syntax_extension *extension,
      +                                                 cmark_html_render_func func) {
      +  extension->html_render_func = func;
      +}
      +
      +void cmark_syntax_extension_set_html_filter_func(cmark_syntax_extension *extension,
      +                                                 cmark_html_filter_func func) {
      +  extension->html_filter_func = func;
      +}
      +
      +void cmark_syntax_extension_set_postprocess_func(cmark_syntax_extension *extension,
      +                                                 cmark_postprocess_func func) {
      +  extension->postprocess_func = func;
      +}
      +
      +void cmark_syntax_extension_set_private(cmark_syntax_extension *extension,
      +                                        void *priv,
      +                                        cmark_free_func free_func) {
      +  extension->priv = priv;
      +  extension->free_function = free_func;
      +}
      +
      +void *cmark_syntax_extension_get_private(cmark_syntax_extension *extension) {
      +    return extension->priv;
      +}
      +
      +void cmark_syntax_extension_set_opaque_alloc_func(cmark_syntax_extension *extension,
      +                                                  cmark_opaque_alloc_func func) {
      +  extension->opaque_alloc_func = func;
      +}
      +
      +void cmark_syntax_extension_set_opaque_free_func(cmark_syntax_extension *extension,
      +                                                 cmark_opaque_free_func func) {
      +  extension->opaque_free_func = func;
      +}
      +
      +void cmark_syntax_extension_set_commonmark_escape_func(cmark_syntax_extension *extension,
      +                                                       cmark_commonmark_escape_func func) {
      +  extension->commonmark_escape_func = func;
      +}
      diff --git a/src/xml.c b/src/xml.c
      index 48674ccb7..d572290ae 100644
      --- a/src/xml.c
      +++ b/src/xml.c
      @@ -3,11 +3,12 @@
       #include 
       #include 
       
      -#include "config.h"
      -#include "cmark.h"
      +#include "cmark-gfm_config.h"
      +#include "cmark-gfm.h"
       #include "node.h"
       #include "buffer.h"
       #include "houdini.h"
      +#include "syntax_extension.h"
       
       #define BUFFER_SIZE 100
       
      @@ -50,6 +51,12 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type,
             cmark_strbuf_puts(xml, buffer);
           }
       
      +    if (node->extension && node->extension->xml_attr_func) {
      +      const char* r = node->extension->xml_attr_func(node->extension, node);
      +      if (r != NULL)
      +        cmark_strbuf_puts(xml, r);
      +    }
      +
           literal = false;
       
           switch (node->type) {
      @@ -126,6 +133,9 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type,
             escape_xml(xml, node->as.link.title.data, node->as.link.title.len);
             cmark_strbuf_putc(xml, '"');
             break;
      +    case CMARK_NODE_ATTRIBUTE:
      +      // TODO
      +      break;
           default:
             break;
           }
      @@ -148,8 +158,12 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type,
       }
       
       char *cmark_render_xml(cmark_node *root, int options) {
      +  return cmark_render_xml_with_mem(root, options, cmark_node_mem(root));
      +}
      +
      +char *cmark_render_xml_with_mem(cmark_node *root, int options, cmark_mem *mem) {
         char *result;
      -  cmark_strbuf xml = CMARK_BUF_INIT(cmark_node_mem(root));
      +  cmark_strbuf xml = CMARK_BUF_INIT(mem);
         cmark_event_type ev_type;
         cmark_node *cur;
         struct render_state state = {&xml, 0};
      diff --git a/suppressions b/suppressions
      new file mode 100644
      index 000000000..d03ae8532
      --- /dev/null
      +++ b/suppressions
      @@ -0,0 +1,10 @@
      +{
      +   .
      +   Memcheck:Leak
      +   fun:malloc
      +   fun:__smakebuf
      +   fun:__srefill0
      +   fun:__fread
      +   fun:fread
      +   fun:main
      +}
      diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
      index 5c07fb7b2..2b5c99bc5 100755
      --- a/test/CMakeLists.txt
      +++ b/test/CMakeLists.txt
      @@ -14,8 +14,9 @@ if (CMARK_SHARED OR CMARK_STATIC)
       endif()
       
       if (WIN32)
      -  file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR}/src WIN_DLL_DIR)
      -  set(NEWPATH "${WIN_DLL_DIR};$ENV{PATH}")
      +  file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR}/src WIN_SRC_DLL_DIR)
      +  file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR}/extensions WIN_EXTENSIONS_DLL_DIR)
      +  set(NEWPATH "${WIN_SRC_DLL_DIR};${WIN_EXTENSIONS_DLL_DIR};$ENV{PATH}")
         string(REPLACE ";" "\\;" NEWPATH "${NEWPATH}")
         set_tests_properties(api_test PROPERTIES ENVIRONMENT "PATH=${NEWPATH}")
         set(ROUNDTRIP "${CMAKE_CURRENT_SOURCE_DIR}/roundtrip.bat")
      @@ -56,20 +57,53 @@ IF (PYTHONINTERP_FOUND)
         endif()
       
         add_test(spectest_executable
      -    ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/spec_tests.py" "--no-normalize" "--spec" "${CMAKE_CURRENT_SOURCE_DIR}/spec.txt" "--program" "${CMAKE_CURRENT_BINARY_DIR}/../src/cmark"
      +    ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/spec_tests.py" "--no-normalize" "--spec" "${CMAKE_CURRENT_SOURCE_DIR}/spec.txt" "--program" "${CMAKE_CURRENT_BINARY_DIR}/../src/cmark-gfm"
           )
       
         add_test(smartpuncttest_executable
      -    ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/spec_tests.py" "--no-normalize" "--spec" "${CMAKE_CURRENT_SOURCE_DIR}/smart_punct.txt" "--program" "${CMAKE_CURRENT_BINARY_DIR}/../src/cmark --smart"
      +    ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/spec_tests.py" "--no-normalize" "--spec" "${CMAKE_CURRENT_SOURCE_DIR}/smart_punct.txt" "--program" "${CMAKE_CURRENT_BINARY_DIR}/../src/cmark-gfm --smart"
      +    )
      +
      +  add_test(extensions_executable
      +    ${PYTHON_EXECUTABLE}
      +    "${CMAKE_CURRENT_SOURCE_DIR}/spec_tests.py"
      +    "--no-normalize"
      +    "--spec" "${CMAKE_CURRENT_SOURCE_DIR}/extensions.txt"
      +    "--program" "${CMAKE_CURRENT_BINARY_DIR}/../src/cmark-gfm"
      +    "--extensions" "table strikethrough autolink tagfilter footnotes tasklist"
      +    )
      +
      +  add_test(roundtrip_extensions_executable
      +    ${PYTHON_EXECUTABLE}
      +    "${CMAKE_CURRENT_SOURCE_DIR}/roundtrip_tests.py"
      +    "--spec" "${CMAKE_CURRENT_SOURCE_DIR}/extensions.txt"
      +    "--program" "${CMAKE_CURRENT_BINARY_DIR}/../src/cmark-gfm"
      +    "--extensions" "table strikethrough autolink tagfilter footnotes tasklist"
      +    )
      +
      +  add_test(option_table_prefer_style_attributes
      +    ${PYTHON_EXECUTABLE}
      +    "${CMAKE_CURRENT_SOURCE_DIR}/roundtrip_tests.py"
      +    "--spec" "${CMAKE_CURRENT_SOURCE_DIR}/extensions-table-prefer-style-attributes.txt"
      +    "--program" "${CMAKE_CURRENT_BINARY_DIR}/../src/cmark-gfm --table-prefer-style-attributes"
      +    "--extensions" "table strikethrough autolink tagfilter footnotes tasklist"
      +    )
      +
      +  add_test(option_full_info_string
      +    ${PYTHON_EXECUTABLE}
      +    "${CMAKE_CURRENT_SOURCE_DIR}/roundtrip_tests.py"
      +    "--spec" "${CMAKE_CURRENT_SOURCE_DIR}/extensions-full-info-string.txt"
      +    "--program" "${CMAKE_CURRENT_BINARY_DIR}/../src/cmark-gfm --full-info-string"
           )
       
         add_test(regressiontest_executable
           ${PYTHON_EXECUTABLE}
           "${CMAKE_CURRENT_SOURCE_DIR}/spec_tests.py" "--no-normalize" "--spec"
           "${CMAKE_CURRENT_SOURCE_DIR}/regression.txt" "--program"
      -    "${CMAKE_CURRENT_BINARY_DIR}/../src/cmark"
      +    "${CMAKE_CURRENT_BINARY_DIR}/../src/cmark-gfm"
           )
       
      +
       ELSE(PYTHONINTERP_FOUND)
       
         message("\n*** A python 3 interpreter is required to run the spec tests.\n")
      diff --git a/test/afl_test_cases/test.md b/test/afl_test_cases/test.md
      index 27eee009c..4156a2aef 100644
      --- a/test/afl_test_cases/test.md
      +++ b/test/afl_test_cases/test.md
      @@ -32,5 +32,18 @@ cb
       x
       
       
      -[f]: /u "t"
      +| a | b |
      +| --- | --- |
      +| c | `d|` \| e |
      +
      +google ~~yahoo~~
      +
      +google.com http://google.com google@google.com
       
      +and  but
      +
      +<surewhynot>
      +sure
      +</surewhynot>
      +
      +[f]: /u "t"
      diff --git a/test/cmark-fuzz.c b/test/cmark-fuzz.c
      index 02c05bc53..0a6dc3da9 100644
      --- a/test/cmark-fuzz.c
      +++ b/test/cmark-fuzz.c
      @@ -1,6 +1,21 @@
       #include <stdint.h>
       #include <stdlib.h>
      -#include "cmark.h"
      +#include <string.h>
      +#include "cmark-gfm.h"
      +#include "cmark-gfm-core-extensions.h"
      +
      +const char *extension_names[] = {
      +  "autolink",
      +  "strikethrough",
      +  "table",
      +  "tagfilter",
      +  NULL,
      +};
      +
      +int LLVMFuzzerInitialize(int *argc, char ***argv) {
      +  cmark_gfm_core_extensions_ensure_registered();
      +  return 0;
      +}
       
       int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
         struct __attribute__((packed)) {
      @@ -12,21 +27,32 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
           /* The beginning of `data` is treated as fuzzer configuration */
           memcpy(&fuzz_config, data, sizeof(fuzz_config));
       
      -    /* Mask off valid option bits */
      -    fuzz_config.options &= (CMARK_OPT_SOURCEPOS | CMARK_OPT_HARDBREAKS | CMARK_OPT_UNSAFE | CMARK_OPT_NOBREAKS | CMARK_OPT_NORMALIZE | CMARK_OPT_VALIDATE_UTF8 | CMARK_OPT_SMART);
      -
           /* Remainder of input is the markdown */
           const char *markdown = (const char *)(data + sizeof(fuzz_config));
           const size_t markdown_size = size - sizeof(fuzz_config);
      -    cmark_node *doc = cmark_parse_document(markdown, markdown_size, fuzz_config.options);
      +    cmark_parser *parser = cmark_parser_new(fuzz_config.options);
      +
      +    for (const char **it = extension_names; *it; ++it) {
      +      const char *extension_name = *it;
      +      cmark_syntax_extension *syntax_extension = cmark_find_syntax_extension(extension_name);
      +      if (!syntax_extension) {
      +        fprintf(stderr, "%s is not a valid syntax extension\n", extension_name);
      +        abort();
      +      }
      +      cmark_parser_attach_syntax_extension(parser, syntax_extension);
      +    }
      +
      +    cmark_parser_feed(parser, markdown, markdown_size);
      +    cmark_node *doc = cmark_parser_finish(parser);
       
           free(cmark_render_commonmark(doc, fuzz_config.options, fuzz_config.width));
      -    free(cmark_render_html(doc, fuzz_config.options));
      +    free(cmark_render_html(doc, fuzz_config.options, NULL));
           free(cmark_render_latex(doc, fuzz_config.options, fuzz_config.width));
           free(cmark_render_man(doc, fuzz_config.options, fuzz_config.width));
           free(cmark_render_xml(doc, fuzz_config.options));
       
           cmark_node_free(doc);
      +    cmark_parser_free(parser);
         }
         return 0;
       }
      diff --git a/test/cmark.py b/test/cmark.py
      index 38d2f599c..b0eb20dbe 100644
      --- a/test/cmark.py
      +++ b/test/cmark.py
      @@ -11,52 +11,95 @@ def pipe_through_prog(prog, text):
           [result, err] = p1.communicate(input=text.encode('utf-8'))
           return [p1.returncode, result.decode('utf-8'), err]
       
      -def to_html(lib, text):
      -    markdown = lib.cmark_markdown_to_html
      -    markdown.restype = c_char_p
      -    markdown.argtypes = [c_char_p, c_size_t, c_int]
      +def parse(lib, extlib, text, extensions):
      +    cmark_gfm_core_extensions_ensure_registered = extlib.cmark_gfm_core_extensions_ensure_registered
      +
      +    find_syntax_extension = lib.cmark_find_syntax_extension
      +    find_syntax_extension.restype = c_void_p
      +    find_syntax_extension.argtypes = [c_char_p]
      +
      +    parser_attach_syntax_extension = lib.cmark_parser_attach_syntax_extension
      +    parser_attach_syntax_extension.argtypes = [c_void_p, c_void_p]
      +
      +    parser_new = lib.cmark_parser_new
      +    parser_new.restype = c_void_p
      +    parser_new.argtypes = [c_int]
      +    
      +    parser_feed = lib.cmark_parser_feed
      +    parser_feed.argtypes = [c_void_p, c_char_p, c_int]
      +
      +    parser_finish = lib.cmark_parser_finish
      +    parser_finish.restype = c_void_p
      +    parser_finish.argtypes = [c_void_p]
      +
      +    cmark_gfm_core_extensions_ensure_registered()
      +
      +    parser = parser_new(0)
      +    for e in set(extensions):
      +        ext = find_syntax_extension(bytes(e, 'utf-8'))
      +        if not ext:
      +            raise Exception("Extension not found: '{}'".format(e))
      +        parser_attach_syntax_extension(parser, ext)
      +
           textbytes = text.encode('utf-8')
           textlen = len(textbytes)
      +    parser_feed(parser, textbytes, textlen)
      +
      +    return [parser_finish(parser), parser]
      +
      +def to_html(lib, extlib, text, extensions):
      +    document, parser = parse(lib, extlib, text, extensions)
      +    parser_get_syntax_extensions = lib.cmark_parser_get_syntax_extensions
      +    parser_get_syntax_extensions.restype = c_void_p
      +    parser_get_syntax_extensions.argtypes = [c_void_p]
      +    syntax_extensions = parser_get_syntax_extensions(parser)
      +
      +    render_html = lib.cmark_render_html
      +    render_html.restype = c_char_p
      +    render_html.argtypes = [c_void_p, c_int, c_void_p]
           # 1 << 17 == CMARK_OPT_UNSAFE
      -    result = markdown(textbytes, textlen, 1 << 17).decode('utf-8')
      +    result = render_html(document, 1 << 17, syntax_extensions).decode('utf-8')
           return [0, result, '']
       
      -def to_commonmark(lib, text):
      -    textbytes = text.encode('utf-8')
      -    textlen = len(textbytes)
      -    parse_document = lib.cmark_parse_document
      -    parse_document.restype = c_void_p
      -    parse_document.argtypes = [c_char_p, c_size_t, c_int]
      +def to_commonmark(lib, extlib, text, extensions):
      +    document, _ = parse(lib, extlib, text, extensions)
      +
           render_commonmark = lib.cmark_render_commonmark
           render_commonmark.restype = c_char_p
           render_commonmark.argtypes = [c_void_p, c_int, c_int]
      -    node = parse_document(textbytes, textlen, 0)
      -    result = render_commonmark(node, 0, 0).decode('utf-8')
      +    result = render_commonmark(document, 0, 0).decode('utf-8')
           return [0, result, '']
       
       class CMark:
      -    def __init__(self, prog=None, library_dir=None):
      +    def __init__(self, prog=None, library_dir=None, extensions=None):
               self.prog = prog
      +        self.extensions = []
      +        if extensions:
      +            self.extensions = extensions.split()
      +
               if prog:
                   prog += ' --unsafe'
      -            self.to_html = lambda x: pipe_through_prog(prog, x)
      -            self.to_commonmark = lambda x: pipe_through_prog(prog + ' -t commonmark', x)
      +            extsfun = lambda exts: ''.join([' -e ' + e for e in set(exts)])
      +            self.to_html = lambda x, exts=[]: pipe_through_prog(prog + extsfun(exts + self.extensions), x)
      +            self.to_commonmark = lambda x, exts=[]: pipe_through_prog(prog + ' -t commonmark' + extsfun(exts + self.extensions), x)
               else:
                   sysname = platform.system()
                   if sysname == 'Darwin':
      -                libnames = [ "libcmark.dylib" ]
      +                libnames = [ ["lib", ".dylib" ] ]
                   elif sysname == 'Windows':
      -                libnames = [ "cmark.dll", "libcmark.dll" ]
      +                libnames = [ ["", ".dll"], ["lib", ".dll"] ]
                   else:
      -                libnames = [ "libcmark.so" ]
      +                libnames = [ ["lib", ".so"] ]
                   if not library_dir:
      -                library_dir = os.path.join("build", "src")
      -            for libname in libnames:
      -                candidate = os.path.join(library_dir, libname)
      +                library_dir = os.path.join("..", "build", "src")
      +            for prefix, suffix in libnames:
      +                candidate = os.path.join(library_dir, prefix + "cmark-gfm" + suffix)
                       if os.path.isfile(candidate):
                           libpath = candidate
                           break
                   cmark = CDLL(libpath)
      -            self.to_html = lambda x: to_html(cmark, x)
      -            self.to_commonmark = lambda x: to_commonmark(cmark, x)
      +            extlib = CDLL(os.path.join(
      +                library_dir, "..", "extensions", prefix + "cmark-gfm-extensions" + suffix))
      +            self.to_html = lambda x, exts=[]: to_html(cmark, extlib, x, exts + self.extensions)
      +            self.to_commonmark = lambda x, exts=[]: to_commonmark(cmark, extlib, x, exts + self.extensions)
       
      diff --git a/test/entity_tests.py b/test/entity_tests.py
      index ebaf9f7af..3abb3b8c0 100644
      --- a/test/entity_tests.py
      +++ b/test/entity_tests.py
      @@ -54,7 +54,6 @@ def get_entities():
               print(entity, '[ERRORED (return code {})]'.format(rc))
               print(err)
           elif check in actual:
      -        # print(entity, '[PASSED]') # omit noisy success output
               passed += 1
           else:
               print(entity, '[FAILED]')
      diff --git a/test/extensions-full-info-string.txt b/test/extensions-full-info-string.txt
      new file mode 100644
      index 000000000..aeb4f445d
      Binary files /dev/null and b/test/extensions-full-info-string.txt differ
      diff --git a/test/extensions-table-prefer-style-attributes.txt b/test/extensions-table-prefer-style-attributes.txt
      new file mode 100644
      index 000000000..0379def1b
      --- /dev/null
      +++ b/test/extensions-table-prefer-style-attributes.txt
      @@ -0,0 +1,38 @@
      +---
      +title: Extensions test with --table-prefer-style-attributes
      +author: FUJI Goro
      +version: 0.1
      +date: '2018-02-20'
      +license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)'
      +...
      +
      +## Tables
      +
      +Table alignment:
      +
      +```````````````````````````````` example
      +aaa | bbb | ccc | ddd | eee
      +:-- | --- | :-: | --- | --:
      +fff | ggg | hhh | iii | jjj
      +.
      +<table>
      +<thead>
      +<tr>
      +<th style="text-align: left">aaa</th>
      +<th>bbb</th>
      +<th style="text-align: center">ccc</th>
      +<th>ddd</th>
      +<th style="text-align: right">eee</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td style="text-align: left">fff</td>
      +<td>ggg</td>
      +<td style="text-align: center">hhh</td>
      +<td>iii</td>
      +<td style="text-align: right">jjj</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      diff --git a/test/extensions.txt b/test/extensions.txt
      new file mode 100644
      index 000000000..0d9993782
      --- /dev/null
      +++ b/test/extensions.txt
      @@ -0,0 +1,826 @@
      +---
      +title: Extensions test
      +author: Yuki Izumi
      +version: 0.1
      +date: '2016-08-31'
      +license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)'
      +...
      +
      +## Tables
      +
      +Here's a well-formed table, doing everything it should.
      +
      +```````````````````````````````` example
      +| abc | def |
      +| --- | --- |
      +| ghi | jkl |
      +| mno | pqr |
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>abc</th>
      +<th>def</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>ghi</td>
      +<td>jkl</td>
      +</tr>
      +<tr>
      +<td>mno</td>
      +<td>pqr</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +We're going to mix up the table now; we'll demonstrate that inline formatting
      +works fine, but block elements don't.  You can also have empty cells, and the
      +textual alignment of the columns is shown to be irrelevant.
      +
      +```````````````````````````````` example
      +Hello!
      +
      +| _abc_ | セン |
      +| ----- | ---- |
      +| 1. Block elements inside cells don't work. | |
      +| But _**inline elements do**_. | x |
      +
      +Hi!
      +.
      +<p>Hello!</p>
      +<table>
      +<thead>
      +<tr>
      +<th><em>abc</em></th>
      +<th>セン</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>1. Block elements inside cells don't work.</td>
      +<td></td>
      +</tr>
      +<tr>
      +<td>But <em><strong>inline elements do</strong></em>.</td>
      +<td>x</td>
      +</tr>
      +</tbody>
      +</table>
      +<p>Hi!</p>
      +````````````````````````````````
      +
      +Here we demonstrate some edge cases about what is and isn't a table.
      +
      +```````````````````````````````` example
      +| Not enough table | to be considered table |
      +
      +| Not enough table | to be considered table |
      +| Not enough table | to be considered table |
      +
      +| Just enough table | to be considered table |
      +| ----------------- | ---------------------- |
      +
      +| ---- | --- |
      +
      +|x|
      +|-|
      +
      +| xyz |
      +| --- |
      +.
      +<p>| Not enough table | to be considered table |</p>
      +<p>| Not enough table | to be considered table |
      +| Not enough table | to be considered table |</p>
      +<table>
      +<thead>
      +<tr>
      +<th>Just enough table</th>
      +<th>to be considered table</th>
      +</tr>
      +</thead>
      +</table>
      +<p>| ---- | --- |</p>
      +<table>
      +<thead>
      +<tr>
      +<th>x</th>
      +</tr>
      +</thead>
      +</table>
      +<table>
      +<thead>
      +<tr>
      +<th>xyz</th>
      +</tr>
      +</thead>
      +</table>
      +````````````````````````````````
      +
      +A "simpler" table, GFM style:
      +
      +```````````````````````````````` example
      +abc | def
      +--- | ---
      +xyz | ghi
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>abc</th>
      +<th>def</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>xyz</td>
      +<td>ghi</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +We are making the parser slighly more lax here. Here is a table with spaces at
      +the end:
      +
      +```````````````````````````````` example
      +Hello!
      +
      +| _abc_ | セン |
      +| ----- | ---- |
      +| this row has a space at the end | | 
      +| But _**inline elements do**_. | x |
      +
      +Hi!
      +.
      +<p>Hello!</p>
      +<table>
      +<thead>
      +<tr>
      +<th><em>abc</em></th>
      +<th>セン</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>this row has a space at the end</td>
      +<td></td>
      +</tr>
      +<tr>
      +<td>But <em><strong>inline elements do</strong></em>.</td>
      +<td>x</td>
      +</tr>
      +</tbody>
      +</table>
      +<p>Hi!</p>
      +````````````````````````````````
      +
      +Table alignment:
      +
      +```````````````````````````````` example
      +aaa | bbb | ccc | ddd | eee
      +:-- | --- | :-: | --- | --:
      +fff | ggg | hhh | iii | jjj
      +.
      +<table>
      +<thead>
      +<tr>
      +<th align="left">aaa</th>
      +<th>bbb</th>
      +<th align="center">ccc</th>
      +<th>ddd</th>
      +<th align="right">eee</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td align="left">fff</td>
      +<td>ggg</td>
      +<td align="center">hhh</td>
      +<td>iii</td>
      +<td align="right">jjj</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +### Table cell count mismatches
      +
      +The header and marker row must match.
      +
      +```````````````````````````````` example
      +| a | b | c |
      +| --- | --- |
      +| this | isn't | okay |
      +.
      +<p>| a | b | c |
      +| --- | --- |
      +| this | isn't | okay |</p>
      +````````````````````````````````
      +
      +But any of the body rows can be shorter. Rows longer
      +than the header are truncated.
      +
      +```````````````````````````````` example
      +| a | b | c |
      +| --- | --- | ---
      +| x
      +| a | b
      +| 1 | 2 | 3 | 4 | 5 |
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>a</th>
      +<th>b</th>
      +<th>c</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>x</td>
      +<td></td>
      +<td></td>
      +</tr>
      +<tr>
      +<td>a</td>
      +<td>b</td>
      +<td></td>
      +</tr>
      +<tr>
      +<td>1</td>
      +<td>2</td>
      +<td>3</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +### Embedded pipes
      +
      +Tables with embedded pipes could be tricky.
      +
      +```````````````````````````````` example
      +| a | b |
      +| --- | --- |
      +| Escaped pipes are \|okay\|. | Like \| this. |
      +| Within `\|code\| is okay` too. |
      +| _**`c\|`**_ \| complex
      +| don't **\_reparse\_**
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>a</th>
      +<th>b</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>Escaped pipes are |okay|.</td>
      +<td>Like | this.</td>
      +</tr>
      +<tr>
      +<td>Within <code>|code| is okay</code> too.</td>
      +<td></td>
      +</tr>
      +<tr>
      +<td><em><strong><code>c|</code></strong></em> | complex</td>
      +<td></td>
      +</tr>
      +<tr>
      +<td>don't <strong>_reparse_</strong></td>
      +<td></td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +### Oddly-formatted markers
      +
      +This shouldn't assert.
      +
      +```````````````````````````````` example
      +| a |
      +--- |
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>a</th>
      +</tr>
      +</thead>
      +</table>
      +````````````````````````````````
      +
      +### Escaping
      +
      +```````````````````````````````` example
      +| a | b |
      +| --- | --- |
      +| \\ | `\\` |
      +| \\\\ | `\\\\` |
      +| \_ | `\_` |
      +| \| | `\|` |
      +| \a | `\a` |
      +
      +\\ `\\`
      +
      +\\\\ `\\\\`
      +
      +\_ `\_`
      +
      +\| `\|`
      +
      +\a `\a`
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>a</th>
      +<th>b</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>\</td>
      +<td><code>\\</code></td>
      +</tr>
      +<tr>
      +<td>\\</td>
      +<td><code>\\\\</code></td>
      +</tr>
      +<tr>
      +<td>_</td>
      +<td><code>\_</code></td>
      +</tr>
      +<tr>
      +<td>|</td>
      +<td><code>|</code></td>
      +</tr>
      +<tr>
      +<td>\a</td>
      +<td><code>\a</code></td>
      +</tr>
      +</tbody>
      +</table>
      +<p>\ <code>\\</code></p>
      +<p>\\ <code>\\\\</code></p>
      +<p>_ <code>\_</code></p>
      +<p>| <code>\|</code></p>
      +<p>\a <code>\a</code></p>
      +````````````````````````````````
      +
      +### Embedded HTML
      +
      +```````````````````````````````` example
      +| a |
      +| --- |
      +| <strong>hello</strong> |
      +| ok <br> sure |
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>a</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td><strong>hello</strong></td>
      +</tr>
      +<tr>
      +<td>ok <br> sure</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +### Reference-style links
      +
      +```````````````````````````````` example
      +Here's a link to [Freedom Planet 2][].
      +
      +| Here's a link to [Freedom Planet 2][] in a table header. |
      +| --- |
      +| Here's a link to [Freedom Planet 2][] in a table row. |
      +
      +[Freedom Planet 2]: http://www.freedomplanet2.com/
      +.
      +<p>Here's a link to <a href="http://www.freedomplanet2.com/">Freedom Planet 2</a>.</p>
      +<table>
      +<thead>
      +<tr>
      +<th>Here's a link to <a href="http://www.freedomplanet2.com/">Freedom Planet 2</a> in a table header.</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>Here's a link to <a href="http://www.freedomplanet2.com/">Freedom Planet 2</a> in a table row.</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +### Sequential cells
      +
      +```````````````````````````````` example
      +| a | b | c |
      +| --- | --- | --- |
      +| d || e |
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>a</th>
      +<th>b</th>
      +<th>c</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>d</td>
      +<td></td>
      +<td>e</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +### Interaction with emphasis
      +
      +```````````````````````````````` example
      +| a | b |
      +| --- | --- |
      +|***(a)***|
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>a</th>
      +<th>b</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td><em><strong>(a)</strong></em></td>
      +<td></td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +### a table can be recognised when separated from a paragraph of text without an empty line
      +
      +```````````````````````````````` example
      +123
      +456
      +| a | b |
      +| ---| --- |
      +d | e
      +.
      +<p>123
      +456</p>
      +<table>
      +<thead>
      +<tr>
      +<th>a</th>
      +<th>b</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>d</td>
      +<td>e</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +## Strikethroughs
      +
      +A well-formed strikethrough.
      +
      +```````````````````````````````` example
      +A proper ~strikethrough~.
      +.
      +<p>A proper <del>strikethrough</del>.</p>
      +````````````````````````````````
      +
      +Some strikethrough edge cases.
      +
      +```````````````````````````````` example
      +These are ~not strikethroughs.
      +
      +No, they are not~
      +
      +This ~is ~ legit~ isn't ~ legit.
      +
      +This is not ~~~~~one~~~~~ huge strikethrough.
      +
      +~one~ ~~two~~ ~~~three~~~
      +
      +No ~mismatch~~
      +.
      +<p>These are ~not strikethroughs.</p>
      +<p>No, they are not~</p>
      +<p>This <del>is ~ legit</del> isn't ~ legit.</p>
      +<p>This is not ~~~~~one~~~~~ huge strikethrough.</p>
      +<p><del>one</del> <del>two</del> ~~~three~~~</p>
      +<p>No ~mismatch~~</p>
      +````````````````````````````````
      +
      +Using 200 tilde since it overflows the internal buffer
      +size (100) for parsing delimiters in inlines.c
      +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~striked~
      +
      +## Autolinks
      +
      +```````````````````````````````` example
      +: http://google.com https://google.com
      +
      +<http://google.com/å> http://google.com/å
      +
      +scyther@pokemon.com
      +
      +www.github.com www.github.com/á
      +
      +www.google.com/a_b
      +
      +**Autolink and http://inlines**
      +
      +![http://inline.com/image](http://inline.com/image)
      +
      +a.w@b.c
      +
      +Full stop outside parens shouldn't be included http://google.com/ok.
      +
      +(Full stop inside parens shouldn't be included http://google.com/ok.)
      +
      +"http://google.com"
      +
      +'http://google.com'
      +
      +http://🍄.ga/ http://x🍄.ga/
      +.
      +<p>: <a href="http://google.com">http://google.com</a> <a href="https://google.com">https://google.com</a></p>
      +<p><a href="http://google.com/%C3%A5">http://google.com/å</a> <a href="http://google.com/%C3%A5">http://google.com/å</a></p>
      +<p><a href="mailto:scyther@pokemon.com">scyther@pokemon.com</a></p>
      +<p><a href="http://www.github.com">www.github.com</a> <a href="http://www.github.com/%C3%A1">www.github.com/á</a></p>
      +<p><a href="http://www.google.com/a_b">www.google.com/a_b</a></p>
      +<p><strong>Autolink and <a href="http://inlines">http://inlines</a></strong></p>
      +<p><img src="http://inline.com/image" alt="http://inline.com/image" /></p>
      +<p><a href="mailto:a.w@b.c">a.w@b.c</a></p>
      +<p>Full stop outside parens shouldn't be included <a href="http://google.com/ok">http://google.com/ok</a>.</p>
      +<p>(Full stop inside parens shouldn't be included <a href="http://google.com/ok">http://google.com/ok</a>.)</p>
      +<p>&quot;<a href="http://google.com">http://google.com</a>&quot;</p>
      +<p>'<a href="http://google.com">http://google.com</a>'</p>
      +<p><a href="http://%F0%9F%8D%84.ga/">http://🍄.ga/</a> <a href="http://x%F0%9F%8D%84.ga/">http://x🍄.ga/</a></p>
      +````````````````````````````````
      +
      +```````````````````````````````` example
      +This shouldn't crash everything: (_A_@_.A
      +.
      +<IGNORE>
      +````````````````````````````````
      +
      +```````````````````````````````` example
      +These should not link:
      +
      +* @a.b.c@. x
      +* n@.  b
      +.
      +<p>These should not link:</p>
      +<ul>
      +<li>@a.b.c@. x</li>
      +<li>n@.  b</li>
      +</ul>
      +````````````````````````````````
      +
      +## HTML tag filter
      +
      +
      +```````````````````````````````` example
      +This is <xmp> not okay, but **this** <strong>is</strong>.
      +
      +<p>This is <xmp> not okay, but **this** <strong>is</strong>.</p>
      +
      +Nope, I won't have <textarea>.
      +
      +<p>No <textarea> here either.</p>
      +
      +<p>This <random /> <thing> is okay</thing> though.</p>
      +
      +Yep, <totally>okay</totally>.
      +
      +<!-- HTML comments are okay, though. -->
      +<!- But we're strict. ->
      +<! No nonsense. >
      +<!-- Leave multiline comments the heck alone, though, okay?
      +Even with {"x":"y"} or 1 > 2 or whatever. Even **markdown**.
      +-->
      +<!--- Support everything CommonMark's parser does. -->
      +<!---->
      +<!--thistoo-->
      +.
      +<p>This is &lt;xmp> not okay, but <strong>this</strong> <strong>is</strong>.</p>
      +<p>This is &lt;xmp> not okay, but **this** <strong>is</strong>.</p>
      +<p>Nope, I won't have &lt;textarea>.</p>
      +<p>No &lt;textarea> here either.</p>
      +<p>This <random /> <thing> is okay</thing> though.</p>
      +<p>Yep, <totally>okay</totally>.</p>
      +<!-- HTML comments are okay, though. -->
      +<p>&lt;!- But we're strict. -&gt;
      +&lt;! No nonsense. &gt;</p>
      +<!-- Leave multiline comments the heck alone, though, okay?
      +Even with {"x":"y"} or 1 > 2 or whatever. Even **markdown**.
      +-->
      +<!--- Support everything CommonMark's parser does. -->
      +<!---->
      +<!--thistoo-->
      +````````````````````````````````
      +
      +## Footnotes
      +
      +```````````````````````````````` example
      +This is some text![^1]. Other text.[^footnote].
      +
      +Here's a thing[^other-note].
      +
      +And another thing[^codeblock-note].
      +
      +This doesn't have a referent[^nope].
      +
      +
      +[^other-note]:       no code block here (spaces are stripped away)
      +
      +[^codeblock-note]:
      +        this is now a code block (8 spaces indentation)
      +
      +[^1]: Some *bolded* footnote definition.
      +
      +Hi!
      +
      +[^footnote]:
      +    > Blockquotes can be in a footnote.
      +
      +        as well as code blocks
      +
      +    or, naturally, simple paragraphs.
      +
      +[^unused]: This is unused.
      +.
      +<p>This is some text!<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup>. Other text.<sup class="footnote-ref"><a href="#fn2" id="fnref2">2</a></sup>.</p>
      +<p>Here's a thing<sup class="footnote-ref"><a href="#fn3" id="fnref3">3</a></sup>.</p>
      +<p>And another thing<sup class="footnote-ref"><a href="#fn4" id="fnref4">4</a></sup>.</p>
      +<p>This doesn't have a referent[^nope].</p>
      +<p>Hi!</p>
      +<section class="footnotes">
      +<ol>
      +<li id="fn1">
      +<p>Some <em>bolded</em> footnote definition. <a href="#fnref1" class="footnote-backref">↩</a></p>
      +</li>
      +<li id="fn2">
      +<blockquote>
      +<p>Blockquotes can be in a footnote.</p>
      +</blockquote>
      +<pre><code>as well as code blocks
      +</code></pre>
      +<p>or, naturally, simple paragraphs. <a href="#fnref2" class="footnote-backref">↩</a></p>
      +</li>
      +<li id="fn3">
      +<p>no code block here (spaces are stripped away) <a href="#fnref3" class="footnote-backref">↩</a></p>
      +</li>
      +<li id="fn4">
      +<pre><code>this is now a code block (8 spaces indentation)
      +</code></pre>
      +<a href="#fnref4" class="footnote-backref">↩</a>
      +</li>
      +</ol>
      +</section>
      +````````````````````````````````
      +
      +## Interop
      +
      +Autolink and strikethrough.
      +
      +```````````````````````````````` example
      +~~www.google.com~~
      +
      +~~http://google.com~~
      +.
      +<p><del><a href="http://www.google.com">www.google.com</a></del></p>
      +<p><del><a href="http://google.com">http://google.com</a></del></p>
      +````````````````````````````````
      +
      +Autolink and tables.
      +
      +```````````````````````````````` example
      +| a | b |
      +| --- | --- |
      +| https://github.com www.github.com | http://pokemon.com |
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>a</th>
      +<th>b</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td><a href="https://github.com">https://github.com</a> <a href="http://www.github.com">www.github.com</a></td>
      +<td><a href="http://pokemon.com">http://pokemon.com</a></td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +## Task lists
      +
      +```````````````````````````````` example
      +- [ ] foo
      +- [x] bar
      +.
      +<ul>
      +<li><input type="checkbox" disabled="" /> foo</li>
      +<li><input type="checkbox" checked="" disabled="" /> bar</li>
      +</ul>
      +````````````````````````````````
      +
      +Show that a task list and a regular list get processed the same in
      +the way that sublists are created. If something works in a list
      +item, then it should work the same way with a task.  The only
      +difference should be the tasklist marker. So, if we use something
      +other than a space or x, it won't be recognized as a task item, and
      +so will be treated as a regular item.
      +
      +```````````````````````````````` example
      +- [x] foo
      +  - [ ] bar
      +  - [x] baz
      +- [ ] bim
      +
      +Show a regular (non task) list to show that it has the same structure
      +- [@] foo
      +  - [@] bar
      +  - [@] baz
      +- [@] bim
      +.
      +<ul>
      +<li><input type="checkbox" checked="" disabled="" /> foo
      +<ul>
      +<li><input type="checkbox" disabled="" /> bar</li>
      +<li><input type="checkbox" checked="" disabled="" /> baz</li>
      +</ul>
      +</li>
      +<li><input type="checkbox" disabled="" /> bim</li>
      +</ul>
      +<p>Show a regular (non task) list to show that it has the same structure</p>
      +<ul>
      +<li>[@] foo
      +<ul>
      +<li>[@] bar</li>
      +<li>[@] baz</li>
      +</ul>
      +</li>
      +<li>[@] bim</li>
      +</ul>
      +````````````````````````````````
      +Use a larger indent -- a task list and a regular list should produce
      +the same structure.
      +
      +```````````````````````````````` example
      +- [x] foo
      +    - [ ] bar
      +    - [x] baz
      +- [ ] bim
      +
      +Show a regular (non task) list to show that it has the same structure
      +- [@] foo
      +    - [@] bar
      +    - [@] baz
      +- [@] bim
      +.
      +<ul>
      +<li><input type="checkbox" checked="" disabled="" /> foo
      +<ul>
      +<li><input type="checkbox" disabled="" /> bar</li>
      +<li><input type="checkbox" checked="" disabled="" /> baz</li>
      +</ul>
      +</li>
      +<li><input type="checkbox" disabled="" /> bim</li>
      +</ul>
      +<p>Show a regular (non task) list to show that it has the same structure</p>
      +<ul>
      +<li>[@] foo
      +<ul>
      +<li>[@] bar</li>
      +<li>[@] baz</li>
      +</ul>
      +</li>
      +<li>[@] bim</li>
      +</ul>
      +````````````````````````````````
      diff --git a/test/fuzzing_dictionary b/test/fuzzing_dictionary
      index b06783c94..448c448f1 100644
      --- a/test/fuzzing_dictionary
      +++ b/test/fuzzing_dictionary
      @@ -47,3 +47,21 @@ tag_open_q="<?"
       tag_sq2_close="]]>"
       tag_xml_q="<?xml?>"
       underscore="_"
      +
      +# GFM specific
      +
      +strikethrough="~~~strike~~~"
      +user_mention="@octocat"
      +email_mention="octocat@github.com"
      +http="http://"
      +https="https://"
      +ftp="ftp://"
      +title_tag="title"
      +textarea_tag="textarea"
      +style_tag="style"
      +xmp_tag="xmp"
      +iframe_tag="iframe"
      +noembed_tag="noembed"
      +noframes_tag="noframes"
      +script_tag="script"
      +plaintext_tag="plaintext"
      diff --git a/test/pathological_tests.py b/test/pathological_tests.py
      index e96c33340..4d4d38939 100644
      --- a/test/pathological_tests.py
      +++ b/test/pathological_tests.py
      @@ -5,21 +5,33 @@
       import argparse
       import sys
       import platform
      +import itertools
       import multiprocessing
      -import time
       from cmark import CMark
       
      -if __name__ == "__main__":
      -    parser = argparse.ArgumentParser(description='Run cmark tests.')
      -    parser.add_argument('--program', dest='program', nargs='?', default=None,
      -            help='program to test')
      -    parser.add_argument('--library-dir', dest='library_dir', nargs='?',
      -            default=None, help='directory containing dynamic library')
      -    args = parser.parse_args(sys.argv[1:])
      +def hash_collisions():
      +    REFMAP_SIZE = 16
      +    COUNT = 50000
       
      -allowed_failures = {"many references": True}
      +    def badhash(ref):
      +        h = 0
      +        for c in ref:
      +            a = (h << 6) & 0xFFFFFFFF
      +            b = (h << 16) & 0xFFFFFFFF
      +            h = ord(c) + a + b - h
      +            h = h & 0xFFFFFFFF
      +
      +        return (h % REFMAP_SIZE) == 0
      +
      +    keys = ("x%d" % i for i in itertools.count())
      +    collisions = itertools.islice((k for k in keys if badhash(k)), COUNT)
      +    bad_key = next(collisions)
       
      -cmark = CMark(prog=args.program, library_dir=args.library_dir)
      +    document = ''.join("[%s]: /url\n\n[%s]\n\n" % (key, bad_key) for key in collisions)
      +
      +    return document, re.compile("(<p>\[%s\]</p>\n){%d}" % (bad_key, COUNT-1))
      +
      +allowed_failures = {"many references": True}
       
       # list of pairs consisting of input and a regex that must match the output.
       pathological = {
      @@ -75,65 +87,68 @@
           "unclosed links B":
                        ("[a](b" * 30000,
                         re.compile("(\[a\]\(b){30000}")),
      +    "tables":
      +                 ("aaa\rbbb\n-\v\n" * 30000,
      +                  re.compile("^<p>aaa</p>\n<table>\n<thead>\n<tr>\n<th>bbb</th>\n</tr>\n</thead>\n<tbody>\n(<tr>\n<td>aaa</td>\n</tr>\n<tr>\n<td>bbb</td>\n</tr>\n<tr>\n<td>-\x0b</td>\n</tr>\n){29999}</tbody>\n</table>\n$")),
       #    "many references":
       #                 ("".join(map(lambda x: ("[" + str(x) + "]: u\n"), range(1,5000 * 16))) + "[0] " * 5000,
      -#                  re.compile("(\[0\] ){4999}"))
      +#                  re.compile("(\[0\] ){4999}")),
      +    "reference collisions": hash_collisions()
           }
       
       whitespace_re = re.compile('/s+/')
      +passed = 0
      +errored = 0
      +ignored = 0
      +TIMEOUT = 5
       
      -results = {'passed': [], 'errored': [], 'failed': [], 'ignored': []}
      +def run_test(inp, regex):
      +    parser = argparse.ArgumentParser(description='Run cmark tests.')
      +    parser.add_argument('--program', dest='program', nargs='?', default=None,
      +            help='program to test')
      +    parser.add_argument('--library-dir', dest='library_dir', nargs='?',
      +            default=None, help='directory containing dynamic library')
      +    args = parser.parse_args(sys.argv[1:])
      +    cmark = CMark(prog=args.program, library_dir=args.library_dir, extensions="table")
       
      -def run_pathological_test(description, results):
      -    (inp, regex) = pathological[description]
           [rc, actual, err] = cmark.to_html(inp)
      -    extra = ""
           if rc != 0:
      -        print(description, '[ERRORED (return code %d)]' %rc)
      +        print('[ERRORED (return code %d)]' % rc)
               print(err)
      -        if allowed_failures[description]:
      -            results['ignored'].append(description)
      -        else:
      -            results['errored'].append(description)
      +        exit(1)
           elif regex.search(actual):
      -        print(description, '[PASSED]')
      -        results['passed'].append(description)
      +        print('[PASSED]')
           else:
      -        print(description, '[FAILED]')
      +        print('[FAILED (mismatch)]')
               print(repr(actual))
      -        if allowed_failures[description]:
      -            results['ignored'].append(description)
      -        else:
      -            results['failed'].append(description)
      -
      -print("Testing pathological cases:")
      -for description in pathological:
      -    p = multiprocessing.Process(target=run_pathological_test,
      -              args=(description, results,))
      -    p.start()
      -    # wait 4 seconds or until it finishes
      -    p.join(4)
      -    # kill it if still active
      -    if p.is_alive():
      -        print(description, '[TIMEOUT]')
      -        if allowed_failures[description]:
      -            results['ignored'].append(description)
      +        exit(1)
      +
      +if __name__ == '__main__':
      +    print("Testing pathological cases:")
      +    for description in pathological:
      +        (inp, regex) = pathological[description]
      +        print(description, "... ", end='')
      +        sys.stdout.flush()
      +
      +        p = multiprocessing.Process(target=run_test, args=(inp, regex))
      +        p.start()
      +        p.join(TIMEOUT)
      +
      +        if p.is_alive():
      +            p.terminate()
      +            p.join()
      +            print('[TIMED OUT]')
      +            if allowed_failures[description]:
      +                ignored += 1
      +            else:
      +                errored += 1
      +        elif p.exitcode != 0:
      +            if allowed_failures[description]:
      +                ignored += 1
      +            else:
      +                errored += 1
               else:
      -            results['errored'].append(description)
      -        p.terminate()
      -        p.join()
      -
      -passed  = len(results['passed'])
      -failed  = len(results['failed'])
      -errored = len(results['errored'])
      -ignored = len(results['ignored'])
      -
      -print("%d passed, %d failed, %d errored" % (passed, failed, errored))
      -if ignored > 0:
      -    print("Ignoring these allowed failures:")
      -    for x in results['ignored']:
      -        print(x)
      -if failed == 0 and errored == 0:
      -    exit(0)
      -else:
      -    exit(1)
      +            passed += 1
      +
      +    print("%d passed, %d errored, %d ignored" % (passed, errored, ignored))
      +    exit(errored)
      diff --git a/test/regression.txt b/test/regression.txt
      index 62b1e7efe..d033a4003 100644
      --- a/test/regression.txt
      +++ b/test/regression.txt
      @@ -94,6 +94,111 @@ Issue #192 - escaped spaces in link destination
       <p>[a](te\ st)</p>
       ````````````````````````````````
       
      +Issue github/github#76615:  multiple delimiter combinations gets sketchy
      +
      +
      +```````````````````````````````` example strikethrough
      +~~**_`this`_**~~  
      +~~***`this`***~~  
      +~~___`this`___~~
      +
      +**_`this`_**  
      +***`this`***  
      +___`this`___
      +
      +~~**_this_**~~  
      +~~***this***~~  
      +~~___this___~~
      +
      +**_this_**  
      +***this***  
      +___this___
      +.
      +<p><del><strong><em><code>this</code></em></strong></del><br />
      +<del><em><strong><code>this</code></strong></em></del><br />
      +<del><em><strong><code>this</code></strong></em></del></p>
      +<p><strong><em><code>this</code></em></strong><br />
      +<em><strong><code>this</code></strong></em><br />
      +<em><strong><code>this</code></strong></em></p>
      +<p><del><strong><em>this</em></strong></del><br />
      +<del><em><strong>this</strong></em></del><br />
      +<del><em><strong>this</strong></em></del></p>
      +<p><strong><em>this</em></strong><br />
      +<em><strong>this</strong></em><br />
      +<em><strong>this</strong></em></p>
      +````````````````````````````````
      +
      +Issue #527 - meta tags in inline contexts
      +
      +```````````````````````````````` example
      +City:
      +<span itemprop="contentLocation" itemscope itemtype="https://schema.org/City">
      +  <meta itemprop="name" content="Springfield">
      +</span>
      +.
      +<p>City:
      +<span itemprop="contentLocation" itemscope itemtype="https://schema.org/City">
      +<meta itemprop="name" content="Springfield">
      +</span></p>
      +````````````````````````````````
      +
      +cmark-gfm strikethrough rules
      +
      +```````````````````````````````` example strikethrough
      +~Hi~ Hello, world!
      +.
      +<p><del>Hi</del> Hello, world!</p>
      +````````````````````````````````
      +
      +```````````````````````````````` example strikethrough
      +This ~text~ ~~is~~ ~~~curious~~~.
      +.
      +<p>This <del>text</del> <del>is</del> ~~~curious~~~.</p>
      +````````````````````````````````
      +
      +`~` should not be escaped in href — https://github.com/github/markup/issues/311
      +
      +```````````````````````````````` example
      +[x](http://members.aon.at/~nkehrer/ibm_5110/emu5110.html)
      +.
      +<p><a href="http://members.aon.at/~nkehrer/ibm_5110/emu5110.html">x</a></p>
      +````````````````````````````````
      +
      +Footnotes in tables
      +
      +```````````````````````````````` example table footnotes
      +A footnote in a paragraph[^1]
      +
      +| Column1   | Column2 |
      +| --------- | ------- |
      +| foot [^1] | note    |
      +
      +[^1]: a footnote
      +.
      +<p>A footnote in a paragraph<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup></p>
      +<table>
      +<thead>
      +<tr>
      +<th>Column1</th>
      +<th>Column2</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>foot <sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup></td>
      +<td>note</td>
      +</tr>
      +</tbody>
      +</table>
      +<section class="footnotes">
      +<ol>
      +<li id="fn1">
      +<p>a footnote <a href="#fnref1" class="footnote-backref">↩</a></p>
      +</li>
      +</ol>
      +</section>
      +````````````````````````````````
      +
       Issue #527 - meta tags in inline contexts
       
       ```````````````````````````````` example
      @@ -154,3 +259,13 @@ Issue #289.
       .
       <p>[a](&lt;b) c&gt;</p>
       ````````````````````````````````
      +
      +Pull request #128 - Buffer overread in tables extension
      +
      +```````````````````````````````` example table
      +|
      +-|
      +.
      +<p>|
      +-|</p>
      +````````````````````````````````
      diff --git a/test/roundtrip_tests.py b/test/roundtrip_tests.py
      index a52aa8d83..4fe817fd6 100644
      --- a/test/roundtrip_tests.py
      +++ b/test/roundtrip_tests.py
      @@ -14,6 +14,8 @@
                   default=None, help='limit to sections matching regex pattern')
           parser.add_argument('--library-dir', dest='library_dir', nargs='?',
                   default=None, help='directory containing dynamic library')
      +    parser.add_argument('--extensions', dest='extensions', nargs='?',
      +            default=None, help='space separated list of extensions to enable')
           parser.add_argument('--no-normalize', dest='normalize',
                   action='store_const', const=False, default=True,
                   help='do not normalize HTML')
      @@ -23,11 +25,11 @@
       
       spec = sys.argv[1]
       
      -def converter(md):
      -  cmark = CMark(prog=args.program, library_dir=args.library_dir)
      -  [ec, result, err] = cmark.to_commonmark(md)
      +def converter(md, exts):
      +  cmark = CMark(prog=args.program, library_dir=args.library_dir, extensions=args.extensions)
      +  [ec, result, err] = cmark.to_commonmark(md, exts)
         if ec == 0:
      -    [ec, html, err] = cmark.to_html(result)
      +    [ec, html, err] = cmark.to_html(result, exts)
           if ec == 0:
               # In the commonmark writer we insert dummy HTML
               # comments between lists, and between lists and code
      @@ -44,4 +46,5 @@ def converter(md):
       for test in tests:
           do_test(converter, test, args.normalize, result_counts)
       
      +sys.stdout.buffer.write("{pass} passed, {fail} failed, {error} errored, {skip} skipped\n".format(**result_counts).encode('utf-8'))
       exit(result_counts['fail'] + result_counts['error'])
      diff --git a/test/spec.txt b/test/spec.txt
      index 3913de442..582131d70 100644
      --- a/test/spec.txt
      +++ b/test/spec.txt
      @@ -1,6 +1,5 @@
       ---
      -title: CommonMark Spec
      -author: John MacFarlane
      +title: GitHub Flavored Markdown Spec
       version: 0.29
       date: '2019-04-06'
       license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)'
      @@ -8,6 +7,23 @@ license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)'
       
       # Introduction
       
      +## What is GitHub Flavored Markdown?
      +
      +GitHub Flavored Markdown, often shortened as GFM, is the dialect of Markdown
      +that is currently supported for user content on GitHub.com and GitHub
      +Enterprise.
      +
      +This formal specification, based on the CommonMark Spec, defines the syntax and
      +semantics of this dialect.
      +
      +GFM is a strict superset of CommonMark. All the features which are supported in
      +GitHub user content and that are not specified on the original CommonMark Spec
      +are hence known as **extensions**, and highlighted as such.
      +
      +While GFM supports a wide range of inputs, it's worth noting that GitHub.com
      +and GitHub Enterprise perform additional post-processing and sanitization after
      +GFM is converted to HTML to ensure security and consistency of the website.
      +
       ## What is Markdown?
       
       Markdown is a plain text format for writing structured documents,
      @@ -3289,7 +3305,215 @@ aaa
       <h1>aaa</h1>
       ````````````````````````````````
       
      +<div class="extension">
      +
      +## Tables (extension)
      +
      +GFM enables the `table` extension, where an additional leaf block type is
      +available.
      +
      +A [table](@) is an arrangement of data with rows and columns, consisting of a
      +single header row, a [delimiter row] separating the header from the data, and
      +zero or more data rows.
      +
      +Each row consists of cells containing arbitrary text, in which [inlines] are
      +parsed, separated by pipes (`|`).  A leading and trailing pipe is also
      +recommended for clarity of reading, and if there's otherwise parsing ambiguity.
      +Spaces between pipes and cell content are trimmed.  Block-level elements cannot
      +be inserted in a table.
      +
      +The [delimiter row](@) consists of cells whose only content are hyphens (`-`),
      +and optionally, a leading or trailing colon (`:`), or both, to indicate left,
      +right, or center alignment respectively.
      +
      +```````````````````````````````` example table
      +| foo | bar |
      +| --- | --- |
      +| baz | bim |
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>foo</th>
      +<th>bar</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>baz</td>
      +<td>bim</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +Cells in one column don't need to match length, though it's easier to read if
      +they are. Likewise, use of leading and trailing pipes may be inconsistent:
      +
      +```````````````````````````````` example table
      +| abc | defghi |
      +:-: | -----------:
      +bar | baz
      +.
      +<table>
      +<thead>
      +<tr>
      +<th align="center">abc</th>
      +<th align="right">defghi</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td align="center">bar</td>
      +<td align="right">baz</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +Include a pipe in a cell's content by escaping it, including inside other
      +inline spans:
      +
      +```````````````````````````````` example table
      +| f\|oo  |
      +| ------ |
      +| b `\|` az |
      +| b **\|** im |
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>f|oo</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>b <code>|</code> az</td>
      +</tr>
      +<tr>
      +<td>b <strong>|</strong> im</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +The table is broken at the first empty line, or beginning of another
      +block-level structure:
      +
      +```````````````````````````````` example table
      +| abc | def |
      +| --- | --- |
      +| bar | baz |
      +> bar
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>abc</th>
      +<th>def</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>bar</td>
      +<td>baz</td>
      +</tr>
      +</tbody>
      +</table>
      +<blockquote>
      +<p>bar</p>
      +</blockquote>
      +````````````````````````````````
      +
      +```````````````````````````````` example table
      +| abc | def |
      +| --- | --- |
      +| bar | baz |
      +bar
       
      +bar
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>abc</th>
      +<th>def</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>bar</td>
      +<td>baz</td>
      +</tr>
      +<tr>
      +<td>bar</td>
      +<td></td>
      +</tr>
      +</tbody>
      +</table>
      +<p>bar</p>
      +````````````````````````````````
      +
      +The header row must match the [delimiter row] in the number of cells.  If not,
      +a table will not be recognized:
      +
      +```````````````````````````````` example table
      +| abc | def |
      +| --- |
      +| bar |
      +.
      +<p>| abc | def |
      +| --- |
      +| bar |</p>
      +````````````````````````````````
      +
      +The remainder of the table's rows may vary in the number of cells.  If there
      +are a number of cells fewer than the number of cells in the header row, empty
      +cells are inserted.  If there are greater, the excess is ignored:
      +
      +```````````````````````````````` example table
      +| abc | def |
      +| --- | --- |
      +| bar |
      +| bar | baz | boo |
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>abc</th>
      +<th>def</th>
      +</tr>
      +</thead>
      +<tbody>
      +<tr>
      +<td>bar</td>
      +<td></td>
      +</tr>
      +<tr>
      +<td>bar</td>
      +<td>baz</td>
      +</tr>
      +</tbody>
      +</table>
      +````````````````````````````````
      +
      +If there are no rows in the body, no `<tbody>` is generated in HTML output:
      +
      +```````````````````````````````` example table
      +| abc | def |
      +| --- | --- |
      +.
      +<table>
      +<thead>
      +<tr>
      +<th>abc</th>
      +<th>def</th>
      +</tr>
      +</thead>
      +</table>
      +````````````````````````````````
      +
      +</div>
       
       # Container blocks
       
      @@ -3767,10 +3991,10 @@ The following rules define [list items]:
           Exceptions:
       
           1. When the first list item in a [list] interrupts
      -       a paragraph---that is, when it starts on a line that would
      -       otherwise count as [paragraph continuation text]---then (a)
      -       the lines *Ls* must not begin with a blank line, and (b) if
      -       the list item is ordered, the start number must be 1.
      +    a paragraph---that is, when it starts on a line that would
      +    otherwise count as [paragraph continuation text]---then (a)
      +    the lines *Ls* must not begin with a blank line, and (b) if
      +    the list item is ordered, the start number must be 1.
           2. If any line is a [thematic break][thematic breaks] then
              that line is not a list item.
       
      @@ -4858,6 +5082,63 @@ that in such cases, we require one space indentation from the list marker
       four-space rule in cases where the list marker plus its initial indentation
       takes four spaces (a common case), but diverge in other cases.
       
      +<div class="extension">
      +
      +## Task list items (extension)
      +
      +GFM enables the `tasklist` extension, where an additional processing step is
      +performed on [list items].
      +
      +A [task list item](@) is a [list item][list items] where the first block in it
      +is a paragraph which begins with a [task list item marker] and at least one
      +whitespace character before any other content.
      +
      +A [task list item marker](@) consists of an optional number of spaces, a left
      +bracket (`[`), either a whitespace character or the letter `x` in either
      +lowercase or uppercase, and then a right bracket (`]`).
      +
      +When rendered, the [task list item marker] is replaced with a semantic checkbox element;
      +in an HTML output, this would be an `<input type="checkbox">` element.
      +
      +If the character between the brackets is a whitespace character, the checkbox
      +is unchecked.  Otherwise, the checkbox is checked.
      +
      +This spec does not define how the checkbox elements are interacted with: in practice,
      +implementors are free to render the checkboxes as disabled or inmutable elements,
      +or they may dynamically handle dynamic interactions (i.e. checking, unchecking) in
      +the final rendered document.
      +
      +```````````````````````````````` example disabled
      +- [ ] foo
      +- [x] bar
      +.
      +<ul>
      +<li><input disabled="" type="checkbox"> foo</li>
      +<li><input checked="" disabled="" type="checkbox"> bar</li>
      +</ul>
      +````````````````````````````````
      +
      +Task lists can be arbitrarily nested:
      +
      +```````````````````````````````` example disabled
      +- [x] foo
      +  - [ ] bar
      +  - [x] baz
      +- [ ] bim
      +.
      +<ul>
      +<li><input checked="" disabled="" type="checkbox"> foo
      +<ul>
      +<li><input disabled="" type="checkbox"> bar</li>
      +<li><input checked="" disabled="" type="checkbox"> baz</li>
      +</ul>
      +</li>
      +<li><input disabled="" type="checkbox"> bim</li>
      +</ul>
      +````````````````````````````````
      +
      +</div>
      +
       ## Lists
       
       A [list](@) is a sequence of one or more
      @@ -7424,6 +7705,34 @@ __a<http://foo.bar/?q=__>
       ````````````````````````````````
       
       
      +<div class="extension">
      +
      +## Strikethrough (extension)
      +
      +GFM enables the `strikethrough` extension, where an additional emphasis type is
      +available.
      +
      +Strikethrough text is any text wrapped in two tildes (`~`).
      +
      +```````````````````````````````` example strikethrough
      +~~Hi~~ Hello, world!
      +.
      +<p><del>Hi</del> Hello, world!</p>
      +````````````````````````````````
      +
      +As with regular emphasis delimiters, a new paragraph will cause strikethrough
      +parsing to cease:
      +
      +```````````````````````````````` example strikethrough
      +This ~~has a
      +
      +new paragraph~~.
      +.
      +<p>This ~~has a</p>
      +<p>new paragraph~~.</p>
      +````````````````````````````````
      +
      +</div>
       
       ## Links
       
      @@ -8881,6 +9190,175 @@ foo@bar.example.com
       <p>foo@bar.example.com</p>
       ````````````````````````````````
       
      +<div class="extension">
      +
      +## Autolinks (extension)
      +
      +GFM enables the `autolink` extension, where autolinks will be recognised in a
      +greater number of conditions.
      +
      +[Autolink]s can also be constructed without requiring the use of `<` and to `>`
      +to delimit them, although they will be recognized under a smaller set of
      +circumstances.  All such recognized autolinks can only come at the beginning of
      +a line, after whitespace, or any of the delimiting characters `*`, `_`, `~`,
      +and `(`.
      +
      +An [extended www autolink](@) will be recognized
      +when the text `www.` is found followed by a [valid domain].
      +A [valid domain](@) consists of segments
      +of alphanumeric characters, underscores (`_`) and hyphens (`-`)
      +separated by periods (`.`).
      +There must be at least one period,
      +and no underscores may be present in the last two segments of the domain.
      +
      +The scheme `http` will be inserted automatically:
      +
      +```````````````````````````````` example autolink
      +www.commonmark.org
      +.
      +<p><a href="http://www.commonmark.org">www.commonmark.org</a></p>
      +````````````````````````````````
      +
      +After a [valid domain], zero or more non-space non-`<` characters may follow:
      +
      +```````````````````````````````` example autolink
      +Visit www.commonmark.org/help for more information.
      +.
      +<p>Visit <a href="http://www.commonmark.org/help">www.commonmark.org/help</a> for more information.</p>
      +````````````````````````````````
      +
      +We then apply [extended autolink path validation](@) as follows:
      +
      +Trailing punctuation (specifically, `?`, `!`, `.`, `,`, `:`, `*`, `_`, and `~`)
      +will not be considered part of the autolink, though they may be included in the
      +interior of the link:
      +
      +```````````````````````````````` example autolink
      +Visit www.commonmark.org.
      +
      +Visit www.commonmark.org/a.b.
      +.
      +<p>Visit <a href="http://www.commonmark.org">www.commonmark.org</a>.</p>
      +<p>Visit <a href="http://www.commonmark.org/a.b">www.commonmark.org/a.b</a>.</p>
      +````````````````````````````````
      +
      +When an autolink ends in `)`, we scan the entire autolink for the total number
      +of parentheses.  If there is a greater number of closing parentheses than
      +opening ones, we don't consider the unmatched trailing parentheses part of the
      +autolink, in order to facilitate including an autolink inside a parenthesis:
      +
      +```````````````````````````````` example autolink
      +www.google.com/search?q=Markup+(business)
      +
      +www.google.com/search?q=Markup+(business)))
      +
      +(www.google.com/search?q=Markup+(business))
      +
      +(www.google.com/search?q=Markup+(business)
      +.
      +<p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
      +<p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>))</p>
      +<p>(<a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>)</p>
      +<p>(<a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
      +````````````````````````````````
      +
      +This check is only done when the link ends in a closing parentheses `)`, so if
      +the only parentheses are in the interior of the autolink, no special rules are
      +applied:
      +
      +```````````````````````````````` example autolink
      +www.google.com/search?q=(business))+ok
      +.
      +<p><a href="http://www.google.com/search?q=(business))+ok">www.google.com/search?q=(business))+ok</a></p>
      +````````````````````````````````
      +
      +If an autolink ends in a semicolon (`;`), we check to see if it appears to
      +resemble an [entity reference][entity references]; if the preceding text is `&`
      +followed by one or more alphanumeric characters.  If so, it is excluded from
      +the autolink:
      +
      +```````````````````````````````` example autolink
      +www.google.com/search?q=commonmark&hl=en
      +
      +www.google.com/search?q=commonmark&hl;
      +.
      +<p><a href="http://www.google.com/search?q=commonmark&amp;hl=en">www.google.com/search?q=commonmark&amp;hl=en</a></p>
      +<p><a href="http://www.google.com/search?q=commonmark">www.google.com/search?q=commonmark</a>&amp;hl;</p>
      +````````````````````````````````
      +
      +`<` immediately ends an autolink.
      +
      +```````````````````````````````` example autolink
      +www.commonmark.org/he<lp
      +.
      +<p><a href="http://www.commonmark.org/he">www.commonmark.org/he</a>&lt;lp</p>
      +````````````````````````````````
      +
      +An [extended url autolink](@) will be recognised when one of the schemes
      +`http://`, `https://`, or `ftp://`, followed by a [valid domain], then zero or
      +more non-space non-`<` characters according to
      +[extended autolink path validation]:
      +
      +```````````````````````````````` example autolink
      +http://commonmark.org
      +
      +(Visit https://encrypted.google.com/search?q=Markup+(business))
      +
      +Anonymous FTP is available at ftp://foo.bar.baz.
      +.
      +<p><a href="http://commonmark.org">http://commonmark.org</a></p>
      +<p>(Visit <a href="https://encrypted.google.com/search?q=Markup+(business)">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>
      +<p>Anonymous FTP is available at <a href="ftp://foo.bar.baz">ftp://foo.bar.baz</a>.</p>
      +````````````````````````````````
      +
      +
      +An [extended email autolink](@) will be recognised when an email address is
      +recognised within any text node.  Email addresses are recognised according to
      +the following rules:
      +
      +* One ore more characters which are alphanumeric, or `.`, `-`, `_`, or `+`.
      +* An `@` symbol.
      +* One or more characters which are alphanumeric, or `-` or `_`,
      +  separated by periods (`.`).
      +  There must be at least one period.
      +  The last character must not be one of `-` or `_`.
      +
      +The scheme `mailto:` will automatically be added to the generated link:
      +
      +```````````````````````````````` example autolink
      +foo@bar.baz
      +.
      +<p><a href="mailto:foo@bar.baz">foo@bar.baz</a></p>
      +````````````````````````````````
      +
      +`+` can occur before the `@`, but not after.
      +
      +```````````````````````````````` example autolink
      +hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is.
      +.
      +<p>hello@mail+xyz.example isn't valid, but <a href="mailto:hello+xyz@mail.example">hello+xyz@mail.example</a> is.</p>
      +````````````````````````````````
      +
      +`.`, `-`, and `_` can occur on both sides of the `@`, but only `.` may occur at
      +the end of the email address, in which case it will not be considered part of
      +the address:
      +
      +```````````````````````````````` example autolink
      +a.b-c_d@a.b
      +
      +a.b-c_d@a.b.
      +
      +a.b-c_d@a.b-
      +
      +a.b-c_d@a.b_
      +.
      +<p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a></p>
      +<p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a>.</p>
      +<p>a.b-c_d@a.b-</p>
      +<p>a.b-c_d@a.b_</p>
      +````````````````````````````````
      +
      +</div>
       
       ## Raw HTML
       
      @@ -9156,6 +9634,45 @@ foo <a href="\*">
       ````````````````````````````````
       
       
      +<div class="extension">
      +
      +## Disallowed Raw HTML (extension)
      +
      +GFM enables the `tagfilter` extension, where the following HTML tags will be
      +filtered when rendering HTML output:
      +
      +* `<title>`
      +* `<textarea>`
      +* `<style>`
      +* `<xmp>`
      +* `<iframe>`
      +* `<noembed>`
      +* `<noframes>`
      +* `<script>`
      +* `<plaintext>`
      +
      +Filtering is done by replacing the leading `<` with the entity `&lt;`.  These
      +tags are chosen in particular as they change how HTML is interpreted in a way
      +unique to them (i.e. nested HTML is interpreted differently), and this is
      +usually undesireable in the context of other rendered Markdown content.
      +
      +All other HTML tags are left untouched.
      +
      +```````````````````````````````` example tagfilter
      +<strong> <title> <style> <em>
      +
      +<blockquote>
      +  <xmp> is disallowed.  <XMP> is also disallowed.
      +</blockquote>
      +.
      +<p><strong> &lt;title> &lt;style> <em></p>
      +<blockquote>
      +  &lt;xmp> is disallowed.  &lt;XMP> is also disallowed.
      +</blockquote>
      +````````````````````````````````
      +
      +</div>
      +
       ## Hard line breaks
       
       A line break (not in a code span or HTML tag) that is preceded
      @@ -9239,10 +9756,10 @@ bar</em></p>
       Line breaks do not occur inside code spans
       
       ```````````````````````````````` example
      -`code 
      +`code  
       span`
       .
      -<p><code>code  span</code></p>
      +<p><code>code   span</code></p>
       ````````````````````````````````
       
       
      diff --git a/test/spec_tests.py b/test/spec_tests.py
      index 9974fe057..194c51043 100755
      --- a/test/spec_tests.py
      +++ b/test/spec_tests.py
      @@ -19,6 +19,8 @@
                   default=None, help='limit to sections matching regex pattern')
           parser.add_argument('--library-dir', dest='library_dir', nargs='?',
                   default=None, help='directory containing dynamic library')
      +    parser.add_argument('--extensions', dest='extensions', nargs='?',
      +            default=None, help='space separated list of extensions to enable')
           parser.add_argument('--no-normalize', dest='normalize',
                   action='store_const', const=False, default=True,
                   help='do not normalize HTML')
      @@ -39,11 +41,14 @@ def print_test_header(headertext, example_number, start_line, end_line):
           out("Example %d (lines %d-%d) %s\n" % (example_number,start_line,end_line,headertext))
       
       def do_test(converter, test, normalize, result_counts):
      -    [retcode, actual_html, err] = converter(test['markdown'])
      +    [retcode, actual_html, err] = converter(test['markdown'], test['extensions'])
      +    actual_html = re.sub(r'\r\n', '\n', actual_html)
           if retcode == 0:
      -        expected_html = test['html']
      +        expected_html = re.sub(r'\r\n', '\n', test['html'])
               unicode_error = None
      -        if normalize:
      +        if expected_html.strip() == '<IGNORE>':
      +            passed = True
      +        elif normalize:
                   try:
                       passed = normalize_html(actual_html) == normalize_html(expected_html)
                   except UnicodeDecodeError as e:
      @@ -82,6 +87,7 @@ def get_tests(specfile):
           markdown_lines = []
           html_lines = []
           state = 0  # 0 regular text, 1 markdown example, 2 html output
      +    extensions = []
           headertext = ''
           tests = []
       
      @@ -91,19 +97,22 @@ def get_tests(specfile):
               for line in specf:
                   line_number = line_number + 1
                   l = line.strip()
      -            if l == "`" * 32 + " example":
      +            if l.startswith("`" * 32 + " example"):
                       state = 1
      +                extensions = l[32 + len(" example"):].split()
                   elif l == "`" * 32:
                       state = 0
                       example_number = example_number + 1
                       end_line = line_number
      -                tests.append({
      -                    "markdown":''.join(markdown_lines).replace('→',"\t"),
      -                    "html":''.join(html_lines).replace('→',"\t"),
      -                    "example": example_number,
      -                    "start_line": start_line,
      -                    "end_line": end_line,
      -                    "section": headertext})
      +                if 'disabled' not in extensions:
      +                    tests.append({
      +                        "markdown":''.join(markdown_lines).replace('→',"\t"),
      +                        "html":''.join(html_lines).replace('→',"\t"),
      +                        "example": example_number,
      +                        "start_line": start_line,
      +                        "end_line": end_line,
      +                        "section": headertext,
      +                        "extensions": extensions})
                       start_line = 0
                       markdown_lines = []
                       html_lines = []
      @@ -131,11 +140,11 @@ def get_tests(specfile):
               pattern_re = re.compile('.')
           tests = [ test for test in all_tests if re.search(pattern_re, test['section']) and (not args.number or test['example'] == args.number) ]
           if args.dump_tests:
      -        out(json.dumps(tests, ensure_ascii=False, indent=2))
      +        out(json.dumps(tests, indent=2))
               exit(0)
           else:
               skipped = len(all_tests) - len(tests)
      -        converter = CMark(prog=args.program, library_dir=args.library_dir).to_html
      +        converter = CMark(prog=args.program, library_dir=args.library_dir, extensions=args.extensions).to_html
               result_counts = {'pass': 0, 'fail': 0, 'error': 0, 'skip': skipped}
               for test in tests:
                   do_test(converter, test, args.normalize, result_counts)
      diff --git a/toolchain-mingw32.cmake b/toolchain-mingw32.cmake
      index 61c62a831..c1c6971d9 100644
      --- a/toolchain-mingw32.cmake
      +++ b/toolchain-mingw32.cmake
      @@ -9,7 +9,7 @@ SET(CMAKE_RC_COMPILER i586-mingw32msvc-windres)
       # here is the target environment located
       SET(CMAKE_FIND_ROOT_PATH  /usr/i586-mingw32msvc "${CMAKE_SOURCE_DIR}/windows")
       
      -# adjust the default behaviour of the FIND_XXX() commands:
      +# adjust the default behaviour of the FIND_XYZ() commands:
       # search headers and libraries in the target environment, search 
       # programs in the host environment
       set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
      diff --git a/tools/Dockerfile b/tools/Dockerfile
      new file mode 100644
      index 000000000..65b7fe99e
      --- /dev/null
      +++ b/tools/Dockerfile
      @@ -0,0 +1,41 @@
      +FROM debian:jessie
      +
      +RUN apt-get update && apt-get install -y \
      +  build-essential \
      +  autoconf \
      +  libtool \
      +  git \
      +  pkg-config \
      +  gdb \
      +  valgrind \
      +  python3 \
      +  wget \
      +  clang \
      +  man \
      +  clang-format-3.5 \
      +  && apt-get clean
      +
      +RUN wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz && \
      +	tar xf afl-latest.tgz && \
      +	cd afl-* && \
      +	make install && \
      +	cd .. && \
      +	rm -rf afl-*
      +
      +RUN wget https://github.com/skvadrik/re2c/releases/download/0.15.3/re2c-0.15.3.tar.gz && \
      +	tar xf re2c-0.15.3.tar.gz && \
      +	cd re2c-* && \
      +	./configure && \
      +	make install && \
      +	cd .. && \
      +	rm -rf re2c-*
      +
      +RUN wget https://cmake.org/files/v3.8/cmake-3.8.2.tar.gz && \
      +	tar xf cmake-3.8.2.tar.gz && \
      +	cd cmake-* && \
      +	./bootstrap && \
      +	make install && \
      +	cd .. && \
      +	rm -rf cmake-*
      +
      +RUN apt-get update && apt-get install -y ninja-build
      diff --git a/tools/xml2md_gfm.xsl b/tools/xml2md_gfm.xsl
      new file mode 100644
      index 000000000..d564b5c13
      --- /dev/null
      +++ b/tools/xml2md_gfm.xsl
      @@ -0,0 +1,80 @@
      +<?xml version="1.0" encoding="UTF-8"?>
      +
      +<!--
      +
      +xml2md_gfm.xsl
      +==============
      +
      +This XSLT stylesheet is a complement to xml2md.xsl with templates supporting GitHub-flavored Markdown extensions (tables, strike-through).
      +
      +-->
      +
      +<xsl:stylesheet
      +    version="1.0"
      +    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      +    xmlns:md="http://commonmark.org/xml/1.0">
      +
      +
      +<!-- Import commonmark XSL -->
      +
      +<xsl:import href="xml2md.xsl"/>
      +<xsl:template match="/">
      +  <xsl:apply-imports/>
      +</xsl:template>
      +
      +<!-- params -->
      +
      +<xsl:output method="text" encoding="utf-8"/>
      +
      +
      +<!-- Table -->
      +
      +<xsl:template match="md:table">
      +    <xsl:apply-templates select="." mode="indent-block"/>
      +    <xsl:apply-templates select="md:*"/>
      +</xsl:template>
      +
      +<xsl:template match="md:table_header">
      +    <xsl:text>| </xsl:text>
      +    <xsl:apply-templates select="md:*"/>
      +    <xsl:text>&#xa; | </xsl:text>
      +     <xsl:for-each select="md:table_cell">
      +     <xsl:choose>
      +     <xsl:when test="@align = 'right'">
      +     <xsl:text> ---: |</xsl:text>
      +     </xsl:when>
      +     <xsl:when test="@align = 'left'">
      +     <xsl:text> :--- |</xsl:text>
      +     </xsl:when>
      +     <xsl:when test="@align = 'center'">
      +     <xsl:text> :---: |</xsl:text>
      +     </xsl:when>
      +     <xsl:otherwise>
      +     <xsl:text> --- |</xsl:text>
      +     </xsl:otherwise>
      +     </xsl:choose>
      +     </xsl:for-each>
      +    <xsl:text>&#xa;</xsl:text>
      +</xsl:template>
      +
      +<xsl:template match="md:table_cell">
      +    <xsl:apply-templates select="md:*"/>
      +    <xsl:text>| </xsl:text>
      +</xsl:template>
      +
      +<xsl:template match="md:table_row">
      +    <xsl:text>| </xsl:text>
      +    <xsl:apply-templates select="md:*"/>
      +    <xsl:text>&#xa;</xsl:text>
      +</xsl:template>
      +
      +
      +<!-- Striked-through -->
      +
      +<xsl:template match="md:strikethrough">
      +    <xsl:text>~~</xsl:text>
      +    <xsl:apply-templates select="md:*"/>
      +    <xsl:text>~~</xsl:text>
      +</xsl:template>
      +
      +</xsl:stylesheet>
      diff --git a/wrappers/wrapper.js b/wrappers/wrapper.js
      new file mode 100644
      index 000000000..0a9b8b5be
      --- /dev/null
      +++ b/wrappers/wrapper.js
      @@ -0,0 +1,6 @@
      +
      +const cmark = require('node-cmark');
      +
      +const markdown = '# h1 title';
      +
      +cmark.markdown2html(markdown);
      diff --git a/wrappers/wrapper_ext.py b/wrappers/wrapper_ext.py
      new file mode 100755
      index 000000000..f08cc2076
      --- /dev/null
      +++ b/wrappers/wrapper_ext.py
      @@ -0,0 +1,109 @@
      +#!/usr/bin/env python
      +
      +#
      +# Example for using the shared library from python.
      +# Will work with either python 2 or python 3.
      +# Requires cmark-gfm and cmark-gfm-extensions libraries to be installed.
      +#
      +# This particular example uses the GitHub extensions from the gfm-extensions
      +# library. EXTENSIONS specifies which to use, and the sample shows how to
      +# connect them into a parser.
      +#
      +
      +import sys
      +import ctypes
      +
      +if sys.platform == 'darwin':
      +    libname = 'libcmark-gfm.dylib'
      +    extname = 'libcmark-gfm-extensions.dylib'
      +elif sys.platform == 'win32':
      +    libname = 'cmark-gfm.dll'
      +    extname = 'cmark-gfm-extensions.dll'
      +else:
      +    libname = 'libcmark-gfm.so'
      +    extname = 'libcmark-gfm-extensions.so'
      +cmark = ctypes.CDLL(libname)
      +cmark_ext = ctypes.CDLL(extname)
      +
      +# Options for the GFM rendering call
      +OPTS = 0  # defaults
      +
      +# The GFM extensions that we want to use
      +EXTENSIONS = (
      +  'autolink',
      +  'table',
      +  'strikethrough',
      +  'tagfilter',
      +  )
      +
      +# Use ctypes to access the functions in libcmark-gfm
      +
      +F_cmark_parser_new = cmark.cmark_parser_new
      +F_cmark_parser_new.restype = ctypes.c_void_p
      +F_cmark_parser_new.argtypes = (ctypes.c_int,)
      +
      +F_cmark_parser_feed = cmark.cmark_parser_feed
      +F_cmark_parser_feed.restype = None
      +F_cmark_parser_feed.argtypes = (ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t)
      +
      +F_cmark_parser_finish = cmark.cmark_parser_finish
      +F_cmark_parser_finish.restype = ctypes.c_void_p
      +F_cmark_parser_finish.argtypes = (ctypes.c_void_p,)
      +
      +F_cmark_parser_attach_syntax_extension = cmark.cmark_parser_attach_syntax_extension
      +F_cmark_parser_attach_syntax_extension.restype = ctypes.c_int
      +F_cmark_parser_attach_syntax_extension.argtypes = (ctypes.c_void_p, ctypes.c_void_p)
      +
      +F_cmark_parser_get_syntax_extensions = cmark.cmark_parser_get_syntax_extensions
      +F_cmark_parser_get_syntax_extensions.restype = ctypes.c_void_p
      +F_cmark_parser_get_syntax_extensions.argtypes = (ctypes.c_void_p,)
      +
      +F_cmark_parser_free = cmark.cmark_parser_free
      +F_cmark_parser_free.restype = None
      +F_cmark_parser_free.argtypes = (ctypes.c_void_p,)
      +
      +F_cmark_node_free = cmark.cmark_node_free
      +F_cmark_node_free.restype = None
      +F_cmark_node_free.argtypes = (ctypes.c_void_p,)
      +
      +F_cmark_find_syntax_extension = cmark.cmark_find_syntax_extension
      +F_cmark_find_syntax_extension.restype = ctypes.c_void_p
      +F_cmark_find_syntax_extension.argtypes = (ctypes.c_char_p,)
      +
      +F_cmark_render_html = cmark.cmark_render_html
      +F_cmark_render_html.restype = ctypes.c_char_p
      +F_cmark_render_html.argtypes = (ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p)
      +
      +
      +# Set up the libcmark-gfm library and its extensions
      +F_register = cmark_ext.cmark_gfm_core_extensions_ensure_registered
      +F_register.restype = None
      +F_register.argtypes = ( )
      +F_register()
      +
      +
      +def md2html(text):
      +  "Use cmark-gfm to render the Markdown into an HTML fragment."
      +
      +  parser = F_cmark_parser_new(OPTS)
      +  assert parser
      +  for name in EXTENSIONS:
      +    ext = F_cmark_find_syntax_extension(name)
      +    assert ext
      +    rv = F_cmark_parser_attach_syntax_extension(parser, ext)
      +    assert rv
      +  exts = F_cmark_parser_get_syntax_extensions(parser)
      +
      +  F_cmark_parser_feed(parser, text, len(text))
      +  doc = F_cmark_parser_finish(parser)
      +  assert doc
      +
      +  output = F_cmark_render_html(doc, OPTS, exts)
      +
      +  F_cmark_parser_free(parser)
      +  F_cmark_node_free(doc)
      +
      +  return output
      +
      +
      +sys.stdout.write(md2html(sys.stdin.read()))