From 9e349fb1a9d3fb3e124cc7f66a8a695938407b21 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Mon, 21 Sep 2026 10:11:28 -0300 Subject: [PATCH 1/2] Upgrade Sourcemeta dependencies Signed-off-by: Juan Cruz Viotti --- DEPENDENCIES | 4 +- vendor/blaze/DEPENDENCIES | 2 +- vendor/blaze/config.cmake.in | 19 +- vendor/blaze/schemas/canonical-draft3.json | 7 + .../rules/type_with_applicator_to_extends.h | 47 +- .../src/compiler/default_compiler_draft3.h | 105 +- vendor/blaze/src/compiler/unevaluated.cc | 64 +- vendor/blaze/src/convert/CMakeLists.txt | 1 + vendor/blaze/src/convert/convert.cc | 4 +- vendor/blaze/src/convert/helpers.h | 131 +- .../src/convert/rules/metaschema_vocabulary.h | 99 + .../rules/upgrade_2019_09_to_2020_12.h | 54 +- .../rules/upgrade_dialect_override_cleanup.h | 88 +- .../rules/upgrade_draft_3_to_draft_4.h | 2 +- .../rules/upgrade_draft_4_to_draft_6.h | 18 +- .../rules/upgrade_draft_6_to_draft_7.h | 2 +- .../rules/upgrade_draft_7_to_draft_2019_09.h | 89 +- vendor/core/CMakeLists.txt | 17 +- vendor/core/DEPENDENCIES | 2 - vendor/core/cmake/FindCMarkGFM.cmake | 121 - vendor/core/cmake/FindGoogleBenchmark.cmake | 24 - vendor/core/cmake/Sourcemeta.cmake | 2 +- vendor/core/cmake/common/clang-tidy.cmake | 25 +- .../core/cmake/common/targets/benchmark.cmake | 14 + .../common/targets/googlebenchmark.cmake | 14 - vendor/core/config.cmake.in | 22 + vendor/core/src/core/dns/hostname.cc | 77 +- .../core/dns/include/sourcemeta/core/dns.h | 19 + vendor/core/src/core/email/email.cc | 33 + .../email/include/sourcemeta/core/email.h | 23 + vendor/core/src/core/gzip/deflate.h | 6 +- vendor/core/src/core/gzip/inflate.h | 2 +- vendor/core/src/core/html/escape.cc | 111 +- .../include/sourcemeta/core/html_buffer.h | 104 +- .../include/sourcemeta/core/html_escape.h | 138 +- .../include/sourcemeta/core/html_writer.h | 176 +- vendor/core/src/core/html/writer.cc | 47 +- .../core/src/core/jsonschema/CMakeLists.txt | 2 +- vendor/core/src/core/jsonschema/format.cc | 125 + vendor/core/src/core/jsonschema/frame.cc | 70 +- .../include/sourcemeta/core/jsonschema.h | 36 + .../core/src/core/jsonschema/known_walker.cc | 270 +- vendor/core/src/core/markdown/CMakeLists.txt | 9 +- vendor/core/src/core/markdown/blocks.h | 1336 ++ vendor/core/src/core/markdown/characters.h | 270 + vendor/core/src/core/markdown/document.h | 278 + .../include/sourcemeta/core/markdown.h | 10 +- .../include/sourcemeta/core/markdown_error.h | 47 + vendor/core/src/core/markdown/inlines.h | 1244 ++ vendor/core/src/core/markdown/markdown.cc | 124 +- vendor/core/src/core/markdown/postprocess.h | 524 + vendor/core/src/core/markdown/references.h | 310 + vendor/core/src/core/markdown/render.h | 625 + vendor/core/src/core/markdown/scanners.h | 857 + .../unicode/include/sourcemeta/core/unicode.h | 47 +- .../core/uri/include/sourcemeta/core/uri.h | 104 +- vendor/core/src/core/uri/parse.cc | 93 + vendor/core/src/lang/benchmark/CMakeLists.txt | 49 + vendor/core/src/lang/benchmark/benchmark.cc | 420 + .../core/src/lang/benchmark/benchmark_main.cc | 5 + .../include/sourcemeta/core/benchmark.h | 281 + vendor/core/src/lang/numeric/decimal.cc | 3 - .../lang/text/include/sourcemeta/core/text.h | 102 +- vendor/core/vendor/cmark-gfm/COPYING | 170 - .../vendor/cmark-gfm/extensions/autolink.c | 508 - .../vendor/cmark-gfm/extensions/autolink.h | 8 - .../extensions/cmark-gfm-core-extensions.h | 54 - .../cmark-gfm/extensions/core-extensions.c | 27 - .../cmark-gfm/extensions/ext_scanners.c | 879 - .../cmark-gfm/extensions/ext_scanners.h | 24 - .../cmark-gfm/extensions/ext_scanners.re | 92 - .../cmark-gfm/extensions/strikethrough.c | 167 - .../cmark-gfm/extensions/strikethrough.h | 9 - .../core/vendor/cmark-gfm/extensions/table.c | 917 - .../core/vendor/cmark-gfm/extensions/table.h | 12 - .../vendor/cmark-gfm/extensions/tagfilter.c | 60 - .../vendor/cmark-gfm/extensions/tagfilter.h | 8 - .../vendor/cmark-gfm/extensions/tasklist.c | 156 - .../vendor/cmark-gfm/extensions/tasklist.h | 8 - vendor/core/vendor/cmark-gfm/src/arena.c | 104 - vendor/core/vendor/cmark-gfm/src/blocks.c | 1622 -- vendor/core/vendor/cmark-gfm/src/buffer.c | 278 - vendor/core/vendor/cmark-gfm/src/buffer.h | 116 - .../vendor/cmark-gfm/src/case_fold_switch.inc | 4327 ----- vendor/core/vendor/cmark-gfm/src/chunk.h | 135 - .../cmark-gfm/src/cmark-gfm-extension_api.h | 737 - vendor/core/vendor/cmark-gfm/src/cmark-gfm.h | 833 - .../cmark-gfm/src/cmark-gfm_version.h.in | 7 - vendor/core/vendor/cmark-gfm/src/cmark.c | 55 - .../core/vendor/cmark-gfm/src/cmark_ctype.c | 44 - .../core/vendor/cmark-gfm/src/cmark_ctype.h | 33 - vendor/core/vendor/cmark-gfm/src/commonmark.c | 514 - vendor/core/vendor/cmark-gfm/src/config.h.in | 76 - vendor/core/vendor/cmark-gfm/src/entities.inc | 2138 --- vendor/core/vendor/cmark-gfm/src/footnotes.c | 63 - vendor/core/vendor/cmark-gfm/src/footnotes.h | 27 - vendor/core/vendor/cmark-gfm/src/houdini.h | 57 - .../vendor/cmark-gfm/src/houdini_href_e.c | 100 - .../vendor/cmark-gfm/src/houdini_html_e.c | 66 - .../vendor/cmark-gfm/src/houdini_html_u.c | 149 - vendor/core/vendor/cmark-gfm/src/html.c | 502 - vendor/core/vendor/cmark-gfm/src/html.h | 27 - vendor/core/vendor/cmark-gfm/src/inlines.c | 1788 -- vendor/core/vendor/cmark-gfm/src/inlines.h | 29 - vendor/core/vendor/cmark-gfm/src/iterator.c | 159 - vendor/core/vendor/cmark-gfm/src/iterator.h | 26 - vendor/core/vendor/cmark-gfm/src/latex.c | 468 - .../core/vendor/cmark-gfm/src/linked_list.c | 37 - vendor/core/vendor/cmark-gfm/src/main.c | 328 - vendor/core/vendor/cmark-gfm/src/man.c | 274 - vendor/core/vendor/cmark-gfm/src/map.c | 129 - vendor/core/vendor/cmark-gfm/src/map.h | 44 - vendor/core/vendor/cmark-gfm/src/node.c | 1045 -- vendor/core/vendor/cmark-gfm/src/node.h | 167 - vendor/core/vendor/cmark-gfm/src/parser.h | 59 - vendor/core/vendor/cmark-gfm/src/plaintext.c | 218 - vendor/core/vendor/cmark-gfm/src/plugin.c | 36 - vendor/core/vendor/cmark-gfm/src/plugin.h | 34 - vendor/core/vendor/cmark-gfm/src/references.c | 43 - vendor/core/vendor/cmark-gfm/src/references.h | 26 - vendor/core/vendor/cmark-gfm/src/registry.c | 63 - vendor/core/vendor/cmark-gfm/src/registry.h | 24 - vendor/core/vendor/cmark-gfm/src/render.c | 213 - vendor/core/vendor/cmark-gfm/src/render.h | 62 - vendor/core/vendor/cmark-gfm/src/scanners.c | 14056 ---------------- vendor/core/vendor/cmark-gfm/src/scanners.h | 70 - vendor/core/vendor/cmark-gfm/src/scanners.re | 365 - .../vendor/cmark-gfm/src/syntax_extension.c | 149 - .../vendor/cmark-gfm/src/syntax_extension.h | 34 - vendor/core/vendor/cmark-gfm/src/utf8.c | 317 - vendor/core/vendor/cmark-gfm/src/utf8.h | 35 - vendor/core/vendor/cmark-gfm/src/xml.c | 182 - .../vendor/googlebenchmark/CMakeLists.txt | 351 - vendor/core/vendor/googlebenchmark/LICENSE | 202 - .../cmake/AddCXXCompilerFlag.cmake | 78 - .../cmake/CXXFeatureCheck.cmake | 82 - .../googlebenchmark/cmake/Config.cmake.in | 11 - .../googlebenchmark/cmake/GetGitVersion.cmake | 36 - .../googlebenchmark/cmake/GoogleTest.cmake | 58 - .../googlebenchmark/cmake/GoogleTest.cmake.in | 59 - .../cmake/Modules/FindLLVMAr.cmake | 16 - .../cmake/Modules/FindLLVMNm.cmake | 16 - .../cmake/Modules/FindLLVMRanLib.cmake | 15 - .../cmake/Modules/FindPFM.cmake | 28 - .../googlebenchmark/cmake/benchmark.pc.in | 12 - .../cmake/benchmark_main.pc.in | 7 - .../googlebenchmark/cmake/gnu_posix_regex.cpp | 12 - .../cmake/llvm-toolchain.cmake | 8 - .../googlebenchmark/cmake/posix_regex.cpp | 14 - .../cmake/pthread_affinity.cpp | 16 - .../googlebenchmark/cmake/split_list.cmake | 3 - .../googlebenchmark/cmake/std_regex.cpp | 10 - .../googlebenchmark/cmake/steady_clock.cpp | 7 - .../cmake/thread_safety_attributes.cpp | 4 - .../include/benchmark/benchmark.h | 2060 --- .../include/benchmark/export.h | 47 - .../vendor/googlebenchmark/src/CMakeLists.txt | 180 - .../vendor/googlebenchmark/src/arraysize.h | 33 - .../vendor/googlebenchmark/src/benchmark.cc | 812 - .../src/benchmark_api_internal.cc | 118 - .../src/benchmark_api_internal.h | 87 - .../googlebenchmark/src/benchmark_main.cc | 18 - .../googlebenchmark/src/benchmark_name.cc | 59 - .../googlebenchmark/src/benchmark_register.cc | 521 - .../googlebenchmark/src/benchmark_register.h | 109 - .../googlebenchmark/src/benchmark_runner.cc | 525 - .../googlebenchmark/src/benchmark_runner.h | 136 - .../core/vendor/googlebenchmark/src/check.cc | 11 - .../core/vendor/googlebenchmark/src/check.h | 106 - .../vendor/googlebenchmark/src/colorprint.cc | 200 - .../vendor/googlebenchmark/src/colorprint.h | 33 - .../googlebenchmark/src/commandlineflags.cc | 298 - .../googlebenchmark/src/commandlineflags.h | 133 - .../vendor/googlebenchmark/src/complexity.cc | 255 - .../vendor/googlebenchmark/src/complexity.h | 55 - .../googlebenchmark/src/console_reporter.cc | 210 - .../vendor/googlebenchmark/src/counter.cc | 80 - .../core/vendor/googlebenchmark/src/counter.h | 32 - .../googlebenchmark/src/csv_reporter.cc | 169 - .../vendor/googlebenchmark/src/cycleclock.h | 243 - .../googlebenchmark/src/internal_macros.h | 111 - .../googlebenchmark/src/json_reporter.cc | 327 - vendor/core/vendor/googlebenchmark/src/log.h | 88 - .../core/vendor/googlebenchmark/src/mutex.h | 155 - .../googlebenchmark/src/perf_counters.cc | 284 - .../googlebenchmark/src/perf_counters.h | 200 - vendor/core/vendor/googlebenchmark/src/re.h | 158 - .../vendor/googlebenchmark/src/reporter.cc | 118 - .../vendor/googlebenchmark/src/statistics.cc | 214 - .../vendor/googlebenchmark/src/statistics.h | 44 - .../vendor/googlebenchmark/src/string_util.cc | 254 - .../vendor/googlebenchmark/src/string_util.h | 70 - .../vendor/googlebenchmark/src/sysinfo.cc | 871 - .../googlebenchmark/src/thread_manager.h | 63 - .../vendor/googlebenchmark/src/thread_timer.h | 86 - .../core/vendor/googlebenchmark/src/timers.cc | 284 - .../core/vendor/googlebenchmark/src/timers.h | 75 - 197 files changed, 8096 insertions(+), 47424 deletions(-) create mode 100644 vendor/blaze/src/convert/rules/metaschema_vocabulary.h delete mode 100644 vendor/core/cmake/FindCMarkGFM.cmake delete mode 100644 vendor/core/cmake/FindGoogleBenchmark.cmake create mode 100644 vendor/core/cmake/common/targets/benchmark.cmake delete mode 100644 vendor/core/cmake/common/targets/googlebenchmark.cmake create mode 100644 vendor/core/src/core/jsonschema/format.cc create mode 100644 vendor/core/src/core/markdown/blocks.h create mode 100644 vendor/core/src/core/markdown/characters.h create mode 100644 vendor/core/src/core/markdown/document.h create mode 100644 vendor/core/src/core/markdown/include/sourcemeta/core/markdown_error.h create mode 100644 vendor/core/src/core/markdown/inlines.h create mode 100644 vendor/core/src/core/markdown/postprocess.h create mode 100644 vendor/core/src/core/markdown/references.h create mode 100644 vendor/core/src/core/markdown/render.h create mode 100644 vendor/core/src/core/markdown/scanners.h create mode 100644 vendor/core/src/lang/benchmark/CMakeLists.txt create mode 100644 vendor/core/src/lang/benchmark/benchmark.cc create mode 100644 vendor/core/src/lang/benchmark/benchmark_main.cc create mode 100644 vendor/core/src/lang/benchmark/include/sourcemeta/core/benchmark.h delete mode 100644 vendor/core/vendor/cmark-gfm/COPYING delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/autolink.c delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/autolink.h delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/cmark-gfm-core-extensions.h delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/core-extensions.c delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/ext_scanners.c delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/ext_scanners.h delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/ext_scanners.re delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/strikethrough.c delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/strikethrough.h delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/table.c delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/table.h delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/tagfilter.c delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/tagfilter.h delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/tasklist.c delete mode 100644 vendor/core/vendor/cmark-gfm/extensions/tasklist.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/arena.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/blocks.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/buffer.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/buffer.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/case_fold_switch.inc delete mode 100644 vendor/core/vendor/cmark-gfm/src/chunk.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/cmark-gfm-extension_api.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/cmark-gfm.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/cmark-gfm_version.h.in delete mode 100644 vendor/core/vendor/cmark-gfm/src/cmark.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/cmark_ctype.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/cmark_ctype.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/commonmark.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/config.h.in delete mode 100644 vendor/core/vendor/cmark-gfm/src/entities.inc delete mode 100644 vendor/core/vendor/cmark-gfm/src/footnotes.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/footnotes.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/houdini.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/houdini_href_e.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/houdini_html_e.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/houdini_html_u.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/html.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/html.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/inlines.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/inlines.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/iterator.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/iterator.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/latex.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/linked_list.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/main.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/man.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/map.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/map.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/node.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/node.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/parser.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/plaintext.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/plugin.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/plugin.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/references.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/references.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/registry.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/registry.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/render.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/render.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/scanners.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/scanners.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/scanners.re delete mode 100644 vendor/core/vendor/cmark-gfm/src/syntax_extension.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/syntax_extension.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/utf8.c delete mode 100644 vendor/core/vendor/cmark-gfm/src/utf8.h delete mode 100644 vendor/core/vendor/cmark-gfm/src/xml.c delete mode 100644 vendor/core/vendor/googlebenchmark/CMakeLists.txt delete mode 100644 vendor/core/vendor/googlebenchmark/LICENSE delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/AddCXXCompilerFlag.cmake delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/CXXFeatureCheck.cmake delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/Config.cmake.in delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/GetGitVersion.cmake delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/GoogleTest.cmake delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/GoogleTest.cmake.in delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMAr.cmake delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMNm.cmake delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMRanLib.cmake delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/Modules/FindPFM.cmake delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/benchmark.pc.in delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/benchmark_main.pc.in delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/gnu_posix_regex.cpp delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/llvm-toolchain.cmake delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/posix_regex.cpp delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/pthread_affinity.cpp delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/split_list.cmake delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/std_regex.cpp delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/steady_clock.cpp delete mode 100644 vendor/core/vendor/googlebenchmark/cmake/thread_safety_attributes.cpp delete mode 100644 vendor/core/vendor/googlebenchmark/include/benchmark/benchmark.h delete mode 100644 vendor/core/vendor/googlebenchmark/include/benchmark/export.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/CMakeLists.txt delete mode 100644 vendor/core/vendor/googlebenchmark/src/arraysize.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/benchmark.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/benchmark_api_internal.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/benchmark_api_internal.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/benchmark_main.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/benchmark_name.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/benchmark_register.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/benchmark_register.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/benchmark_runner.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/benchmark_runner.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/check.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/check.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/colorprint.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/colorprint.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/commandlineflags.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/commandlineflags.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/complexity.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/complexity.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/console_reporter.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/counter.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/counter.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/csv_reporter.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/cycleclock.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/internal_macros.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/json_reporter.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/log.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/mutex.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/perf_counters.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/perf_counters.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/re.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/reporter.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/statistics.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/statistics.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/string_util.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/string_util.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/sysinfo.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/thread_manager.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/thread_timer.h delete mode 100644 vendor/core/vendor/googlebenchmark/src/timers.cc delete mode 100644 vendor/core/vendor/googlebenchmark/src/timers.h diff --git a/DEPENDENCIES b/DEPENDENCIES index 3892a6405..107c82cc5 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,4 +1,4 @@ vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02 -core https://github.com/sourcemeta/core 5dabb7f983b54e302b35ab74547b58c86576537b -blaze https://github.com/sourcemeta/blaze f25c2ab22cb13964a47be77acb8bbcc01ad1f2dd +core https://github.com/sourcemeta/core 9c3323a59a4f8113e269cfb713c85ba34cf06d96 +blaze https://github.com/sourcemeta/blaze e91f46a5a91fd5a315ab01bac4ed6c3827ac3d95 bootstrap https://github.com/twbs/bootstrap 1a6fdfae6be09b09eaced8f0e442ca6f7680a61e diff --git a/vendor/blaze/DEPENDENCIES b/vendor/blaze/DEPENDENCIES index 5e63aabcf..4111b1d40 100644 --- a/vendor/blaze/DEPENDENCIES +++ b/vendor/blaze/DEPENDENCIES @@ -1,3 +1,3 @@ vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02 -core https://github.com/sourcemeta/core 5dabb7f983b54e302b35ab74547b58c86576537b +core https://github.com/sourcemeta/core f3c2038b4c74a558f82b880d1a69e77dd8c8dce6 jsonschema-test-suite https://github.com/json-schema-org/JSON-Schema-Test-Suite 6648e8194c69697b2e1a15fe76a06a480b183a51 diff --git a/vendor/blaze/config.cmake.in b/vendor/blaze/config.cmake.in index 3b3d6aebb..85211835a 100644 --- a/vendor/blaze/config.cmake.in +++ b/vendor/blaze/config.cmake.in @@ -19,11 +19,28 @@ if(NOT BLAZE_COMPONENTS) endif() include(CMakeFindDependencyMacro) -find_dependency(Core COMPONENTS + +set(BLAZE_CORE_COMPONENTS unicode punycode idna regex uri uritemplate json jsonpointer jsonschema jsonld io yaml crypto email ip dns time css memory) +# This installation ships its own copy of Core, and CMake never searches the +# prefix of the package it is currently resolving, so a consumer that doesn't +# explicitly name our prefix, like on Windows, where the default install +# location nests as `C:/Program Files (x86)/blaze`, finds Blaze but not the +# Core next to it. Qt does the same for its sibling packages in +# `Qt6GuiDependencies.cmake`, while leaving external ones to `find_dependency`. +# We probe for that sibling with a quiet `find_package` rather than with +# `find_dependency`, as the latter returns out of this file the moment it comes +# up empty, which would leave no room to fall back on the ordinary search for +# installations that were built against a Core from somewhere else +find_package(Core QUIET COMPONENTS ${BLAZE_CORE_COMPONENTS} + PATHS "${CMAKE_CURRENT_LIST_DIR}/../core" NO_DEFAULT_PATH) +if(NOT Core_FOUND) + find_dependency(Core COMPONENTS ${BLAZE_CORE_COMPONENTS}) +endif() + foreach(component ${BLAZE_COMPONENTS}) if(component STREQUAL "compiler") include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_blaze_bundle.cmake") diff --git a/vendor/blaze/schemas/canonical-draft3.json b/vendor/blaze/schemas/canonical-draft3.json index e78cbf60f..208fea440 100644 --- a/vendor/blaze/schemas/canonical-draft3.json +++ b/vendor/blaze/schemas/canonical-draft3.json @@ -39,6 +39,13 @@ }, "id": { "type": "string" + }, + "definitions": { + "$comment": "TODO: `definitions` is permitted on any subschema as an interim measure, because the canonicaliser preserves it wherever the author wrote it. The desired shape is a single flat `definitions` at the root holding every subschema as a node, with `$ref`s as the edges between them, after which this should be tightened to the root only", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/schema" + } } } }, diff --git a/vendor/blaze/src/canonicalizer/rules/type_with_applicator_to_extends.h b/vendor/blaze/src/canonicalizer/rules/type_with_applicator_to_extends.h index 6d464dabc..b5b8b2f0c 100644 --- a/vendor/blaze/src/canonicalizer/rules/type_with_applicator_to_extends.h +++ b/vendor/blaze/src/canonicalizer/rules/type_with_applicator_to_extends.h @@ -33,7 +33,24 @@ class TypeWithApplicatorToExtends final : public SchemaTransformRule { const unsigned int applicator_count{(has_extends ? 1U : 0U) + (has_disallow ? 1U : 0U) + (has_type_array ? 1U : 0U)}; - const bool has_structural{has_type || has_enum}; + + // An assertion left beside `extends` or `disallow` has to be pushed into a + // branch of its own, otherwise shapes such as `extends` sitting next to + // `properties` are never rewritten and the result is not in canonical form. + // + // A type union on its own deliberately does not count here. In Draft 3 the + // distribution rule folds neighbouring assertions into the branches, but in + // Draft 0 to 2 there is no such rule, so `{"type": [...], "minLength": 2}` + // is a resting state. Splitting it would only invite the implicit type rule + // to rebuild the union around the assertion on the next pass, and the + // fixpoint would never settle + const bool has_assertion{ + std::ranges::any_of(schema.as_object(), [](const auto &entry) -> bool { + return is_assertion_keyword(entry.first) && + !(entry.first == "type" && entry.second.is_array()); + })}; + const bool has_structural{has_type || has_enum || + ((has_extends || has_disallow) && has_assertion)}; ONLY_CONTINUE_IF((has_structural && applicator_count >= 1) || applicator_count >= 2); @@ -45,8 +62,13 @@ class TypeWithApplicatorToExtends final : public SchemaTransformRule { auto typed_branch{sourcemeta::core::JSON::make_object()}; for (const auto &entry : schema.as_object()) { + // Note that `required` must stay where it is. It is a marker read by the + // parent `properties` object rather than an assertion about the instance, + // so moving it into an `extends` branch silently makes it inert and the + // implicit default left behind flips whether the property is required if (entry.first == "extends" || entry.first == "disallow" || entry.first == "$schema" || entry.first == "id" || + entry.first == "required" || (entry.first == "type" && entry.second.is_array())) { continue; } @@ -86,6 +108,9 @@ class TypeWithApplicatorToExtends final : public SchemaTransformRule { if (schema.defines("id")) { new_schema.assign("id", schema.at("id")); } + if (schema.defines("required")) { + new_schema.assign("required", schema.at("required")); + } new_schema.assign("extends", std::move(new_extends)); schema.into(std::move(new_schema)); } @@ -134,6 +159,26 @@ class TypeWithApplicatorToExtends final : public SchemaTransformRule { static constexpr std::array APPLICATORS{ {"extends", "disallow", "type"}}; + // The assertion keywords of these dialects. This is deliberately an + // allow-list rather than a list of keywords to ignore: a keyword missing from + // here only means the rule does not fire, which is the previous behaviour, + // whereas a keyword wrongly treated as an assertion is rewritten on every + // pass and the fixpoint never settles. Markers such as `required` and + // `optional`, the `definitions` container, the core identity keywords and + // metadata are all absent for that reason + static constexpr std::array ASSERTIONS{ + {"enum", "type", "properties", "patternProperties", + "additionalProperties", "items", "additionalItems", "minItems", + "maxItems", "uniqueItems", "minLength", "maxLength", "pattern", "format", + "divisibleBy", "minimum", "maximum", "exclusiveMinimum", + "exclusiveMaximum"}}; + + static auto is_assertion_keyword(std::string_view keyword) -> bool { + return std::ranges::any_of( + ASSERTIONS, + [keyword](const auto *entry) -> bool { return keyword == entry; }); + } + static constexpr auto applicator_bit(std::string_view keyword) -> std::uint8_t { if (keyword == "extends") { diff --git a/vendor/blaze/src/compiler/default_compiler_draft3.h b/vendor/blaze/src/compiler/default_compiler_draft3.h index c3ffceab9..afbe992de 100644 --- a/vendor/blaze/src/compiler/default_compiler_draft3.h +++ b/vendor/blaze/src/compiler/default_compiler_draft3.h @@ -8,11 +8,37 @@ #include // std::sort, std::ranges::any_of, std::ranges::all_of, std::find_if, std::ranges::none_of #include // assert -#include // std::set -#include // std::move, std::to_underlying +#include // std::initializer_list +#include // std::set +#include // std::move, std::to_underlying #include "compile_helpers.h" +// Draft 3 spells the absence of a type restriction as a type of its own, so a +// schema that declares `any` narrows nothing and every keyword it carries +// still applies. Only a type that rules the keyword out lets us skip it +static auto +narrows_type_away(const sourcemeta::core::JSON &schema, + const std::initializer_list types) -> bool { + const auto *value{schema.try_at("type")}; + if (value == nullptr || !value->is_string()) { + return false; + } + + const auto &name{value->to_string()}; + if (name == "any") { + return false; + } + + for (const auto candidate : types) { + if (candidate == name) { + return false; + } + } + + return true; +} + static auto parse_regex(const std::string &pattern, const sourcemeta::blaze::Context &context, const sourcemeta::core::URI &base, @@ -292,9 +318,7 @@ auto compile_required_assertions(const Context &context, const Instructions ¤t, ValueStringSet properties_set) -> Instructions { - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "object") { + if (narrows_type_away(schema_context.schema, {"object"})) { return {}; } @@ -655,9 +679,7 @@ auto compiler_draft3_applicator_properties_with_options( return {}; } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "object") { + if (narrows_type_away(schema_context.schema, {"object"})) { return {}; } @@ -1176,9 +1198,7 @@ auto compiler_draft3_applicator_patternproperties_with_options( return {}; } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "object") { + if (narrows_type_away(schema_context.schema, {"object"})) { return {}; } @@ -1313,9 +1333,7 @@ auto compiler_draft3_applicator_additionalproperties_with_options( const Context &context, const SchemaContext &schema_context, const DynamicContext &dynamic_context, const bool annotate, const bool track_evaluation) -> Instructions { - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "object") { + if (narrows_type_away(schema_context.schema, {"object"})) { return {}; } @@ -1481,9 +1499,7 @@ auto compiler_draft3_validation_pattern(const Context &context, EXPECTED_STRING); } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "string") { + if (narrows_type_away(schema_context.schema, {"string"})) { return {}; } @@ -1532,9 +1548,7 @@ auto compiler_draft3_applicator_items_array( return {}; } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "array") { + if (narrows_type_away(schema_context.schema, {"array"})) { return {}; } @@ -1671,9 +1685,7 @@ auto compiler_draft3_applicator_items_with_options( } } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "array") { + if (narrows_type_away(schema_context.schema, {"array"})) { return {}; } @@ -1806,9 +1818,7 @@ auto compiler_draft3_applicator_additionalitems_from_cursor( const Context &context, const SchemaContext &schema_context, const DynamicContext &dynamic_context, const std::size_t cursor, const bool annotate, const bool track_evaluation) -> Instructions { - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "array") { + if (narrows_type_away(schema_context.schema, {"array"})) { return {}; } @@ -1871,9 +1881,7 @@ auto compiler_draft3_applicator_additionalitems_with_options( const Context &context, const SchemaContext &schema_context, const DynamicContext &dynamic_context, const bool annotate, const bool track_evaluation) -> Instructions { - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "array") { + if (narrows_type_away(schema_context.schema, {"array"})) { return {}; } @@ -1979,9 +1987,7 @@ auto compiler_draft3_validation_uniqueitems( return {}; } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "array") { + if (narrows_type_away(schema_context.schema, {"array"})) { return {}; } @@ -2013,9 +2019,7 @@ auto compiler_draft3_validation_maxlength(const Context &context, EXPECTED_NON_NEGATIVE); } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "string") { + if (narrows_type_away(schema_context.schema, {"string"})) { return {}; } @@ -2069,9 +2073,7 @@ auto compiler_draft3_validation_minlength(const Context &context, EXPECTED_NON_NEGATIVE); } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "string") { + if (narrows_type_away(schema_context.schema, {"string"})) { return {}; } @@ -2115,9 +2117,7 @@ auto compiler_draft3_validation_maxitems(const Context &context, EXPECTED_NON_NEGATIVE); } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "array") { + if (narrows_type_away(schema_context.schema, {"array"})) { return {}; } @@ -2156,9 +2156,7 @@ auto compiler_draft3_validation_minitems(const Context &context, EXPECTED_NON_NEGATIVE); } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "array") { + if (narrows_type_away(schema_context.schema, {"array"})) { return {}; } @@ -2191,10 +2189,7 @@ auto compiler_draft3_validation_maximum(const Context &context, EXPECTED_NUMBER); } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "integer" && - schema_context.schema.at("type").to_string() != "number") { + if (narrows_type_away(schema_context.schema, {"integer", "number"})) { return {}; } @@ -2226,10 +2221,7 @@ auto compiler_draft3_validation_minimum(const Context &context, EXPECTED_NUMBER); } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "integer" && - schema_context.schema.at("type").to_string() != "number") { + if (narrows_type_away(schema_context.schema, {"integer", "number"})) { return {}; } @@ -2896,9 +2888,7 @@ auto compiler_draft3_applicator_dependencies( // Only once the shape is known to be good does it matter whether the keyword // can apply to the instances this schema admits - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "object") { + if (narrows_type_away(schema_context.schema, {"object"})) { return {}; } @@ -2964,10 +2954,7 @@ auto compiler_draft3_validation_divisibleby( EXPECTED_POSITIVE); } - if (schema_context.schema.defines("type") && - schema_context.schema.at("type").is_string() && - schema_context.schema.at("type").to_string() != "integer" && - schema_context.schema.at("type").to_string() != "number") { + if (narrows_type_away(schema_context.schema, {"integer", "number"})) { return {}; } diff --git a/vendor/blaze/src/compiler/unevaluated.cc b/vendor/blaze/src/compiler/unevaluated.cc index 1356f3475..77c418d1f 100644 --- a/vendor/blaze/src/compiler/unevaluated.cc +++ b/vendor/blaze/src/compiler/unevaluated.cc @@ -3,6 +3,9 @@ #include "compile_helpers.h" +#include // std::set +#include // std::pair + namespace { using namespace sourcemeta::core; using namespace sourcemeta::blaze; @@ -13,12 +16,51 @@ const std::string UNEVALUATED_PROPERTIES{"unevaluatedProperties"}; const std::string UNEVALUATED_ITEMS{"unevaluatedItems"}; // NOLINTEND(cert-err58-cpp,bugprone-throwing-static-initialization) +// Whether a location is already being visited has to survive the nested calls +// that walk through it, and stop applying the moment they unwind +class PathGuard { +public: + PathGuard(std::set> &visited, + const WeakPointer &pointer, const bool is_static) + : visited_{visited}, entry_{pointer, is_static}, + first_visit_{visited.insert(this->entry_).second} {} + + ~PathGuard() { + if (this->first_visit_) { + this->visited_.erase(this->entry_); + } + } + + [[nodiscard]] auto first_visit() const -> bool { return this->first_visit_; } + + PathGuard(const PathGuard &) = delete; + auto operator=(const PathGuard &) -> PathGuard & = delete; + PathGuard(PathGuard &&) = delete; + auto operator=(PathGuard &&) -> PathGuard & = delete; + +private: + std::set> &visited_; + const std::pair entry_; + const bool first_visit_; +}; + auto find_adjacent_dependencies( const JSON::String ¤t, const JSON &schema, const SchemaFrame &frame, const SchemaWalker &walker, const SchemaResolver &resolver, const std::set &keywords, const SchemaFrame::Location &root, const SchemaFrame::Location &entry, const bool is_static, + std::set> &visited, sourcemeta::blaze::SchemaUnevaluatedEntry &result) -> void { + // A schema may reference itself, directly or through a chain of in-place + // applicators. Following such a cycle forever exhausts the stack, so we cut + // it as soon as we meet a location already on the path we came in through. + // The mark only lives as long as that path, as two references to a common + // target are not a cycle, and each of them still has to be accounted for + const PathGuard guard{visited, entry.pointer, is_static}; + if (!guard.first_visit()) { + return; + } + const auto &subschema{get(schema, entry.pointer)}; if (!subschema.is_object()) { return; @@ -63,7 +105,7 @@ auto find_adjacent_dependencies( SchemaUnevaluatedEntry nested; find_adjacent_dependencies( current, schema, frame, walker, resolver, keywords, root, - reference.second.value().get(), is_static, nested); + reference.second.value().get(), is_static, visited, nested); // Whatever the target contributes gets recorded at the location of // the target itself, which tells the applicators this reference sits @@ -95,7 +137,7 @@ auto find_adjacent_dependencies( find_adjacent_dependencies( current, schema, frame, walker, resolver, keywords, root, frame.traverse(entry, make_weak_pointer(property.first, index)), - is_static, result); + is_static, visited, result); } break; @@ -107,7 +149,7 @@ auto find_adjacent_dependencies( find_adjacent_dependencies( current, schema, frame, walker, resolver, keywords, root, frame.traverse(entry, make_weak_pointer(property.first, index)), - false, result); + false, visited, result); } } @@ -121,7 +163,7 @@ auto find_adjacent_dependencies( find_adjacent_dependencies( current, schema, frame, walker, resolver, keywords, root, frame.traverse(entry, make_weak_pointer(property.first)), false, - result); + visited, result); } break; @@ -131,14 +173,14 @@ auto find_adjacent_dependencies( find_adjacent_dependencies( current, schema, frame, walker, resolver, keywords, root, frame.traverse(entry, make_weak_pointer(property.first, index)), - false, result); + false, visited, result); } } else if ((property.second.is_object() || property.second.is_boolean())) { find_adjacent_dependencies( current, schema, frame, walker, resolver, keywords, root, frame.traverse(entry, make_weak_pointer(property.first)), false, - result); + visited, result); } break; @@ -149,7 +191,7 @@ auto find_adjacent_dependencies( current, schema, frame, walker, resolver, keywords, root, frame.traverse(entry, make_weak_pointer(property.first, pair.first)), - false, result); + false, visited, result); } } @@ -226,18 +268,20 @@ auto unevaluated(const JSON &schema, const SchemaFrame &frame, Known::JSON_SCHEMA_2020_12_APPLICATOR)) || subschema_vocabularies.contains( Known::JSON_SCHEMA_2019_09_APPLICATOR)) { + std::set> visited; SchemaUnevaluatedEntry unevaluated; find_adjacent_dependencies( "unevaluatedProperties", schema, frame, walker, resolver, {"properties", "patternProperties", "additionalProperties", "unevaluatedProperties"}, - location, location, true, unevaluated); + location, location, true, visited, unevaluated); register_under_all_bases(result, frame, location, UNEVALUATED_PROPERTIES, unevaluated); } } if (has_unevaluated_items) { + std::set> visited; SchemaUnevaluatedEntry unevaluated; if (subschema_vocabularies.contains( Known::JSON_SCHEMA_2020_12_UNEVALUATED) && @@ -246,7 +290,7 @@ auto unevaluated(const JSON &schema, const SchemaFrame &frame, find_adjacent_dependencies( "unevaluatedItems", schema, frame, walker, resolver, {"prefixItems", "items", "contains", "unevaluatedItems"}, location, - location, true, unevaluated); + location, true, visited, unevaluated); register_under_all_bases(result, frame, location, UNEVALUATED_ITEMS, unevaluated); } else if (subschema_vocabularies.contains( @@ -254,7 +298,7 @@ auto unevaluated(const JSON &schema, const SchemaFrame &frame, find_adjacent_dependencies( "unevaluatedItems", schema, frame, walker, resolver, {"items", "additionalItems", "unevaluatedItems"}, location, - location, true, unevaluated); + location, true, visited, unevaluated); register_under_all_bases(result, frame, location, UNEVALUATED_ITEMS, unevaluated); } diff --git a/vendor/blaze/src/convert/CMakeLists.txt b/vendor/blaze/src/convert/CMakeLists.txt index eace72261..efa1f6c64 100644 --- a/vendor/blaze/src/convert/CMakeLists.txt +++ b/vendor/blaze/src/convert/CMakeLists.txt @@ -11,6 +11,7 @@ sourcemeta_library(NAMESPACE sourcemeta PROJECT blaze NAME convert rules/draft_official_dialect_without_empty_fragment.h rules/empty_object_as_true.h rules/enum_to_const.h + rules/metaschema_vocabulary.h rules/prefix_promoted_2020_12_keywords.h rules/prefix_promoted_draft_2019_09_keywords.h rules/prefix_promoted_draft_4_keywords.h diff --git a/vendor/blaze/src/convert/convert.cc b/vendor/blaze/src/convert/convert.cc index 2426994a5..b397e10fe 100644 --- a/vendor/blaze/src/convert/convert.cc +++ b/vendor/blaze/src/convert/convert.cc @@ -248,6 +248,7 @@ auto apply(const std::vector &rules, sourcemeta::core::JSON &schema, #include "rules/draft_official_dialect_without_empty_fragment.h" #include "rules/empty_object_as_true.h" #include "rules/enum_to_const.h" +#include "rules/metaschema_vocabulary.h" #include "rules/prefix_promoted_2020_12_keywords.h" #include "rules/prefix_promoted_draft_2019_09_keywords.h" #include "rules/prefix_promoted_draft_4_keywords.h" @@ -271,7 +272,7 @@ auto convert(sourcemeta::core::JSON &schema, const std::string_view default_id, const bool is_metaschema) -> void { std::vector rules; - rules.reserve(17); + rules.reserve(18); rules.push_back(make_rule()); rules.push_back(make_rule()); rules.push_back(make_rule()); @@ -296,6 +297,7 @@ auto convert(sourcemeta::core::JSON &schema, target == ConvertTarget::Draft202012) { rules.push_back(make_rule()); rules.push_back(make_rule()); + rules.push_back(make_rule()); rules.push_back(make_rule()); } diff --git a/vendor/blaze/src/convert/helpers.h b/vendor/blaze/src/convert/helpers.h index 00449369e..fd29462ca 100644 --- a/vendor/blaze/src/convert/helpers.h +++ b/vendor/blaze/src/convert/helpers.h @@ -36,6 +36,91 @@ inline auto current_dialect_or_override(const sourcemeta::core::JSON &schema) return declared_dialect(schema); } +// A subschema that a `$schema` of the document resolves to is a meta-schema of +// that document, no matter where within the document it sits. Every base +// dialect asks such a subschema to declare an identifier, which is what keeps +// the scan off the subschemas that could never be named that way +inline auto is_metaschema_target(const sourcemeta::core::JSON &schema, + const sourcemeta::core::SchemaFrame &frame, + const sourcemeta::core::WeakPointer &pointer) + -> bool { + if (!schema.is_object() || !schema.defines_any({"$id", "id"})) { + return false; + } + + return frame.any_reference( + [&frame, &pointer]( + const sourcemeta::core::SchemaReferenceType, + const sourcemeta::core::WeakPointer &origin, + const sourcemeta::core::SchemaFrame::Reference &reference) -> bool { + if (origin.empty() || !origin.back().is_property() || + origin.back().to_property() != "$schema") { + return false; + } + + const auto destination{frame.traverse(reference.destination)}; + return destination.has_value() && + destination.value().get().pointer == pointer; + }); +} + +// Whether any subschema that names this one through `$schema` still has work +// of its own left. Such a referrer is read under the dialect this subschema +// defines, so moving this one first would take the referrer off the dialect +// the caller is acting on before its turn ever comes +template +auto has_pending_metaschema_referrer( + const sourcemeta::core::JSON &root, + const sourcemeta::core::SchemaFrame &frame, + const sourcemeta::core::WeakPointer &pointer, const Predicate &pending) + -> bool { + return frame.any_reference( + [&root, &frame, &pointer, &pending]( + const sourcemeta::core::SchemaReferenceType, + const sourcemeta::core::WeakPointer &origin, + const sourcemeta::core::SchemaFrame::Reference &reference) -> bool { + if (origin.empty() || !origin.back().is_property() || + origin.back().to_property() != "$schema") { + return false; + } + + const auto destination{frame.traverse(reference.destination)}; + if (!destination.has_value() || + destination.value().get().pointer != pointer) { + return false; + } + + const auto referrer{sourcemeta::core::to_pointer(origin).initial()}; + const auto referrer_pointer{ + sourcemeta::core::to_weak_pointer(referrer)}; + + // A meta-schema that describes itself is its own referrer, and waiting + // on itself would leave it on the dialect it came in with for good + if (referrer_pointer == pointer) { + return false; + } + + if (pending(sourcemeta::core::get(root, referrer))) { + return true; + } + + // Everything under the referrer is read under the dialect this + // subschema defines too, so work down there counts just as much as + // work on the referrer itself. Another meta-schema is governed by its + // own referrers rather than by this one + return frame.any_subschema_under( + referrer_pointer, + [&root, &frame, &pending]( + const sourcemeta::core::SchemaFrame::Location &entry) -> bool { + const auto &entry_schema{sourcemeta::core::get( + root, sourcemeta::core::to_pointer(entry.pointer))}; + return !is_metaschema_target(entry_schema, frame, + entry.pointer) && + pending(entry_schema); + }); + }); +} + inline auto subschema_at_dialect(const sourcemeta::core::JSON &schema, const sourcemeta::core::SchemaFrame::Location &location, @@ -47,11 +132,43 @@ subschema_at_dialect(const sourcemeta::core::JSON &schema, return schema.is_object() && location.pointer.empty(); } +// The official dialects the upgrade walks through, oldest first, so that a +// marker recording a newer one can be told apart from a stale one +// NOLINTNEXTLINE(cert-err58-cpp,bugprone-throwing-static-initialization) +constexpr std::array LADDER_DIALECTS{ + {"http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-07/schema#", + "https://json-schema.org/draft/2019-09/schema", + "https://json-schema.org/draft/2020-12/schema"}}; + +// How far along the ladder a dialect sits, counting from one so that anything +// the ladder does not name sits before all of them +inline auto dialect_position(const std::string_view dialect) -> std::size_t { + for (std::size_t index = 0; index < LADDER_DIALECTS.size(); index += 1) { + if (LADDER_DIALECTS[index] == dialect) { + return index + 1; + } + } + + return 0; +} + +inline auto moved_past(const sourcemeta::core::JSON &schema, + const std::string_view dialect) -> bool { + const auto *override_value{schema.try_at(DIALECT_OVERRIDE_KEYWORD)}; + return override_value != nullptr && override_value->is_string() && + dialect_position(override_value->to_string()) > + dialect_position(dialect); +} + inline auto drop_dialect_overrides(sourcemeta::core::JSON &schema, - const bool is_root) -> void { + const bool is_root, + const std::string_view dialect) -> void { if (schema.is_array()) { for (auto &item : schema.as_array()) { - drop_dialect_overrides(item, false); + drop_dialect_overrides(item, false, dialect); } return; } @@ -65,7 +182,13 @@ inline auto drop_dialect_overrides(sourcemeta::core::JSON &schema, return; } - schema.erase(DIALECT_OVERRIDE_KEYWORD); + // A subschema that already moved past the dialect being established keeps + // its marker. Dropping it would leave the keywords that move brought in + // looking like keywords of the dialect it has left behind, and the rules + // that reserve those names would prefix them away + if (is_root || !moved_past(schema, dialect)) { + schema.erase(DIALECT_OVERRIDE_KEYWORD); + } std::vector keys; keys.reserve(schema.size()); @@ -73,7 +196,7 @@ inline auto drop_dialect_overrides(sourcemeta::core::JSON &schema, keys.push_back(entry.first); } for (const auto &key : keys) { - drop_dialect_overrides(schema.at(key), false); + drop_dialect_overrides(schema.at(key), false, dialect); } } diff --git a/vendor/blaze/src/convert/rules/metaschema_vocabulary.h b/vendor/blaze/src/convert/rules/metaschema_vocabulary.h new file mode 100644 index 000000000..c1e54b30d --- /dev/null +++ b/vendor/blaze/src/convert/rules/metaschema_vocabulary.h @@ -0,0 +1,99 @@ +class MetaschemaVocabulary final : public SchemaTransformRule { +public: + using reframe_after_transform = std::true_type; + MetaschemaVocabulary() : SchemaTransformRule{"metaschema_vocabulary"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::core::JSON &schema, + const sourcemeta::core::JSON &, + const sourcemeta::core::SchemaVocabularies &vocabularies, + const sourcemeta::core::SchemaFrame &frame, + const sourcemeta::core::SchemaFrame::Location &location, + const sourcemeta::core::SchemaWalker &, + const sourcemeta::core::SchemaResolver &, + const bool is_metaschema) const -> bool override { + ONLY_CONTINUE_IF(schema.is_object() && !schema.defines("$vocabulary")); + + // Whichever dialect the meta-schema ends up on is the one whose + // vocabularies it has to declare, rather than the one the caller asked to + // convert to + this->emits_2020_12_ = vocabularies.contains( + SchemaVocabularies::Known::JSON_SCHEMA_2020_12_CORE); + ONLY_CONTINUE_IF(this->emits_2020_12_ || + vocabularies.contains( + SchemaVocabularies::Known::JSON_SCHEMA_2019_09_CORE)); + + return (is_metaschema && location.pointer.empty()) || + is_metaschema_target(schema, frame, location.pointer); + } + + auto transform(sourcemeta::core::JSON &schema) const -> void override { + if (this->emits_2020_12_) { + synthesize_vocabulary(schema, VOCABULARIES_2020_12); + } else { + synthesize_vocabulary(schema, VOCABULARIES_2019_09); + } + } + +private: + using Vocabulary = std::pair; + + static constexpr std::array VOCABULARIES_2019_09{ + {{"https://json-schema.org/draft/2019-09/vocab/core", true}, + {"https://json-schema.org/draft/2019-09/vocab/applicator", true}, + {"https://json-schema.org/draft/2019-09/vocab/validation", true}, + {"https://json-schema.org/draft/2019-09/vocab/meta-data", true}, + {"https://json-schema.org/draft/2019-09/vocab/format", false}, + {"https://json-schema.org/draft/2019-09/vocab/content", true}}}; + + static constexpr std::array VOCABULARIES_2020_12{ + {{"https://json-schema.org/draft/2020-12/vocab/core", true}, + {"https://json-schema.org/draft/2020-12/vocab/applicator", true}, + {"https://json-schema.org/draft/2020-12/vocab/unevaluated", true}, + {"https://json-schema.org/draft/2020-12/vocab/validation", true}, + {"https://json-schema.org/draft/2020-12/vocab/meta-data", true}, + {"https://json-schema.org/draft/2020-12/vocab/format-annotation", false}, + {"https://json-schema.org/draft/2020-12/vocab/content", true}}}; + + mutable bool emits_2020_12_{false}; + + template + static auto synthesize_vocabulary(sourcemeta::core::JSON &schema, + const std::array &entries) + -> void { + std::string_view anchor; + if (schema.defines("$id")) { + anchor = "$id"; + } else if (schema.defines("$schema")) { + anchor = "$schema"; + } + + const std::string *next_key{nullptr}; + if (!anchor.empty()) { + bool found_anchor{false}; + for (const auto &entry : schema.as_object()) { + if (found_anchor) { + next_key = &entry.first; + break; + } + if (entry.first == anchor) { + found_anchor = true; + } + } + } + + if (next_key != nullptr) { + schema.try_assign_before( + "$vocabulary", sourcemeta::core::JSON::make_object(), *next_key); + } else { + schema.assign_assume_new("$vocabulary", + sourcemeta::core::JSON::make_object()); + } + + auto &vocabularies{schema.at("$vocabulary")}; + for (const auto &[uri, required] : entries) { + vocabularies.assign_assume_new(std::string{uri}, + sourcemeta::core::JSON{required}); + } + } +}; diff --git a/vendor/blaze/src/convert/rules/upgrade_2019_09_to_2020_12.h b/vendor/blaze/src/convert/rules/upgrade_2019_09_to_2020_12.h index 9a39846b4..7e83a6028 100644 --- a/vendor/blaze/src/convert/rules/upgrade_2019_09_to_2020_12.h +++ b/vendor/blaze/src/convert/rules/upgrade_2019_09_to_2020_12.h @@ -32,6 +32,10 @@ class Upgrade201909To202012 final : public SchemaTransformRule { any_descendant_has_pending_pattern(root, frame, location); this->resource_has_recursive_anchor_ = compute_resource_has_recursive_anchor(root, frame, location); + this->anchor_at_resource_root_ = + location.pointer.empty() || + location.type == + sourcemeta::core::SchemaFrame::LocationType::Resource; this->document_has_unevaluated_items_ = compute_document_has_unevaluated_items(root, frame, walker, resolver); @@ -54,6 +58,9 @@ class Upgrade201909To202012 final : public SchemaTransformRule { this->resource_has_recursive_anchor_ = compute_resource_has_recursive_anchor(root, frame, location); + this->anchor_at_resource_root_ = + location.pointer.empty() || + location.type == sourcemeta::core::SchemaFrame::LocationType::Resource; this->document_has_unevaluated_items_ = compute_document_has_unevaluated_items(root, frame, walker, resolver); return true; @@ -71,7 +78,11 @@ class Upgrade201909To202012 final : public SchemaTransformRule { if (schema.defines("$recursiveAnchor") && schema.at("$recursiveAnchor").is_boolean()) { - if (schema.at("$recursiveAnchor").to_boolean()) { + // Only the root of a schema resource can carry a recursive anchor. + // Anywhere else the keyword says nothing, so turning it into a dynamic + // anchor would invent a target that nothing was ever pointed at + if (schema.at("$recursiveAnchor").to_boolean() && + this->anchor_at_resource_root_) { schema.rename("$recursiveAnchor", "$dynamicAnchor"); schema.at("$dynamicAnchor").into(sourcemeta::core::JSON{"meta"}); } else { @@ -159,7 +170,7 @@ class Upgrade201909To202012 final : public SchemaTransformRule { if (schema.defines("$schema") && schema.at("$schema").is_string() && schema.at("$schema").to_string() == DRAFT_2019_09_URL) { schema.assign("$schema", sourcemeta::core::JSON{DRAFT_2020_12_URL}); - drop_dialect_overrides(schema, true); + drop_dialect_overrides(schema, true, DRAFT_2020_12_URL); } else { mark_dialect_override(schema, DRAFT_2020_12_URL); } @@ -285,6 +296,7 @@ class Upgrade201909To202012 final : public SchemaTransformRule { std::pair> renames_; mutable bool resource_has_recursive_anchor_{false}; + mutable bool anchor_at_resource_root_{false}; mutable bool is_inside_contains_wrapper_{false}; mutable bool descendant_has_pending_pattern_{false}; mutable bool document_has_unevaluated_items_{false}; @@ -623,36 +635,12 @@ class Upgrade201909To202012 final : public SchemaTransformRule { return false; } - const auto &resource_pointer{closest.value().get().pointer}; - std::set seen; - return frame.any_subschema( - [&](const sourcemeta::core::SchemaFrame::Location &entry) -> bool { - if (!entry.pointer.starts_with(resource_pointer)) { - return false; - } - if (entry.type == - sourcemeta::core::SchemaFrame::LocationType::Resource && - entry.pointer.size() > resource_pointer.size()) { - return false; - } - const auto pointer_str{sourcemeta::core::to_string(entry.pointer)}; - if (seen.contains(pointer_str)) { - return false; - } - seen.insert(pointer_str); - - const auto absolute{sourcemeta::core::to_pointer(entry.pointer)}; - const auto &subschema{sourcemeta::core::get(root, absolute)}; - if (!subschema.is_object()) { - return false; - } - if (subschema.defines("$recursiveAnchor") && - subschema.at("$recursiveAnchor").is_boolean() && - subschema.at("$recursiveAnchor").to_boolean()) { - return true; - } - - return false; - }); + // A recursive reference binds to the anchor of the resource it sits in, + // and only that resource's root can declare one + const auto &resource{sourcemeta::core::get( + root, sourcemeta::core::to_pointer(closest.value().get().pointer))}; + return resource.is_object() && resource.defines("$recursiveAnchor") && + resource.at("$recursiveAnchor").is_boolean() && + resource.at("$recursiveAnchor").to_boolean(); } }; diff --git a/vendor/blaze/src/convert/rules/upgrade_dialect_override_cleanup.h b/vendor/blaze/src/convert/rules/upgrade_dialect_override_cleanup.h index a6d2b0b0c..138c589f4 100644 --- a/vendor/blaze/src/convert/rules/upgrade_dialect_override_cleanup.h +++ b/vendor/blaze/src/convert/rules/upgrade_dialect_override_cleanup.h @@ -6,22 +6,67 @@ class UpgradeDialectOverrideCleanup final : public SchemaTransformRule { [[nodiscard]] auto condition(const sourcemeta::core::JSON &schema, - const sourcemeta::core::JSON &, + const sourcemeta::core::JSON &root, const sourcemeta::core::SchemaVocabularies &, - const sourcemeta::core::SchemaFrame &, + const sourcemeta::core::SchemaFrame &frame, const sourcemeta::core::SchemaFrame::Location &location, const sourcemeta::core::SchemaWalker &, - const sourcemeta::core::SchemaResolver &, const bool) const + const sourcemeta::core::SchemaResolver &resolver, const bool) const -> bool override { ONLY_CONTINUE_IF(location.pointer.empty() && schema.is_object()); + this->redundant_.clear(); const auto *override_value{schema.try_at(DIALECT_OVERRIDE_KEYWORD)}; - ONLY_CONTINUE_IF(override_value != nullptr && override_value->is_string()); + if (override_value != nullptr && override_value->is_string()) { + return true; + } + + // A document that names a dialect of its own never bumps a `$schema` the + // ladder recognises, so nothing there will ever clear the markers that + // subschemas below it left behind. Every other document clears them when + // it bumps, and taking them early would strip state the ladder still needs + ONLY_CONTINUE_IF(dialect_position(declared_dialect(schema)) == 0); + + [[maybe_unused]] const auto visited{frame.any_subschema_under( + location.pointer, + [this, &root, &frame, &resolver]( + const sourcemeta::core::SchemaFrame::Location &entry) -> bool { + const auto entry_pointer{sourcemeta::core::to_pointer(entry.pointer)}; + const auto &entry_schema{sourcemeta::core::get(root, entry_pointer)}; + if (!entry_schema.is_object()) { + return false; + } + + const auto *marker{entry_schema.try_at(DIALECT_OVERRIDE_KEYWORD)}; + if (marker == nullptr || !marker->is_string()) { + return false; + } + + // Framing agreeing with what the marker claims is what makes it + // redundant. Until then it is the only record of the move + const auto vocabulary{marker_vocabulary(marker->to_string())}; + if (vocabulary.has_value() && frame.vocabularies(entry, resolver) + .contains(vocabulary.value())) { + this->redundant_.push_back(entry_pointer); + } - return true; + return false; + })}; + + return !this->redundant_.empty(); } auto transform(sourcemeta::core::JSON &schema) const -> void override { + if (!schema.defines(DIALECT_OVERRIDE_KEYWORD)) { + for (const auto &pointer : this->redundant_) { + sourcemeta::core::get(schema, pointer).erase(DIALECT_OVERRIDE_KEYWORD); + } + + return; + } + + const sourcemeta::core::JSON::String dialect{ + schema.at(DIALECT_OVERRIDE_KEYWORD).to_string()}; if (!schema.defines("$schema")) { sourcemeta::core::JSON dialect_value{ schema.at(DIALECT_OVERRIDE_KEYWORD).to_string()}; @@ -40,6 +85,37 @@ class UpgradeDialectOverrideCleanup final : public SchemaTransformRule { } } - drop_dialect_overrides(schema, true); + drop_dialect_overrides(schema, true, dialect); + } + +private: + // The vocabulary that stands for each dialect the ladder walks through, so + // that what framing reports can be told apart from what a marker claims + static auto marker_vocabulary(const std::string_view dialect) + -> std::optional { + using Known = SchemaVocabularies::Known; + static constexpr std::array, 6> ENTRIES{ + {{"http://json-schema.org/draft-03/schema#", + Known::JSON_SCHEMA_DRAFT_3}, + {"http://json-schema.org/draft-04/schema#", + Known::JSON_SCHEMA_DRAFT_4}, + {"http://json-schema.org/draft-06/schema#", + Known::JSON_SCHEMA_DRAFT_6}, + {"http://json-schema.org/draft-07/schema#", + Known::JSON_SCHEMA_DRAFT_7}, + {"https://json-schema.org/draft/2019-09/schema", + Known::JSON_SCHEMA_2019_09_CORE}, + {"https://json-schema.org/draft/2020-12/schema", + Known::JSON_SCHEMA_2020_12_CORE}}}; + + for (const auto &[uri, vocabulary] : ENTRIES) { + if (uri == dialect) { + return vocabulary; + } + } + + return std::nullopt; } + + mutable std::vector redundant_; }; diff --git a/vendor/blaze/src/convert/rules/upgrade_draft_3_to_draft_4.h b/vendor/blaze/src/convert/rules/upgrade_draft_3_to_draft_4.h index a41ff3dde..454da9bc3 100644 --- a/vendor/blaze/src/convert/rules/upgrade_draft_3_to_draft_4.h +++ b/vendor/blaze/src/convert/rules/upgrade_draft_3_to_draft_4.h @@ -56,7 +56,7 @@ class UpgradeDraft3ToDraft4 final : public SchemaTransformRule { if (schema.defines("$schema") && schema.at("$schema").is_string() && schema.at("$schema").to_string() == DRAFT_3_URL) { schema.assign("$schema", sourcemeta::core::JSON{DRAFT_4_URL}); - drop_dialect_overrides(schema, true); + drop_dialect_overrides(schema, true, DRAFT_4_URL); } else { mark_dialect_override(schema, DRAFT_4_URL); } diff --git a/vendor/blaze/src/convert/rules/upgrade_draft_4_to_draft_6.h b/vendor/blaze/src/convert/rules/upgrade_draft_4_to_draft_6.h index fbbbac6cc..d967c8e06 100644 --- a/vendor/blaze/src/convert/rules/upgrade_draft_4_to_draft_6.h +++ b/vendor/blaze/src/convert/rules/upgrade_draft_4_to_draft_6.h @@ -35,6 +35,15 @@ class UpgradeDraft4ToDraft6 final : public SchemaTransformRule { ONLY_CONTINUE_IF(sanitization_branch || other_branch || root_via_default_dialect); + // A meta-schema the document embeds decides the dialect its referrers are + // read under, so moving it before them would take them off this dialect + // before their turn + if (is_metaschema_target(schema, frame, location.pointer) && + has_pending_metaschema_referrer(root, frame, location.pointer, + has_pending_draft_4_pattern)) { + return false; + } + if (!sanitization_branch && other_branch && enclosing_resource_has_pending_sanitization(location, root, frame)) { return false; @@ -43,12 +52,17 @@ class UpgradeDraft4ToDraft6 final : public SchemaTransformRule { if (!sanitization_branch) { if (frame.any_subschema_under( location.pointer, - [&root](const sourcemeta::core::SchemaFrame::Location &entry) + [&root, + &frame](const sourcemeta::core::SchemaFrame::Location &entry) -> bool { const auto entry_pointer{ sourcemeta::core::to_pointer(entry.pointer)}; const auto &entry_schema{ sourcemeta::core::get(root, entry_pointer)}; + if (is_metaschema_target(entry_schema, frame, entry.pointer)) { + return false; + } + if (entry_schema.is_object() && entry_schema.defines("$ref")) { return false; } @@ -108,7 +122,7 @@ class UpgradeDraft4ToDraft6 final : public SchemaTransformRule { if (schema.defines("$schema") && schema.at("$schema").is_string() && schema.at("$schema").to_string() == DRAFT_4_URL) { schema.assign("$schema", sourcemeta::core::JSON{DRAFT_6_URL}); - drop_dialect_overrides(schema, true); + drop_dialect_overrides(schema, true, DRAFT_6_URL); } else { mark_dialect_override(schema, DRAFT_6_URL); } diff --git a/vendor/blaze/src/convert/rules/upgrade_draft_6_to_draft_7.h b/vendor/blaze/src/convert/rules/upgrade_draft_6_to_draft_7.h index 4313edc80..92e7b8317 100644 --- a/vendor/blaze/src/convert/rules/upgrade_draft_6_to_draft_7.h +++ b/vendor/blaze/src/convert/rules/upgrade_draft_6_to_draft_7.h @@ -34,7 +34,7 @@ class UpgradeDraft6ToDraft7 final : public SchemaTransformRule { if (schema.defines("$schema") && schema.at("$schema").is_string() && schema.at("$schema").to_string() == DRAFT_6_URL) { schema.assign("$schema", sourcemeta::core::JSON{DRAFT_7_URL}); - drop_dialect_overrides(schema, true); + drop_dialect_overrides(schema, true, DRAFT_7_URL); } else { mark_dialect_override(schema, DRAFT_7_URL); } diff --git a/vendor/blaze/src/convert/rules/upgrade_draft_7_to_draft_2019_09.h b/vendor/blaze/src/convert/rules/upgrade_draft_7_to_draft_2019_09.h index 0ed82597c..b3cb872d7 100644 --- a/vendor/blaze/src/convert/rules/upgrade_draft_7_to_draft_2019_09.h +++ b/vendor/blaze/src/convert/rules/upgrade_draft_7_to_draft_2019_09.h @@ -11,25 +11,16 @@ class UpgradeDraft7To201909 final : public SchemaTransformRule { const sourcemeta::core::SchemaFrame &frame, const sourcemeta::core::SchemaFrame::Location &location, const sourcemeta::core::SchemaWalker &, - const sourcemeta::core::SchemaResolver &, - const bool is_metaschema) const -> bool override { - this->metaschema_synthesis_pending_ = false; - + const sourcemeta::core::SchemaResolver &, const bool) const + -> bool override { ONLY_CONTINUE_IF( vocabularies.contains(SchemaVocabularies::Known::JSON_SCHEMA_DRAFT_7) && schema.is_object()); - const bool needs_dialect_transition{ - subschema_at_dialect(schema, location, DRAFT_7_URL) || - has_actionable_id_fragment(schema) || - has_actionable_dependencies(schema) || - has_actionable_ref_siblings(schema)}; - - const bool needs_metaschema_vocabulary{is_metaschema && - location.pointer.empty() && - !schema.defines("$vocabulary")}; - - ONLY_CONTINUE_IF(needs_dialect_transition || needs_metaschema_vocabulary); + ONLY_CONTINUE_IF(subschema_at_dialect(schema, location, DRAFT_7_URL) || + has_actionable_id_fragment(schema) || + has_actionable_dependencies(schema) || + has_actionable_ref_siblings(schema)); if (frame.any_subschema_under( location.pointer, @@ -45,7 +36,6 @@ class UpgradeDraft7To201909 final : public SchemaTransformRule { return false; } - this->metaschema_synthesis_pending_ = needs_metaschema_vocabulary; return true; } @@ -55,14 +45,10 @@ class UpgradeDraft7To201909 final : public SchemaTransformRule { this->split_id_fragment(schema); this->split_dependencies(schema); if (bump_schema(schema)) { - drop_dialect_overrides(schema, true); + drop_dialect_overrides(schema, true, DRAFT_2019_09_URL); } else { mark_dialect_override(schema, DRAFT_2019_09_URL); } - - if (this->metaschema_synthesis_pending_) { - synthesize_2019_09_vocabulary(schema); - } } [[nodiscard]] auto rereference(const std::string_view, @@ -91,19 +77,6 @@ class UpgradeDraft7To201909 final : public SchemaTransformRule { static constexpr std::string_view DRAFT_2019_09_URL{ "https://json-schema.org/draft/2019-09/schema"}; - static constexpr std::string_view VOCAB_2019_09_CORE_URL{ - "https://json-schema.org/draft/2019-09/vocab/core"}; - static constexpr std::string_view VOCAB_2019_09_APPLICATOR_URL{ - "https://json-schema.org/draft/2019-09/vocab/applicator"}; - static constexpr std::string_view VOCAB_2019_09_VALIDATION_URL{ - "https://json-schema.org/draft/2019-09/vocab/validation"}; - static constexpr std::string_view VOCAB_2019_09_META_DATA_URL{ - "https://json-schema.org/draft/2019-09/vocab/meta-data"}; - static constexpr std::string_view VOCAB_2019_09_FORMAT_URL{ - "https://json-schema.org/draft/2019-09/vocab/format"}; - static constexpr std::string_view VOCAB_2019_09_CONTENT_URL{ - "https://json-schema.org/draft/2019-09/vocab/content"}; - // NOLINTNEXTLINE(cert-err58-cpp,bugprone-throwing-static-initialization) static inline const std::array SHADOW_EXEMPT_KEYWORDS{ {"$schema", "$id", "title", "description", "default", "examples", @@ -131,8 +104,6 @@ class UpgradeDraft7To201909 final : public SchemaTransformRule { std::pair> renames_; - mutable bool metaschema_synthesis_pending_{false}; - static auto is_shadow_exempt(const std::string_view keyword) -> bool { return std::ranges::any_of(SHADOW_EXEMPT_KEYWORDS, [&keyword](const auto &candidate) -> auto { @@ -339,52 +310,6 @@ class UpgradeDraft7To201909 final : public SchemaTransformRule { return false; } - static auto synthesize_2019_09_vocabulary(sourcemeta::core::JSON &schema) - -> void { - std::string_view anchor; - if (schema.defines("$id")) { - anchor = "$id"; - } else if (schema.defines("$schema")) { - anchor = "$schema"; - } - - const std::string *next_key{nullptr}; - if (!anchor.empty()) { - bool found_anchor{false}; - for (const auto &entry : schema.as_object()) { - if (found_anchor) { - next_key = &entry.first; - break; - } - if (entry.first == anchor) { - found_anchor = true; - } - } - } - - if (next_key != nullptr) { - schema.try_assign_before( - "$vocabulary", sourcemeta::core::JSON::make_object(), *next_key); - } else { - schema.assign_assume_new("$vocabulary", - sourcemeta::core::JSON::make_object()); - } - - auto &vocabularies{schema.at("$vocabulary")}; - vocabularies.assign_assume_new(std::string{VOCAB_2019_09_CORE_URL}, - sourcemeta::core::JSON{true}); - vocabularies.assign_assume_new(std::string{VOCAB_2019_09_APPLICATOR_URL}, - sourcemeta::core::JSON{true}); - vocabularies.assign_assume_new(std::string{VOCAB_2019_09_VALIDATION_URL}, - sourcemeta::core::JSON{true}); - vocabularies.assign_assume_new(std::string{VOCAB_2019_09_META_DATA_URL}, - sourcemeta::core::JSON{true}); - vocabularies.assign_assume_new(std::string{VOCAB_2019_09_FORMAT_URL}, - sourcemeta::core::JSON{false}); - vocabularies.assign_assume_new(std::string{VOCAB_2019_09_CONTENT_URL}, - sourcemeta::core::JSON{true}); - } - static auto has_pending_pattern(const sourcemeta::core::JSON &subschema) -> bool { if (!subschema.is_object()) { diff --git a/vendor/core/CMakeLists.txt b/vendor/core/CMakeLists.txt index 8f94b3db1..3d0e39f6e 100644 --- a/vendor/core/CMakeLists.txt +++ b/vendor/core/CMakeLists.txt @@ -15,6 +15,7 @@ option(SOURCEMETA_CORE_LANG_OPTIONS "Build the Sourcemeta Core Options library" option(SOURCEMETA_CORE_LANG_TEXT "Build the Sourcemeta Core language text library" ON) option(SOURCEMETA_CORE_LANG_STACKTRACE "Build the Sourcemeta Core language stacktrace library" ON) option(SOURCEMETA_CORE_LANG_TEST "Build the Sourcemeta Core language test library" ON) +option(SOURCEMETA_CORE_LANG_BENCHMARK "Build the Sourcemeta Core language benchmark library" ON) option(SOURCEMETA_CORE_UNICODE "Build the Sourcemeta Core Unicode library" ON) option(SOURCEMETA_CORE_PUNYCODE "Build the Sourcemeta Core Punycode library" ON) option(SOURCEMETA_CORE_TIME "Build the Sourcemeta Core time library" ON) @@ -54,11 +55,10 @@ option(SOURCEMETA_CORE_TESTS "Build the Sourcemeta Core tests" OFF) option(SOURCEMETA_CORE_TESTS_CI "Build the Sourcemeta Core CI tests" OFF) option(SOURCEMETA_CORE_BENCHMARK "Build the Sourcemeta Core benchmarks" OFF) option(SOURCEMETA_CORE_DOCS "Build the Sourcemeta Core docs" OFF) -option(SOURCEMETA_CORE_CLANG_TIDY_ANALYZER "Run the Clang static analyzer alongside ClangTidy" OFF) +option(SOURCEMETA_CORE_CLANG_TIDY "Run ClangTidy alongside compilation wherever this project can" ON) option(SOURCEMETA_CORE_INSTALL "Install the Sourcemeta Core library" ON) option(SOURCEMETA_CORE_ADDRESS_SANITIZER "Build Sourcemeta Core with an address sanitizer" OFF) option(SOURCEMETA_CORE_UNDEFINED_SANITIZER "Build Sourcemeta Core with an undefined behavior sanitizer" OFF) -option(SOURCEMETA_CORE_CONTRIB_GOOGLEBENCHMARK "Build the GoogleBenchmark library for downstream consumers" OFF) option(SOURCEMETA_CORE_USE_SYSTEM_ALLOCATOR "Always use the system allocator" OFF) include(Sourcemeta) @@ -160,6 +160,10 @@ if(SOURCEMETA_CORE_LANG_TEST) add_subdirectory(src/lang/test) endif() +if(SOURCEMETA_CORE_LANG_BENCHMARK) + add_subdirectory(src/lang/benchmark) +endif() + if(SOURCEMETA_CORE_UNICODE) add_subdirectory(src/core/unicode) endif() @@ -285,7 +289,6 @@ if(SOURCEMETA_CORE_CSS) endif() if(SOURCEMETA_CORE_MARKDOWN) - find_package(CMarkGFM REQUIRED) add_subdirectory(src/core/markdown) endif() @@ -311,10 +314,6 @@ endif() # Testing -if(SOURCEMETA_CORE_CONTRIB_GOOGLEBENCHMARK OR SOURCEMETA_CORE_BENCHMARK) - find_package(GoogleBenchmark REQUIRED) -endif() - if(SOURCEMETA_CORE_TESTS) enable_testing() @@ -364,6 +363,10 @@ if(SOURCEMETA_CORE_TESTS) add_subdirectory(test/test) endif() + if(SOURCEMETA_CORE_LANG_BENCHMARK) + add_subdirectory(test/benchmark) + endif() + if(SOURCEMETA_CORE_UNICODE) add_subdirectory(test/unicode) endif() diff --git a/vendor/core/DEPENDENCIES b/vendor/core/DEPENDENCIES index a5810af50..9c86c5aa4 100644 --- a/vendor/core/DEPENDENCIES +++ b/vendor/core/DEPENDENCIES @@ -2,12 +2,10 @@ vendorpull https://github.com/sourcemeta/vendorpull 89f348a97842e05aeab45d338d41 mimalloc https://github.com/microsoft/mimalloc v3.4.4 jsontestsuite https://github.com/nst/JSONTestSuite d64aefb55228d9584d3e5b2433f720ea8fd00c82 yaml-test-suite https://github.com/yaml/yaml-test-suite data-2022-01-17 -cmark-gfm https://github.com/github/cmark-gfm 587a12bb54d95ac37241377e6ddc93ea0e45439b uritemplate-test https://github.com/uri-templates/uritemplate-test 1eb27ab4462b9e5819dc47db99044f5fd1fa9bc7 pyca-cryptography https://github.com/pyca/cryptography 9747d06e83764e7f1ea4c04daf134cb8f861700b wycheproof https://github.com/C2SP/wycheproof 6d7cccd0fcb1917368579adeeac10fe802f1b521 pcre2 https://github.com/PCRE2Project/pcre2 pcre2-10.48 -googlebenchmark https://github.com/google/benchmark 378fe693a1ef51500db21b11ff05a8018c5f0e55 unicodetools https://github.com/unicode-org/unicodetools final-17.0-20250910 jose-cookbook https://github.com/ietf-jose/cookbook 13692b68bfc18b99557a5b1ed311fd5077bfff04 w3c-json-ld https://github.com/w3c/json-ld-api 8654ac22b6cf4f441d2fee915ae634d36b5a8067 diff --git a/vendor/core/cmake/FindCMarkGFM.cmake b/vendor/core/cmake/FindCMarkGFM.cmake deleted file mode 100644 index 0155c9839..000000000 --- a/vendor/core/cmake/FindCMarkGFM.cmake +++ /dev/null @@ -1,121 +0,0 @@ -if(NOT CMarkGFM_FOUND) - set(CMARK_GFM_DIR "${PROJECT_SOURCE_DIR}/vendor/cmark-gfm") - set(CMARK_GFM_SOURCE_DIR "${CMARK_GFM_DIR}/src") - set(CMARK_GFM_EXTENSIONS_DIR "${CMARK_GFM_DIR}/extensions") - set(CMARK_GFM_BINARY_DIR "${PROJECT_BINARY_DIR}/cmark-gfm") - - file(MAKE_DIRECTORY "${CMARK_GFM_BINARY_DIR}/include") - - set(CMARK_GFM_VERSION_MAJOR 0) - set(CMARK_GFM_VERSION_MINOR 0) - set(CMARK_GFM_VERSION_PATCH 0) - set(CMARK_GFM_VERSION_GFM 0) - - include(CheckIncludeFile) - include(CheckSymbolExists) - check_include_file(stdbool.h HAVE_STDBOOL_H) - check_symbol_exists(__builtin_expect "" HAVE___BUILTIN_EXPECT) - - if(SOURCEMETA_COMPILER_LLVM OR SOURCEMETA_COMPILER_GCC) - set(HAVE___ATTRIBUTE__ 1) - endif() - - configure_file( - "${CMARK_GFM_SOURCE_DIR}/config.h.in" - "${CMARK_GFM_BINARY_DIR}/include/config.h") - - set(_SAVED_PROJECT_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) - set(_SAVED_PROJECT_VERSION_MINOR ${PROJECT_VERSION_MINOR}) - set(_SAVED_PROJECT_VERSION_PATCH ${PROJECT_VERSION_PATCH}) - set(PROJECT_VERSION_MAJOR ${CMARK_GFM_VERSION_MAJOR}) - set(PROJECT_VERSION_MINOR ${CMARK_GFM_VERSION_MINOR}) - set(PROJECT_VERSION_PATCH ${CMARK_GFM_VERSION_PATCH}) - set(PROJECT_VERSION_GFM ${CMARK_GFM_VERSION_GFM}) - configure_file( - "${CMARK_GFM_SOURCE_DIR}/cmark-gfm_version.h.in" - "${CMARK_GFM_BINARY_DIR}/include/cmark-gfm_version.h") - set(PROJECT_VERSION_MAJOR ${_SAVED_PROJECT_VERSION_MAJOR}) - set(PROJECT_VERSION_MINOR ${_SAVED_PROJECT_VERSION_MINOR}) - set(PROJECT_VERSION_PATCH ${_SAVED_PROJECT_VERSION_PATCH}) - unset(_SAVED_PROJECT_VERSION_MAJOR) - unset(_SAVED_PROJECT_VERSION_MINOR) - unset(_SAVED_PROJECT_VERSION_PATCH) - - set(CMARK_GFM_CORE_SOURCES - "${CMARK_GFM_SOURCE_DIR}/arena.c" - "${CMARK_GFM_SOURCE_DIR}/blocks.c" - "${CMARK_GFM_SOURCE_DIR}/buffer.c" - "${CMARK_GFM_SOURCE_DIR}/cmark.c" - "${CMARK_GFM_SOURCE_DIR}/cmark_ctype.c" - "${CMARK_GFM_SOURCE_DIR}/commonmark.c" - "${CMARK_GFM_SOURCE_DIR}/footnotes.c" - "${CMARK_GFM_SOURCE_DIR}/houdini_href_e.c" - "${CMARK_GFM_SOURCE_DIR}/houdini_html_e.c" - "${CMARK_GFM_SOURCE_DIR}/houdini_html_u.c" - "${CMARK_GFM_SOURCE_DIR}/html.c" - "${CMARK_GFM_SOURCE_DIR}/inlines.c" - "${CMARK_GFM_SOURCE_DIR}/iterator.c" - "${CMARK_GFM_SOURCE_DIR}/latex.c" - "${CMARK_GFM_SOURCE_DIR}/linked_list.c" - "${CMARK_GFM_SOURCE_DIR}/man.c" - "${CMARK_GFM_SOURCE_DIR}/map.c" - "${CMARK_GFM_SOURCE_DIR}/node.c" - "${CMARK_GFM_SOURCE_DIR}/plaintext.c" - "${CMARK_GFM_SOURCE_DIR}/plugin.c" - "${CMARK_GFM_SOURCE_DIR}/references.c" - "${CMARK_GFM_SOURCE_DIR}/registry.c" - "${CMARK_GFM_SOURCE_DIR}/render.c" - "${CMARK_GFM_SOURCE_DIR}/scanners.c" - "${CMARK_GFM_SOURCE_DIR}/syntax_extension.c" - "${CMARK_GFM_SOURCE_DIR}/utf8.c" - "${CMARK_GFM_SOURCE_DIR}/xml.c") - - set(CMARK_GFM_EXTENSION_SOURCES - "${CMARK_GFM_EXTENSIONS_DIR}/autolink.c" - "${CMARK_GFM_EXTENSIONS_DIR}/core-extensions.c" - "${CMARK_GFM_EXTENSIONS_DIR}/ext_scanners.c" - "${CMARK_GFM_EXTENSIONS_DIR}/strikethrough.c" - "${CMARK_GFM_EXTENSIONS_DIR}/table.c" - "${CMARK_GFM_EXTENSIONS_DIR}/tagfilter.c" - "${CMARK_GFM_EXTENSIONS_DIR}/tasklist.c") - - # Merged into the library that uses it, so that no archive, no header and - # no CMake package of our own build of it reaches an installed consumer - add_library(cmark_gfm OBJECT - ${CMARK_GFM_CORE_SOURCES} ${CMARK_GFM_EXTENSION_SOURCES}) - sourcemeta_add_default_options(PRIVATE cmark_gfm) - - if(SOURCEMETA_COMPILER_LLVM OR SOURCEMETA_COMPILER_GCC) - target_compile_options(cmark_gfm PRIVATE -Wno-sign-conversion) - target_compile_options(cmark_gfm PRIVATE -Wno-unused-parameter) - endif() - - if(SOURCEMETA_COMPILER_MSVC) - target_compile_options(cmark_gfm PRIVATE /wd4100) - target_compile_definitions(cmark_gfm PRIVATE _CRT_SECURE_NO_WARNINGS) - endif() - - target_include_directories(cmark_gfm PRIVATE - "${CMARK_GFM_BINARY_DIR}/include" - "${CMARK_GFM_SOURCE_DIR}" - "${CMARK_GFM_EXTENSIONS_DIR}") - - target_include_directories(cmark_gfm PUBLIC - "$" - "$" - "$") - - target_compile_definitions(cmark_gfm PRIVATE HAVE_CONFIG_H) - # Marking every entry point as visible would publish this library from the - # one it is merged into, where it can collide with a real installation of it - target_compile_definitions(cmark_gfm PUBLIC CMARK_GFM_STATIC_DEFINE) - - include(GenerateExportHeader) - generate_export_header(cmark_gfm - BASE_NAME CMARK_GFM - EXPORT_FILE_NAME "${CMARK_GFM_BINARY_DIR}/include/cmark-gfm_export.h") - - add_library(CMarkGFM::cmark_gfm ALIAS cmark_gfm) - - set(CMarkGFM_FOUND ON) -endif() diff --git a/vendor/core/cmake/FindGoogleBenchmark.cmake b/vendor/core/cmake/FindGoogleBenchmark.cmake deleted file mode 100644 index 096e0396d..000000000 --- a/vendor/core/cmake/FindGoogleBenchmark.cmake +++ /dev/null @@ -1,24 +0,0 @@ -if(NOT Benchmark_FOUND) - set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "enable testing of the benchmark library") - - # This library compiles its own sources with warnings as errors, and those - # warnings are not ours to answer for on every compiler that we support - set(BENCHMARK_ENABLE_WERROR OFF CACHE BOOL "enable warnings as errors when building the benchmark library") - - add_subdirectory("${PROJECT_SOURCE_DIR}/vendor/googlebenchmark") - - # The option above only governs the warnings as errors that this library - # turns on for itself. The one that consumers set reaches every target in - # the build, including this one - set_target_properties(benchmark benchmark_main - PROPERTIES COMPILE_WARNING_AS_ERROR OFF) - - # Consumers run static analysis over their own benchmark sources, and the - # headers this library exposes are not theirs to answer for - get_target_property(BENCHMARK_INCLUDE_DIRECTORIES - benchmark INTERFACE_INCLUDE_DIRECTORIES) - set_target_properties(benchmark PROPERTIES - INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${BENCHMARK_INCLUDE_DIRECTORIES}") - - set(Benchmark_FOUND ON) -endif() diff --git a/vendor/core/cmake/Sourcemeta.cmake b/vendor/core/cmake/Sourcemeta.cmake index 2392d658b..b150ddd42 100644 --- a/vendor/core/cmake/Sourcemeta.cmake +++ b/vendor/core/cmake/Sourcemeta.cmake @@ -14,7 +14,7 @@ include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/clang-format.cmake") include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/shellcheck.cmake") include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/doxygen.cmake") include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/test.cmake") -include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/googlebenchmark.cmake") +include("${SOURCEMETA_UTILITIES_DIRECTORY}/targets/benchmark.cmake") include("${SOURCEMETA_UTILITIES_DIRECTORY}/clang-tidy.cmake") # To let downstream projects directly include this file diff --git a/vendor/core/cmake/common/clang-tidy.cmake b/vendor/core/cmake/common/clang-tidy.cmake index 00d8b2407..f5b8116ab 100644 --- a/vendor/core/cmake/common/clang-tidy.cmake +++ b/vendor/core/cmake/common/clang-tidy.cmake @@ -91,8 +91,19 @@ function(sourcemeta_clang_tidy_attempt_enable) message(FATAL_ERROR "You must pass the target name using the TARGET option") endif() + # Whether to analyse at all is the caller's to decide, while whether this + # project can is decided here. A project that vendors this without declaring + # the option keeps the behaviour it had before the option existed, so only an + # explicit refusal turns the tool off + if(DEFINED SOURCEMETA_CORE_CLANG_TIDY AND NOT SOURCEMETA_CORE_CLANG_TIDY) + return() + endif() + # TODO: Support other platforms too, like Linux - if(APPLE AND SOURCEMETA_COMPILER_LLVM) + # + # A shared build compiles the same sources as a static one, differing only in + # linkage, so analysing both finds the same things twice at full price + if(APPLE AND SOURCEMETA_COMPILER_LLVM AND NOT BUILD_SHARED_LIBS) message(STATUS "Enabling ClangTidy alongside compilation for target ${SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_ENABLE_TARGET}") else() return() @@ -119,12 +130,8 @@ function(sourcemeta_clang_tidy_attempt_enable) CACHE STRING "CXX_CLANG_TIDY") endif() - # The static analyzer roughly triples ClangTidy time per translation unit, so - # it stays out of the local edit loop. This sits outside the cache guard above - # so that toggling the option takes effect on an existing build tree. The - # `--checks` argument is appended to the `Checks` option of the configuration - # file rather than replacing it, so the group composes with whatever the file - # enables + # This sits outside the cache guard above so that every target composes its + # own arguments rather than freezing the first target's into the cache set(TARGET_CLANG_TIDY "${SOURCEMETA_CXX_CLANG_TIDY}") # This tool bundles a newer compiler than the ones this project builds with, @@ -132,10 +139,6 @@ function(sourcemeta_clang_tidy_attempt_enable) # a feature of a language revision that is yet to be released list(APPEND TARGET_CLANG_TIDY "--extra-arg=-Wno-c2y-extensions") - if(SOURCEMETA_CORE_CLANG_TIDY_ANALYZER) - list(APPEND TARGET_CLANG_TIDY "--checks=clang-analyzer-*") - endif() - set_target_properties("${SOURCEMETA_TARGET_CLANG_TIDY_ATTEMPT_ENABLE_TARGET}" PROPERTIES CXX_CLANG_TIDY "${TARGET_CLANG_TIDY}") endfunction() diff --git a/vendor/core/cmake/common/targets/benchmark.cmake b/vendor/core/cmake/common/targets/benchmark.cmake new file mode 100644 index 000000000..971fbb1c3 --- /dev/null +++ b/vendor/core/cmake/common/targets/benchmark.cmake @@ -0,0 +1,14 @@ +function(sourcemeta_benchmark) + cmake_parse_arguments(SOURCEMETA_BENCHMARK "" + "NAMESPACE;PROJECT" "SOURCES" ${ARGN}) + + sourcemeta_executable( + NAMESPACE "${SOURCEMETA_BENCHMARK_NAMESPACE}" + PROJECT "${SOURCEMETA_BENCHMARK_PROJECT}" + NAME benchmarks + SOURCES "${SOURCEMETA_BENCHMARK_SOURCES}" + OUTPUT TARGET_NAME) + + target_link_libraries("${TARGET_NAME}" PRIVATE sourcemeta::core::benchmark) + target_link_libraries("${TARGET_NAME}" PRIVATE sourcemeta::core::benchmark_main) +endfunction() diff --git a/vendor/core/cmake/common/targets/googlebenchmark.cmake b/vendor/core/cmake/common/targets/googlebenchmark.cmake deleted file mode 100644 index 86cf3cd66..000000000 --- a/vendor/core/cmake/common/targets/googlebenchmark.cmake +++ /dev/null @@ -1,14 +0,0 @@ -function(sourcemeta_googlebenchmark) - cmake_parse_arguments(SOURCEMETA_GOOGLEBENCHMARK "" - "NAMESPACE;PROJECT" "SOURCES" ${ARGN}) - - sourcemeta_executable( - NAMESPACE "${SOURCEMETA_GOOGLEBENCHMARK_NAMESPACE}" - PROJECT "${SOURCEMETA_GOOGLEBENCHMARK_PROJECT}" - NAME benchmark - SOURCES "${SOURCEMETA_GOOGLEBENCHMARK_SOURCES}" - OUTPUT TARGET_NAME) - - target_link_libraries("${TARGET_NAME}" PRIVATE benchmark::benchmark) - target_link_libraries("${TARGET_NAME}" PRIVATE benchmark::benchmark_main) -endfunction() diff --git a/vendor/core/config.cmake.in b/vendor/core/config.cmake.in index 189f0c87d..f1a149456 100644 --- a/vendor/core/config.cmake.in +++ b/vendor/core/config.cmake.in @@ -5,6 +5,7 @@ list(APPEND SOURCEMETA_CORE_COMPONENTS ${Core_FIND_COMPONENTS}) list(APPEND SOURCEMETA_CORE_COMPONENTS ${core_FIND_COMPONENTS}) if(NOT SOURCEMETA_CORE_COMPONENTS) list(APPEND SOURCEMETA_CORE_COMPONENTS allocator) + list(APPEND SOURCEMETA_CORE_COMPONENTS benchmark) list(APPEND SOURCEMETA_CORE_COMPONENTS preprocessor) list(APPEND SOURCEMETA_CORE_COMPONENTS io) list(APPEND SOURCEMETA_CORE_COMPONENTS process) @@ -352,7 +353,17 @@ foreach(component ${SOURCEMETA_CORE_COMPONENTS}) include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_text.cmake") include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_css.cmake") elseif(component STREQUAL "markdown") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_io.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_text.cmake") include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_unicode.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_punycode.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_idna.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_dns.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_ip.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_uri.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_email.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_preprocessor.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_html.cmake") include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_markdown.cmake") elseif(component STREQUAL "diff") include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_text.cmake") @@ -367,6 +378,17 @@ foreach(component ${SOURCEMETA_CORE_COMPONENTS}) include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_text.cmake") elseif(component STREQUAL "stacktrace") include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_stacktrace.cmake") + elseif(component STREQUAL "benchmark") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_io.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_preprocessor.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_numeric.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_text.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_unicode.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_json.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_options.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_process.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_benchmark.cmake") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_benchmark_main.cmake") elseif(component STREQUAL "test") include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_text.cmake") include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_diff.cmake") diff --git a/vendor/core/src/core/dns/hostname.cc b/vendor/core/src/core/dns/hostname.cc index 2b862935f..01ea08ca3 100644 --- a/vendor/core/src/core/dns/hostname.cc +++ b/vendor/core/src/core/dns/hostname.cc @@ -6,6 +6,27 @@ namespace sourcemeta::core { +auto is_hostname_label(const std::string_view value) -> bool { + // RFC 1035 §2.3.4: per-label cap is 63 octets + if (value.empty() || value.size() > 63) { + return false; + } + + // RFC 1123 §2.1: first character must be let-dig, never hyphen, and RFC 952 + // §B ends a label in a let-dig too, where let-dig = ALPHA / DIGIT + if (!is_alphanum(value.front()) || !is_alphanum(value.back())) { + return false; + } + + for (const auto character : value) { + if (character != '-' && !is_alphanum(character)) { + return false; + } + } + + return true; +} + auto is_hostname(const std::string_view value) -> bool { // RFC 952 §B: requires at least one if (value.empty()) { @@ -19,39 +40,11 @@ auto is_hostname(const std::string_view value) -> bool { return false; } - std::string_view::size_type position{0}; - while (position < value.size()) { - const auto label_start{position}; - bool last_was_hyphen{false}; - bool label_has_content{false}; - - while (position < value.size() && value[position] != '.') { - const auto character{value[position]}; - if (character == '-') { - // RFC 1123 §2.1: first character must be let-dig, never hyphen - if (!label_has_content) { - return false; - } - last_was_hyphen = true; - position += 1; - label_has_content = true; - continue; - } - - // RFC 952 §B: let-dig = ALPHA / DIGIT - if (is_alphanum(character)) { - last_was_hyphen = false; - position += 1; - label_has_content = true; - continue; - } - - return false; - } - - // RFC 1035 §2.3.4: per-label cap is 63 octets - const auto label_length{position - label_start}; - if (label_length == 0 || label_length > 63 || last_was_hyphen) { + std::string_view remaining{value}; + while (true) { + const auto dot{remaining.find('.')}; + const auto label{remaining.substr(0, dot)}; + if (!is_hostname_label(label)) { return false; } @@ -59,23 +52,21 @@ auto is_hostname(const std::string_view value) -> bool { // case-insensitively. A-labels must also satisfy RFC 5891 §4.2.3 and // RFC 5892 (Punycode round-trip, IDNA 2008 derived properties, // contextual rules) - const auto label{value.substr(label_start, label_length)}; if (starts_with_ignore_case(label, "xn--") && !idna_is_valid_a_label(label)) { return false; } - if (position < value.size()) { - // value[position] == '.' - position += 1; - if (position == value.size()) { - // Trailing dot is not part of the host name grammar - return false; - } + if (dot == std::string_view::npos) { + return true; } - } - return true; + remaining.remove_prefix(dot + 1); + // Trailing dot is not part of the host name grammar + if (remaining.empty()) { + return false; + } + } } } // namespace sourcemeta::core diff --git a/vendor/core/src/core/dns/include/sourcemeta/core/dns.h b/vendor/core/src/core/dns/include/sourcemeta/core/dns.h index ba3b1985f..ab8f1702d 100644 --- a/vendor/core/src/core/dns/include/sourcemeta/core/dns.h +++ b/vendor/core/src/core/dns/include/sourcemeta/core/dns.h @@ -18,6 +18,25 @@ namespace sourcemeta::core { +/// @ingroup dns +/// Check whether the given string is a valid label of an Internet host name, +/// which RFC 1123 Section 2.1 and RFC 952 Section B make of a letter or digit, +/// followed by letters, digits, and hyphens, and ending in a letter or digit, +/// within the 63 octets that RFC 1035 Section 2.3.4 allows. For example: +/// +/// ```cpp +/// #include +/// +/// #include +/// +/// assert(sourcemeta::core::is_hostname_label("example")); +/// assert(sourcemeta::core::is_hostname_label("1host")); +/// assert(!sourcemeta::core::is_hostname_label("-bad")); +/// assert(!sourcemeta::core::is_hostname_label("bad-")); +/// ``` +SOURCEMETA_CORE_DNS_EXPORT +auto is_hostname_label(const std::string_view value) -> bool; + /// @ingroup dns /// Check whether the given string is a valid Internet host name per /// RFC 1123 Section 2.1, which relaxes the first-character rule of diff --git a/vendor/core/src/core/email/email.cc b/vendor/core/src/core/email/email.cc index 639acfd03..fd15ad1cd 100644 --- a/vendor/core/src/core/email/email.cc +++ b/vendor/core/src/core/email/email.cc @@ -163,6 +163,39 @@ auto is_idn_email_uts46(const std::string_view value) -> bool { return mailbox_separator(value).has_value(); } +auto is_html_email(const std::string_view value) -> bool { + // HTML Standard valid email address: email = 1*( atext / "." ) "@" label + // *( "." label ), where the at sign is not atext, so the first one separates + // the local part from the domain + const auto separator{value.find('@')}; + if (separator == std::string_view::npos || separator == 0) { + return false; + } + + for (const auto character : value.substr(0, separator)) { + if (character != '.' && !is_atext(character)) { + return false; + } + } + + auto domain{value.substr(separator + 1)}; + while (true) { + // HTML Standard valid email address: label = let-dig [ [ ldh-str ] + // let-dig ], which is the label of a host name, limited to a length of 63 + // characters by RFC 1034 §3.5 + const auto dot{domain.find('.')}; + if (!is_hostname_label(domain.substr(0, dot))) { + return false; + } + + if (dot == std::string_view::npos) { + return true; + } + + domain.remove_prefix(dot + 1); + } +} + auto email_domain(const std::string_view value) -> std::string_view { const auto separator{mailbox_separator(value)}; if (!separator.has_value()) { diff --git a/vendor/core/src/core/email/include/sourcemeta/core/email.h b/vendor/core/src/core/email/include/sourcemeta/core/email.h index 8e8e43291..b9e311f41 100644 --- a/vendor/core/src/core/email/include/sourcemeta/core/email.h +++ b/vendor/core/src/core/email/include/sourcemeta/core/email.h @@ -106,6 +106,29 @@ auto is_idn_email(const std::string_view value) -> bool; SOURCEMETA_CORE_EMAIL_EXPORT auto is_idn_email_uts46(const std::string_view value) -> bool; +/// @ingroup email +/// Check whether the given string is a valid email address per the HTML +/// Standard, the grammar behind the `email` input type, which deliberately +/// departs from RFC 5322. The local part is any sequence of `atext` characters +/// and dots, and the domain is a dot-separated sequence of letter-digit-hyphen +/// labels of up to 63 characters that neither start nor end with a hyphen. +/// Quoted strings, comments, and address literals are not accepted. See +/// https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address. +/// For example: +/// +/// ```cpp +/// #include +/// +/// #include +/// +/// assert(sourcemeta::core::is_html_email("user@example.com")); +/// assert(sourcemeta::core::is_html_email(".a..b.@example.com")); +/// assert(!sourcemeta::core::is_html_email("\"a b\"@example.com")); +/// assert(!sourcemeta::core::is_html_email("user@[192.168.1.1]")); +/// ``` +SOURCEMETA_CORE_EMAIL_EXPORT +auto is_html_email(const std::string_view value) -> bool; + /// @ingroup email /// Produce the domain half of a valid RFC 5321 `Mailbox`, returning an empty /// view when the input is not one, which no valid mailbox can otherwise yield diff --git a/vendor/core/src/core/gzip/deflate.h b/vendor/core/src/core/gzip/deflate.h index 509fcb28a..3fcbc67e1 100644 --- a/vendor/core/src/core/gzip/deflate.h +++ b/vendor/core/src/core/gzip/deflate.h @@ -89,7 +89,7 @@ class DeflateBitWriter { auto flush() -> void { std::uint64_t word{this->buffer_}; - if (std::endian::native == std::endian::big) { + if constexpr (std::endian::native == std::endian::big) { word = std::byteswap(word); } @@ -542,7 +542,7 @@ class DeflateEncoder { static auto load_32(const std::uint8_t *data) -> std::uint32_t { std::uint32_t word{0}; std::memcpy(&word, data, sizeof(word)); - if (std::endian::native == std::endian::big) { + if constexpr (std::endian::native == std::endian::big) { word = std::byteswap(word); } @@ -552,7 +552,7 @@ class DeflateEncoder { static auto load_64(const std::uint8_t *data) -> std::uint64_t { std::uint64_t word{0}; std::memcpy(&word, data, sizeof(word)); - if (std::endian::native == std::endian::big) { + if constexpr (std::endian::native == std::endian::big) { word = std::byteswap(word); } diff --git a/vendor/core/src/core/gzip/inflate.h b/vendor/core/src/core/gzip/inflate.h index 046a95283..7f4aa589a 100644 --- a/vendor/core/src/core/gzip/inflate.h +++ b/vendor/core/src/core/gzip/inflate.h @@ -740,7 +740,7 @@ class InflateDecoder { static auto load_word(const std::uint8_t *data) -> std::uint64_t { std::uint64_t word{0}; std::memcpy(&word, data, sizeof(word)); - if (std::endian::native == std::endian::big) { + if constexpr (std::endian::native == std::endian::big) { word = std::byteswap(word); } diff --git a/vendor/core/src/core/html/escape.cc b/vendor/core/src/core/html/escape.cc index 0615fd447..bb318a692 100644 --- a/vendor/core/src/core/html/escape.cc +++ b/vendor/core/src/core/html/escape.cc @@ -1,6 +1,7 @@ #include -#include // std::string +#include // std::size_t +#include // std::string namespace sourcemeta::core { @@ -125,112 +126,4 @@ auto html_escape(std::string &text) -> void { }); } -static auto needs_escape(const std::string_view input) -> bool { - for (std::string_view::size_type position{0}; position < input.size(); - position += 1) { - // The no-break space also requires escaping (HTML Living Standard "escaping - // a string" step 2) - if (static_cast(input[position]) == 0xC2 && - position + 1 < input.size() && - static_cast(input[position + 1]) == 0xA0) { - return true; - } - - switch (input[position]) { - case '&': - case '<': - case '>': - case '"': - case '\'': - return true; - default: - break; - } - } - - return false; -} - -auto html_escape_append(std::string &output, const std::string_view input) - -> void { - if (!needs_escape(input)) { - output += input; - return; - } - - for (std::string_view::size_type position{0}; position < input.size(); - position += 1) { - // The no-break space is replaced by its named entity (HTML Living Standard - // "escaping a string" step 2) - if (static_cast(input[position]) == 0xC2 && - position + 1 < input.size() && - static_cast(input[position + 1]) == 0xA0) { - output += " "; - position += 1; - continue; - } - - switch (input[position]) { - case '&': - output += "&"; - break; - case '<': - output += "<"; - break; - case '>': - output += ">"; - break; - case '"': - output += """; - break; - case '\'': - output += "'"; - break; - default: - output += input[position]; - } - } -} - -auto html_escape_append(HTMLBuffer &output, const std::string_view input) - -> void { - if (!needs_escape(input)) { - output.append(input); - return; - } - - for (std::string_view::size_type position{0}; position < input.size(); - position += 1) { - // The no-break space is replaced by its named entity (HTML Living Standard - // "escaping a string" step 2) - if (static_cast(input[position]) == 0xC2 && - position + 1 < input.size() && - static_cast(input[position + 1]) == 0xA0) { - output.append(" "); - position += 1; - continue; - } - - switch (input[position]) { - case '&': - output.append("&"); - break; - case '<': - output.append("<"); - break; - case '>': - output.append(">"); - break; - case '"': - output.append("""); - break; - case '\'': - output.append("'"); - break; - default: - output.append(input[position]); - } - } -} - } // namespace sourcemeta::core diff --git a/vendor/core/src/core/html/include/sourcemeta/core/html_buffer.h b/vendor/core/src/core/html/include/sourcemeta/core/html_buffer.h index d72b08ac1..4f410bd94 100644 --- a/vendor/core/src/core/html/include/sourcemeta/core/html_buffer.h +++ b/vendor/core/src/core/html/include/sourcemeta/core/html_buffer.h @@ -7,10 +7,13 @@ #include +#include // assert +#include // std::size_t #include // std::memcpy #include // std::ostream #include // std::string #include // std::string_view +#include // std::cmp_less, std::move namespace sourcemeta::core { @@ -24,17 +27,17 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLBuffer { HTMLBuffer(HTMLBuffer &&) = delete; auto operator=(HTMLBuffer &&) -> HTMLBuffer & = delete; - /// Reserve a number of bytes of capacity up front + /// Reserve capacity for at least a number of bytes in total up front, + /// keeping the accumulated contents SOURCEMETA_FORCEINLINE auto reserve(const std::size_t bytes) -> void { - this->buffer_.resize(bytes); - this->cursor_ = this->buffer_.data(); - this->end_ = this->cursor_ + bytes; + if (this->capacity() < bytes) { + this->reallocate(bytes); + } } /// Append a single character to the buffer SOURCEMETA_FORCEINLINE auto append(const char character) -> void { - if ((this->cursor_ == nullptr) || this->cursor_ >= this->end_) - [[unlikely]] { + if (this->cursor_ == this->end_) [[unlikely]] { this->grow(1); } @@ -49,11 +52,7 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLBuffer { return; } - const auto remaining{ - (this->cursor_ != nullptr) - ? static_cast(this->end_ - this->cursor_) - : 0UZ}; - if (remaining < length) [[unlikely]] { + if (std::cmp_less(this->end_ - this->cursor_, length)) [[unlikely]] { this->grow(length); } @@ -61,23 +60,91 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLBuffer { this->cursor_ += length; } - /// Get the accumulated contents of the buffer - [[nodiscard]] SOURCEMETA_FORCEINLINE auto str() -> const std::string & { - if (this->cursor_ != nullptr) { - this->buffer_.resize( - static_cast(this->cursor_ - this->buffer_.data())); - this->cursor_ = nullptr; - this->end_ = nullptr; + /// Reserve capacity for at least a number of bytes on top of the accumulated + /// contents, so that appending up to that many bytes through + /// `append_unchecked` needs no further capacity checks + SOURCEMETA_FORCEINLINE auto reserve_additional(const std::size_t bytes) + -> void { + if (std::cmp_less(this->end_ - this->cursor_, bytes)) [[unlikely]] { + this->grow(bytes); + } + } + + /// Append a sequence of characters whose capacity was already reserved + /// through `reserve_additional` + SOURCEMETA_FORCEINLINE auto + append_unchecked(const std::string_view data) noexcept -> void { + assert(std::cmp_less_equal(data.size(), this->end_ - this->cursor_)); + if (!data.empty()) { + std::memcpy(this->cursor_, data.data(), data.size()); + this->cursor_ += data.size(); } + } + + /// Get the number of bytes accumulated so far + [[nodiscard]] SOURCEMETA_FORCEINLINE auto size() const noexcept + -> std::size_t { + return static_cast(this->cursor_ - this->begin_); + } + /// Get the last character of the buffer, which must not be empty + [[nodiscard]] SOURCEMETA_FORCEINLINE auto back() const noexcept -> char { + assert(this->cursor_ != this->begin_); + return *(this->cursor_ - 1); + } + + /// Remove a number of bytes from the end of the buffer, which must hold at + /// least that many bytes + SOURCEMETA_FORCEINLINE auto remove_suffix(const std::size_t count) noexcept + -> void { + assert(count <= this->size()); + this->cursor_ -= count; + } + + /// Get a view of the accumulated contents, which stays valid until the + /// buffer is modified + [[nodiscard]] SOURCEMETA_FORCEINLINE auto view() const noexcept + -> std::string_view { + return {this->begin_, this->size()}; + } + + /// Discard the accumulated contents, keeping the capacity for reuse + SOURCEMETA_FORCEINLINE auto clear() noexcept -> void { + this->cursor_ = this->begin_; + } + + /// Get the accumulated contents of the buffer + [[nodiscard]] SOURCEMETA_FORCEINLINE auto str() -> const std::string & { + this->buffer_.resize(this->size()); + this->begin_ = this->buffer_.data(); + this->cursor_ = this->begin_ + this->buffer_.size(); + this->end_ = this->cursor_; return this->buffer_; } + /// Move the accumulated contents out of the buffer, leaving it empty and + /// ready to accumulate new contents + [[nodiscard]] SOURCEMETA_FORCEINLINE auto take() -> std::string { + this->buffer_.resize(this->size()); + std::string result{std::move(this->buffer_)}; + this->buffer_.clear(); + this->begin_ = nullptr; + this->cursor_ = nullptr; + this->end_ = nullptr; + return result; + } + /// Write the accumulated contents to an output stream auto write(std::ostream &stream) -> void; private: + [[nodiscard]] SOURCEMETA_FORCEINLINE auto capacity() const noexcept + -> std::size_t { + return static_cast(this->end_ - this->begin_); + } + auto grow(std::size_t needed) -> void; + auto reallocate(std::size_t capacity) -> void; // Exporting symbols that depends on the standard C++ library is considered // safe. @@ -90,6 +157,7 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLBuffer { #if defined(_MSC_VER) #pragma warning(pop) #endif + char *begin_{nullptr}; char *cursor_{nullptr}; char *end_{nullptr}; }; diff --git a/vendor/core/src/core/html/include/sourcemeta/core/html_escape.h b/vendor/core/src/core/html/include/sourcemeta/core/html_escape.h index d9aad0bcf..3a4171695 100644 --- a/vendor/core/src/core/html/include/sourcemeta/core/html_escape.h +++ b/vendor/core/src/core/html/include/sourcemeta/core/html_escape.h @@ -6,7 +6,13 @@ #endif #include +#include +#include // std::array +#include // std::same_as +#include // std::size_t +#include // std::uint8_t, std::uint64_t +#include // std::memcpy #include // std::string #include // std::string_view @@ -34,17 +40,129 @@ SOURCEMETA_CORE_HTML_EXPORT auto html_escape(std::string &text) -> void; /// @ingroup html -/// Append the HTML-escaped form of `input` directly to `output`, -/// without allocating a temporary string. The input must not reference the -/// output, since appending to the output may relocate its storage. -SOURCEMETA_CORE_HTML_EXPORT -auto html_escape_append(std::string &output, std::string_view input) -> void; +/// Append the HTML-escaped form of `input` to a string or to a buffer, without +/// allocating a temporary string. The input must not reference the output, +/// since appending to the output may relocate its storage. For example: +/// +/// ```cpp +/// #include +/// #include +/// +/// std::string output{"

"}; +/// sourcemeta::core::html_escape_append(output, "1 < 2"); +/// assert(output == "

1 < 2"); +/// ``` +template + requires std::same_as || std::same_as +inline auto html_escape_append(Output &output, const std::string_view input) + -> void { + // The bytes that escaping may replace, which are the quotation mark, the + // ampersand, the apostrophe, the angle brackets, and the first byte of the + // UTF-8 encoding of the no-break space + static constexpr std::array SPECIAL_BYTES{{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 + 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, // 0x30 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x50 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x70 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xB0 + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xD0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xF0 + }}; + constexpr std::uint64_t LOW_BITS{0x0101010101010101ULL}; + constexpr std::uint64_t HIGH_BITS{0x8080808080808080ULL}; -/// @ingroup html -/// Append the HTML-escaped form of `input` directly to a buffer. The input must -/// not reference the buffer, since appending to it may relocate its storage. -SOURCEMETA_CORE_HTML_EXPORT -auto html_escape_append(HTMLBuffer &output, std::string_view input) -> void; + const auto size{input.size()}; + // Whatever stays as it is goes out in runs, so that text with nothing to + // escape takes a single append + std::size_t run_start{0}; + std::size_t position{0}; + while (position < size) { + auto end{size}; + if (size - position >= 8) { + std::uint64_t word{0}; + std::memcpy(&word, input.data() + position, 8); + // A byte of a word equals another when subtracting from their difference + // borrows, which also flags the byte right after a genuine match, and + // that is harmless when only asking whether the word has a match at all. + // Setting the lowest bit of every byte makes the ampersand match the + // apostrophe, and setting the second lowest bit makes the less-than sign + // match the greater-than sign, so four comparisons cover the six bytes + const auto quotations{word ^ (LOW_BITS * '"')}; + const auto apostrophes{(word | LOW_BITS) ^ (LOW_BITS * '\'')}; + const auto angles{(word | (LOW_BITS * 2U)) ^ (LOW_BITS * '>')}; + const auto leads{word ^ (LOW_BITS * 0xC2)}; + const auto matches{((quotations - LOW_BITS) & ~quotations) | + ((apostrophes - LOW_BITS) & ~apostrophes) | + ((angles - LOW_BITS) & ~angles) | + ((leads - LOW_BITS) & ~leads)}; + if ((matches & HIGH_BITS) == 0) { + position += 8; + continue; + } + + end = position + 8; + } + + while (position < end) { + if (SPECIAL_BYTES[static_cast(input[position])] == 0) { + position += 1; + continue; + } + + std::string_view replacement; + std::size_t consumed{1}; + switch (input[position]) { + case '&': + replacement = "&"; + break; + case '<': + replacement = "<"; + break; + case '>': + replacement = ">"; + break; + case '"': + replacement = """; + break; + case '\'': + replacement = "'"; + break; + default: + // The no-break space is replaced by its named entity (HTML Living + // Standard "escaping a string" step 2) + if (static_cast(input[position]) == 0xC2 && + position + 1 < size && + static_cast(input[position + 1]) == 0xA0) { + replacement = " "; + consumed = 2; + } + + break; + } + + if (replacement.empty()) { + position += 1; + continue; + } + + output.append(input.substr(run_start, position - run_start)); + output.append(replacement); + position += consumed; + run_start = position; + } + } + + output.append(input.substr(run_start)); +} } // namespace sourcemeta::core diff --git a/vendor/core/src/core/html/include/sourcemeta/core/html_writer.h b/vendor/core/src/core/html/include/sourcemeta/core/html_writer.h index 24d643ab8..46d059362 100644 --- a/vendor/core/src/core/html/include/sourcemeta/core/html_writer.h +++ b/vendor/core/src/core/html/include/sourcemeta/core/html_writer.h @@ -9,7 +9,11 @@ #include #include +#include // std::array #include // assert +#include // std::size_t +#include // std::uint8_t +#include // std::string #include // std::string_view #include // std::vector @@ -40,14 +44,18 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLWriter { /// Close the most recently opened element. Closing when no element is open /// has no effect. SOURCEMETA_FORCEINLINE auto close() -> HTMLWriter & { - this->flush_open_tag(); + this->tag_open_ = false; assert(!this->tag_stack_.empty()); if (this->tag_stack_.empty()) [[unlikely]] { return *this; } - this->buffer_.append("buffer_.append(this->tag_stack_.back()); - this->buffer_.append(">"); + const auto &closing{this->tag_stack_.back()}; + // Copying every byte of the fixed storage is cheaper than copying a + // variable number of them, and the bytes past the tag are then dropped + this->buffer_.reserve_additional(closing.bytes.size()); + this->buffer_.append_unchecked( + std::string_view{closing.bytes.data(), closing.bytes.size()}); + this->buffer_.remove_suffix(closing.bytes.size() - closing.size); this->tag_stack_.pop_back(); return *this; } @@ -58,14 +66,106 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLWriter { std::string_view value) -> HTMLWriter & { assert(this->tag_open_); - this->buffer_.append(" "); - this->buffer_.append(name); - this->buffer_.append("=\""); + this->reopen_tag(); + // The space before the name, the equals sign and the quotation mark after + // it, along with the end of the tag, which takes four bytes for a void + // element + this->buffer_.reserve_additional(name.size() + 7); + this->buffer_.append_unchecked(" "); + this->buffer_.append_unchecked(name); + this->buffer_.append_unchecked("=\""); html_escape_append(this->buffer_, value); - this->buffer_.append("\""); + this->buffer_.reserve_additional(4); + if (this->tag_open_is_void_) { + this->buffer_.append_unchecked("\" />"); + } else { + this->buffer_.append_unchecked("\">"); + } + return *this; + } + + /// Add an attribute without a value, such as a boolean attribute, to the + /// currently open tag. Must be called immediately after an element method + /// and before any content. For example: + /// + /// ```cpp + /// #include + /// #include + /// + /// sourcemeta::core::HTMLWriter document; + /// document.input().attribute("type", "checkbox").attribute("checked"); + /// assert(document.str() == ""); + /// ``` + SOURCEMETA_FORCEINLINE auto attribute(std::string_view name) -> HTMLWriter & { + assert(this->tag_open_); + this->reopen_tag(); + this->buffer_.reserve_additional(name.size() + 1); + this->buffer_.append_unchecked(" "); + this->buffer_.append_unchecked(name); + this->end_open_tag(); return *this; } + /// Write a line feed unless nothing was written yet or the output already + /// ends with one, so that the markup that follows starts on a line of its + /// own. For example: + /// + /// ```cpp + /// #include + /// #include + /// + /// sourcemeta::core::HTMLWriter document; + /// document.p("Hello"); + /// document.ensure_line_feed(); + /// document.ensure_line_feed(); + /// document.p("World"); + /// assert(document.str() == "

Hello

\n

World

"); + /// ``` + SOURCEMETA_FORCEINLINE auto ensure_line_feed() -> HTMLWriter & { + this->tag_open_ = false; + if (this->buffer_.size() > 0 && this->buffer_.back() != '\n') { + this->buffer_.append('\n'); + } + + return *this; + } + + /// Move the rendered HTML string out of the writer, leaving the writer empty + /// and ready to render another document. For example: + /// + /// ```cpp + /// #include + /// #include + /// + /// sourcemeta::core::HTMLWriter document; + /// document.p("Hello"); + /// const auto result{document.take()}; + /// assert(result == "

Hello

"); + /// assert(document.str().empty()); + /// ``` + [[nodiscard]] SOURCEMETA_FORCEINLINE auto take() -> std::string { + this->tag_open_ = false; + this->tag_stack_.clear(); + return this->buffer_.take(); + } + + /// Discard the output and every open element. For example: + /// + /// ```cpp + /// #include + /// #include + /// + /// sourcemeta::core::HTMLWriter document; + /// document.div().p("Hello"); + /// document.clear(); + /// assert(document.str().empty()); + /// ``` + SOURCEMETA_FORCEINLINE auto clear() -> void { + this->tag_open_ = false; + this->tag_stack_.clear(); + this->buffer_.clear(); + } + /// Write HTML-escaped text content. The single-argument element shorthand /// routes through this and therefore also escapes. The HTML serialization /// emits the content of a raw-text element literally, so escaping its content @@ -73,7 +173,7 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLWriter { /// the content of a raw-text element must be written unescaped rather than as /// escaped text, and it must not contain that element's closing-tag sequence. SOURCEMETA_FORCEINLINE auto text(std::string_view content) -> HTMLWriter & { - this->flush_open_tag(); + this->tag_open_ = false; html_escape_append(this->buffer_, content); return *this; } @@ -81,14 +181,13 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLWriter { /// Write content without HTML-escaping. This is how the content of a raw-text /// element is emitted, since escaped text would corrupt it. SOURCEMETA_FORCEINLINE auto raw(std::string_view content) -> HTMLWriter & { - this->flush_open_tag(); + this->tag_open_ = false; this->buffer_.append(content); return *this; } /// Get the rendered HTML string [[nodiscard]] SOURCEMETA_FORCEINLINE auto str() -> const std::string & { - this->flush_open_tag(); return this->buffer_.str(); } @@ -112,12 +211,12 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLWriter { // NOLINTBEGIN(bugprone-macro-parentheses) #define HTML_WRITER_CONTAINER(name) \ SOURCEMETA_FORCEINLINE auto name() -> HTMLWriter & { \ - this->open_tag(#name); \ + this->open_tag("<" #name ">", ClosingTag{""}); \ return *this; \ } \ SOURCEMETA_FORCEINLINE auto name(std::string_view text_content) \ -> HTMLWriter & { \ - this->open_tag(#name); \ + this->open_tag("<" #name ">", ClosingTag{""}); \ this->text(text_content); \ this->close(); \ return *this; \ @@ -128,12 +227,12 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLWriter { // NOLINTBEGIN(bugprone-macro-parentheses) #define HTML_WRITER_CONTAINER_NAMED(name, tag) \ SOURCEMETA_FORCEINLINE auto name() -> HTMLWriter & { \ - this->open_tag(#tag); \ + this->open_tag("<" #tag ">", ClosingTag{""}); \ return *this; \ } \ SOURCEMETA_FORCEINLINE auto name(std::string_view text_content) \ -> HTMLWriter & { \ - this->open_tag(#tag); \ + this->open_tag("<" #tag ">", ClosingTag{""}); \ this->text(text_content); \ this->close(); \ return *this; \ @@ -145,7 +244,7 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLWriter { // NOLINTBEGIN(bugprone-macro-parentheses) #define HTML_WRITER_VOID(name) \ SOURCEMETA_FORCEINLINE auto name() -> HTMLWriter & { \ - this->void_tag(#name); \ + this->void_tag("<" #name " />"); \ return *this; \ } // NOLINTEND(bugprone-macro-parentheses) @@ -447,27 +546,50 @@ class SOURCEMETA_CORE_HTML_EXPORT HTMLWriter { #endif private: - SOURCEMETA_FORCEINLINE auto open_tag(std::string_view tag) -> void { - this->flush_open_tag(); - this->buffer_.append("<"); - this->buffer_.append(tag); - this->tag_stack_.push_back(tag); + // A closing tag kept in a fixed number of bytes, as copying a constant + // number of bytes is cheaper than copying a variable one + struct ClosingTag { + constexpr explicit ClosingTag(const std::string_view tag) noexcept + : size{static_cast(tag.size())} { + for (std::size_t index = 0; index < tag.size(); index += 1) { + this->bytes[index] = tag[index]; + } + } + + std::array bytes{}; + std::uint8_t size; + }; + + SOURCEMETA_FORCEINLINE auto open_tag(std::string_view opening, + const ClosingTag &closing) -> void { + this->buffer_.append(opening); + this->tag_stack_.push_back(closing); this->tag_open_ = true; this->tag_open_is_void_ = false; } - SOURCEMETA_FORCEINLINE auto void_tag(std::string_view tag) -> void { - this->flush_open_tag(); - this->buffer_.append("<"); - this->buffer_.append(tag); + SOURCEMETA_FORCEINLINE auto void_tag(std::string_view opening) -> void { + this->buffer_.append(opening); this->tag_open_ = true; this->tag_open_is_void_ = true; } - auto flush_open_tag() -> void; + // Remove the characters that end the tag opened last, so that attributes + // can go before them + SOURCEMETA_FORCEINLINE auto reopen_tag() -> void { + this->buffer_.remove_suffix(this->tag_open_is_void_ ? 3 : 1); + } + + SOURCEMETA_FORCEINLINE auto end_open_tag() -> void { + if (this->tag_open_is_void_) { + this->buffer_.append(" />"); + } else { + this->buffer_.append('>'); + } + } HTMLBuffer buffer_; - std::vector tag_stack_; + std::vector tag_stack_; bool tag_open_{false}; bool tag_open_is_void_{false}; #if defined(_MSC_VER) diff --git a/vendor/core/src/core/html/writer.cc b/vendor/core/src/core/html/writer.cc index 4bd1d3731..d2a53f023 100644 --- a/vendor/core/src/core/html/writer.cc +++ b/vendor/core/src/core/html/writer.cc @@ -1,47 +1,40 @@ #include -#include // std::ostream +#include // std::max +#include // std::size_t +#include // std::ostream namespace sourcemeta::core { auto HTMLBuffer::grow(const std::size_t needed) -> void { - const auto current_size{ - (this->cursor_ != nullptr) - ? static_cast(this->cursor_ - this->buffer_.data()) - : 0}; - auto new_capacity{this->buffer_.empty() ? 1024UZ : this->buffer_.size() * 2}; - while (new_capacity < current_size + needed) { + auto new_capacity{std::max(1024UZ, this->capacity() * 2)}; + while (new_capacity < this->size() + needed) { new_capacity *= 2; } - this->buffer_.resize(new_capacity); - this->cursor_ = this->buffer_.data() + current_size; - this->end_ = this->buffer_.data() + new_capacity; + this->reallocate(new_capacity); } -auto HTMLBuffer::write(std::ostream &stream) -> void { - if (this->cursor_ != nullptr) { - const auto size{ - static_cast(this->cursor_ - this->buffer_.data())}; - stream.write(this->buffer_.data(), static_cast(size)); - } +auto HTMLBuffer::reallocate(const std::size_t capacity) -> void { + const auto used{this->size()}; + // Appends write straight into the spare capacity, so that space has to count + // as part of the contents of the underlying string, and the C++ standard has + // no way of handing out contents that are left uninitialized. Growth doubles, + // so the fill amortizes to a single pass over the buffer + this->buffer_.resize(capacity); + this->begin_ = this->buffer_.data(); + this->cursor_ = this->begin_ + used; + this->end_ = this->begin_ + capacity; } -auto HTMLWriter::flush_open_tag() -> void { - if (this->tag_open_) { - if (this->tag_open_is_void_) { - this->buffer_.append(" />"); - } else { - this->buffer_.append(">"); - } - - this->tag_open_ = false; - this->tag_open_is_void_ = false; +auto HTMLBuffer::write(std::ostream &stream) -> void { + const auto used{this->size()}; + if (used > 0) { + stream.write(this->begin_, static_cast(used)); } } auto HTMLWriter::write(std::ostream &stream) -> void { - this->flush_open_tag(); this->buffer_.write(stream); } diff --git a/vendor/core/src/core/jsonschema/CMakeLists.txt b/vendor/core/src/core/jsonschema/CMakeLists.txt index 826c2e91c..7929157b1 100644 --- a/vendor/core/src/core/jsonschema/CMakeLists.txt +++ b/vendor/core/src/core/jsonschema/CMakeLists.txt @@ -4,7 +4,7 @@ include(./known_resolver.cmake) sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME jsonschema PRIVATE_HEADERS error.h types.h vocabularies.h frame.h - SOURCES jsonschema.cc vocabularies.cc known_walker.cc frame.cc + SOURCES jsonschema.cc vocabularies.cc known_walker.cc frame.cc format.cc helpers.h iterator.h "${CMAKE_CURRENT_BINARY_DIR}/known_resolver.cc") diff --git a/vendor/core/src/core/jsonschema/format.cc b/vendor/core/src/core/jsonschema/format.cc new file mode 100644 index 000000000..ad98a5720 --- /dev/null +++ b/vendor/core/src/core/jsonschema/format.cc @@ -0,0 +1,125 @@ +#include + +#include // std::ranges::sort +#include // std::array, std::to_array +#include // assert +#include // std::size_t +#include // std::uint16_t +#include // std::ranges::greater, std::reference_wrapper +#include // std::numeric_limits +#include // std::string_view +#include // std::unordered_map +#include // std::vector + +namespace sourcemeta::core { + +namespace { + +// The order in which keywords are meant to appear within a schema, where the +// position of an entry is the rank of the keyword it names +constexpr auto KEYWORDS{std::to_array( + {// Most core keywords tend to come first + "$schema", "$id", "id", "$vocabulary", "$anchor", "$dynamicAnchor", + "$recursiveAnchor", + + // Then important metadata about the schema + "title", "description", "$comment", "examples", "deprecated", "readOnly", + "writeOnly", "default", + + // This is a placeholder for "x-"-prefixed unknown keywords, as they are + // almost always metadata + "x-", + + // Then references + "$ref", "$dynamicRef", "$recursiveRef", + + // Then keywords that apply to any type + "type", "disallow", "extends", "const", "enum", "optional", "requires", + "allOf", "anyOf", "oneOf", "not", "if", "then", "else", + + // Then keywords about numbers + "exclusiveMaximum", "maximum", "maximumCanEqual", "exclusiveMinimum", + "minimum", "minimumCanEqual", "multipleOf", "divisibleBy", "maxDecimal", + + // Then keywords about strings + "pattern", "format", "maxLength", "minLength", "contentEncoding", + "contentMediaType", "contentSchema", + + // Then keywords about arrays + "maxItems", "minItems", "uniqueItems", "maxContains", "minContains", + "contains", "prefixItems", "items", "additionalItems", "unevaluatedItems", + + // Then keywords about objects + "required", "maxProperties", "minProperties", "propertyNames", + "properties", "patternProperties", "additionalProperties", + "unevaluatedProperties", "dependentRequired", "dependencies", + "dependentSchemas", + + // Reusable utilities go last + "$defs", "definitions"})}; + +constexpr std::string_view EXTENSION_PREFIX{"x-"}; + +auto make_index() -> std::unordered_map { + std::unordered_map index; + index.reserve(KEYWORDS.size()); + for (std::size_t position = 0; position < KEYWORDS.size(); position += 1) { + index.emplace(KEYWORDS[position], static_cast(position)); + } + + return index; +} + +// NOLINTNEXTLINE(cert-err58-cpp,bugprone-throwing-static-initialization) +const auto INDEX{make_index()}; + +auto keyword_rank(const JSON::String &keyword) -> std::uint16_t { + constexpr auto UNRECOGNISED{std::numeric_limits::max()}; + const auto match{INDEX.find(keyword.starts_with(EXTENSION_PREFIX) + ? EXTENSION_PREFIX + : std::string_view{keyword})}; + if (match == INDEX.cend()) { + return UNRECOGNISED; + } + + return match->second; +} + +auto keyword_compare(const JSON::String &left, const JSON::String &right) + -> bool { + const auto left_rank{keyword_rank(left)}; + const auto right_rank{keyword_rank(right)}; + if (left_rank == right_rank) { + return left < right; + } + + return left_rank < right_rank; +} + +} // namespace + +auto schema_format(JSON &schema, const SchemaFrame &frame) -> void { + assert(schema.is_object() || schema.is_boolean()); + + std::vector> subschemas; + frame.for_each_subschema( + [&subschemas](const SchemaFrame::Location &location) -> void { + subschemas.emplace_back(location.pointer); + }); + + // Reordering an object moves its properties around, so a location that names + // one of them stops standing for what it used to. Going from the deepest + // subschema upwards means that by the time an object moves, every location + // that goes through it was already taken care of + std::ranges::sort(subschemas, std::ranges::greater{}, + [](const auto &pointer) { return pointer.get().size(); }); + + for (const auto &pointer : subschemas) { + auto &subschema{get(schema, pointer.get())}; + if (subschema.is_object()) { + subschema.reorder(keyword_compare); + } + } +} + +} // namespace sourcemeta::core diff --git a/vendor/core/src/core/jsonschema/frame.cc b/vendor/core/src/core/jsonschema/frame.cc index d8eaba6bd..6f2bf8e24 100644 --- a/vendor/core/src/core/jsonschema/frame.cc +++ b/vendor/core/src/core/jsonschema/frame.cc @@ -351,6 +351,22 @@ auto supports_id_anchors(const sourcemeta::core::SchemaBaseDialect base_dialect) } } +// Draft 6 introduced a plain name syntax for the fragment that an identifier +// may consist of. Draft 4 and 3 impose no pattern on it +auto requires_plain_name_anchors( + const sourcemeta::core::SchemaBaseDialect base_dialect) -> bool { + using sourcemeta::core::SchemaBaseDialect; + switch (base_dialect) { + case SchemaBaseDialect::JSON_SCHEMA_DRAFT_7: + case SchemaBaseDialect::JSON_SCHEMA_DRAFT_7_HYPER: + case SchemaBaseDialect::JSON_SCHEMA_DRAFT_6: + case SchemaBaseDialect::JSON_SCHEMA_DRAFT_6_HYPER: + return true; + default: + return false; + } +} + // Generic URI normalisation only decodes unreserved characters (see RFC 3986, // section 6.2.2.2), so a reference destination may still spell its JSON // Pointer fragment with percent-encoded octets. Re-serialise such fragments @@ -917,9 +933,46 @@ SchemaFrame::SchemaFrame(const Mode mode, const sourcemeta::core::JSON &root, // This mode analyses a single schema, which the caller may have pointed // at through a container, so its identifier is the one we report std::optional root_id{std::nullopt}; + bool root_declares_anchor{false}; if (path.empty() || this->mode_ == SchemaFrame::Mode::Root) { - const auto maybe_id{sourcemeta::core::identify( - schema, root_base_dialect.value(), default_id)}; + const auto declared_id{sourcemeta::core::identify( + schema, root_base_dialect.value(), std::string_view{})}; + + // Before 2019-09 an identifier that consists of nothing but a fragment + // names the schema it sits on rather than declaring a resource of its + // own, so the schema goes by whatever name the caller gave it, if any, + // and we take care of the fragment as an anchor further down, just like + // we do for every other subschema + // + // To specify such a subschema identifier, the "$id" keyword is set to + // a URI reference with a plain name fragment (not a JSON Pointer + // fragment). + // + // See + // https://json-schema.org/draft-07/draft-handrews-json-schema-01#rfc.section.8.2.3 + root_declares_anchor = !declared_id.empty() && + supports_id_anchors(root_base_dialect.value()) && + declared_id.starts_with('#'); + if (root_declares_anchor) { + // The mode that reports on a single schema never walks the document, + // so the anchor that this declares is held to the rules of its dialect + // here rather than wherever every other anchor of the document is + if (requires_plain_name_anchors(root_base_dialect.value())) { + if (!is_valid_anchor(declared_id.substr(1))) { + throw SchemaKeywordError( + sourcemeta::core::id_keyword(root_base_dialect.value()).name, + declared_id, "Invalid anchor value"); + } + } else if (!sourcemeta::core::URI::is_uri_reference(declared_id)) { + throw SchemaKeywordError( + sourcemeta::core::id_keyword(root_base_dialect.value()).name, + declared_id, "The identifier is not a valid URI"); + } + } + + const auto maybe_id{root_declares_anchor || declared_id.empty() + ? default_id + : declared_id}; if (!maybe_id.empty()) { try { root_id = canonicalize_identifier(maybe_id, default_base); @@ -1065,9 +1118,16 @@ SchemaFrame::SchemaFrame(const Mode mode, const sourcemeta::core::JSON &root, const std::string default_id_for_entry{ entry.pointer.empty() && root_id.has_value() ? root_id.value() : std::string{}}; - const auto maybe_id{sourcemeta::core::identify(entry.subschema.get(), - entry.base_dialect.value(), - default_id_for_entry)}; + // An identifier that only names the top of the document in place was + // taken apart above, which leaves the name the caller gave it, if any, + // as the one that identifies the document + const auto maybe_id{ + entry.pointer.empty() && root_declares_anchor && + !default_id_for_entry.empty() + ? std::string_view{default_id_for_entry} + : sourcemeta::core::identify(entry.subschema.get(), + entry.base_dialect.value(), + default_id_for_entry)}; std::optional identifier{ !maybe_id.empty() ? std::make_optional(maybe_id) diff --git a/vendor/core/src/core/jsonschema/include/sourcemeta/core/jsonschema.h b/vendor/core/src/core/jsonschema/include/sourcemeta/core/jsonschema.h index 78d9498c6..7937cb998 100644 --- a/vendor/core/src/core/jsonschema/include/sourcemeta/core/jsonschema.h +++ b/vendor/core/src/core/jsonschema/include/sourcemeta/core/jsonschema.h @@ -101,6 +101,42 @@ auto schema_reidentify(sourcemeta::core::JSON &schema, std::string_view new_identifier, const SchemaBaseDialect base_dialect) -> void; +/// @ingroup jsonschema +/// +/// This function reorders the properties of every subschema that the given +/// frame reports, following an opinionated JSON Schema aware order, modifying +/// the schema in place. Note that doing so invalidates the given frame, as the +/// locations it holds point into the schema. For example: +/// +/// ```cpp +/// #include +/// #include +/// +/// #include +/// #include +/// +/// sourcemeta::core::JSON document = +/// sourcemeta::core::parse_json(R"JSON({ +/// "type": "string", +/// "minLength": 3, +/// "$schema": "https://json-schema.org/draft/2020-12/schema" +/// })JSON"); +/// +/// const sourcemeta::core::SchemaFrame frame{ +/// sourcemeta::core::SchemaFrame::Mode::Locations, document, +/// sourcemeta::core::schema_walker, +/// sourcemeta::core::schema_resolver}; +/// +/// sourcemeta::core::schema_format(document, frame); +/// +/// std::ostringstream stream; +/// sourcemeta::core::prettify(document, stream); +/// std::cout << stream.str() << std::endl; +/// ``` +SOURCEMETA_CORE_JSONSCHEMA_EXPORT +auto schema_format(sourcemeta::core::JSON &schema, const SchemaFrame &frame) + -> void; + } // namespace sourcemeta::core #endif diff --git a/vendor/core/src/core/jsonschema/known_walker.cc b/vendor/core/src/core/jsonschema/known_walker.cc index c35ec4abf..75f5f1ed7 100644 --- a/vendor/core/src/core/jsonschema/known_walker.cc +++ b/vendor/core/src/core/jsonschema/known_walker.cc @@ -58,7 +58,7 @@ struct Variant { SchemaWalkerResult result; }; -constexpr std::array VARIANTS{{ +constexpr std::array VARIANTS{{ {.vocabulary = Known::JSON_SCHEMA_2020_12_CORE, .secondary = std::nullopt, .result = {SchemaKeywordType::Other, @@ -101,20 +101,6 @@ constexpr std::array VARIANTS{{ KEYWORDS_REF, {}, INSTANCES_ANY}}, - {.vocabulary = Known::JSON_SCHEMA_DRAFT_6, - .secondary = std::nullopt, - .result = {SchemaKeywordType::Comment, - Known::JSON_SCHEMA_DRAFT_6, - KEYWORDS_REF, - {}, - INSTANCES_ANY}}, - {.vocabulary = Known::JSON_SCHEMA_DRAFT_6_HYPER, - .secondary = std::nullopt, - .result = {SchemaKeywordType::Comment, - Known::JSON_SCHEMA_DRAFT_6_HYPER, - KEYWORDS_REF, - {}, - INSTANCES_ANY}}, {.vocabulary = Known::JSON_SCHEMA_2020_12_CORE, .secondary = std::nullopt, .result = {SchemaKeywordType::LocationMembers, @@ -920,20 +906,6 @@ constexpr std::array VARIANTS{{ KEYWORDS_REF, {}, INSTANCES_STRING}}, - {.vocabulary = Known::JSON_SCHEMA_DRAFT_6, - .secondary = std::nullopt, - .result = {SchemaKeywordType::Comment, - Known::JSON_SCHEMA_DRAFT_6, - KEYWORDS_REF, - {}, - INSTANCES_STRING}}, - {.vocabulary = Known::JSON_SCHEMA_DRAFT_6_HYPER, - .secondary = std::nullopt, - .result = {SchemaKeywordType::Comment, - Known::JSON_SCHEMA_DRAFT_6_HYPER, - KEYWORDS_REF, - {}, - INSTANCES_STRING}}, {.vocabulary = Known::JSON_SCHEMA_DRAFT_3_HYPER, .secondary = std::nullopt, .result = {SchemaKeywordType::Other, @@ -1011,20 +983,6 @@ constexpr std::array VARIANTS{{ KEYWORDS_REF, {}, INSTANCES_STRING}}, - {.vocabulary = Known::JSON_SCHEMA_DRAFT_6, - .secondary = std::nullopt, - .result = {SchemaKeywordType::Comment, - Known::JSON_SCHEMA_DRAFT_6, - KEYWORDS_REF, - {}, - INSTANCES_STRING}}, - {.vocabulary = Known::JSON_SCHEMA_DRAFT_6_HYPER, - .secondary = std::nullopt, - .result = {SchemaKeywordType::Comment, - Known::JSON_SCHEMA_DRAFT_6_HYPER, - KEYWORDS_REF, - {}, - INSTANCES_STRING}}, {.vocabulary = Known::JSON_SCHEMA_2020_12_CONTENT, .secondary = std::nullopt, .result = {SchemaKeywordType::ApplicatorValueInPlaceOther, @@ -4129,13 +4087,6 @@ constexpr std::array VARIANTS{{ KEYWORDS_REF, {}, INSTANCES_ANY}}, - {.vocabulary = Known::JSON_SCHEMA_DRAFT_6, - .secondary = std::nullopt, - .result = {SchemaKeywordType::Comment, - Known::JSON_SCHEMA_DRAFT_6, - KEYWORDS_REF, - {}, - INSTANCES_ANY}}, {.vocabulary = Known::JSON_SCHEMA_DRAFT_6_HYPER, .secondary = std::nullopt, .result = {SchemaKeywordType::Comment, @@ -4934,20 +4885,6 @@ constexpr std::array VARIANTS{{ KEYWORDS_REF, {}, INSTANCES_ANY}}, - {.vocabulary = Known::JSON_SCHEMA_DRAFT_6, - .secondary = std::nullopt, - .result = {SchemaKeywordType::Comment, - Known::JSON_SCHEMA_DRAFT_6, - KEYWORDS_REF, - {}, - INSTANCES_ANY}}, - {.vocabulary = Known::JSON_SCHEMA_DRAFT_6_HYPER, - .secondary = std::nullopt, - .result = {SchemaKeywordType::Comment, - Known::JSON_SCHEMA_DRAFT_6_HYPER, - KEYWORDS_REF, - {}, - INSTANCES_ANY}}, {.vocabulary = Known::OPENAPI_3_2_BASE, .secondary = std::nullopt, .result = {SchemaKeywordType::Other, @@ -4975,143 +4912,140 @@ struct Keyword { constexpr std::array KEYWORDS{{ {.name = "$anchor", .offset = 0, .count = 2, .legacy_ref = false}, - {.name = "$comment", .offset = 2, .count = 6, .legacy_ref = false}, - {.name = "$defs", .offset = 8, .count = 2, .legacy_ref = false}, - {.name = "$dynamicAnchor", .offset = 10, .count = 1, .legacy_ref = false}, - {.name = "$dynamicRef", .offset = 11, .count = 1, .legacy_ref = false}, - {.name = "$id", .offset = 12, .count = 6, .legacy_ref = false}, - {.name = "$recursiveAnchor", .offset = 18, .count = 1, .legacy_ref = false}, - {.name = "$recursiveRef", .offset = 19, .count = 1, .legacy_ref = false}, - {.name = "$ref", .offset = 20, .count = 16, .legacy_ref = false}, - {.name = "$schema", .offset = 36, .count = 16, .legacy_ref = false}, - {.name = "$vocabulary", .offset = 52, .count = 2, .legacy_ref = false}, - {.name = "additionalItems", .offset = 54, .count = 9, .legacy_ref = false}, + {.name = "$comment", .offset = 2, .count = 4, .legacy_ref = true}, + {.name = "$defs", .offset = 6, .count = 2, .legacy_ref = false}, + {.name = "$dynamicAnchor", .offset = 8, .count = 1, .legacy_ref = false}, + {.name = "$dynamicRef", .offset = 9, .count = 1, .legacy_ref = false}, + {.name = "$id", .offset = 10, .count = 6, .legacy_ref = false}, + {.name = "$recursiveAnchor", .offset = 16, .count = 1, .legacy_ref = false}, + {.name = "$recursiveRef", .offset = 17, .count = 1, .legacy_ref = false}, + {.name = "$ref", .offset = 18, .count = 16, .legacy_ref = false}, + {.name = "$schema", .offset = 34, .count = 16, .legacy_ref = false}, + {.name = "$vocabulary", .offset = 50, .count = 2, .legacy_ref = false}, + {.name = "additionalItems", .offset = 52, .count = 9, .legacy_ref = false}, {.name = "additionalProperties", - .offset = 63, + .offset = 61, .count = 16, .legacy_ref = false}, - {.name = "allOf", .offset = 79, .count = 8, .legacy_ref = false}, - {.name = "alternate", .offset = 87, .count = 3, .legacy_ref = false}, - {.name = "anchor", .offset = 90, .count = 2, .legacy_ref = true}, - {.name = "anchorPointer", .offset = 92, .count = 2, .legacy_ref = true}, - {.name = "anyOf", .offset = 94, .count = 8, .legacy_ref = false}, - {.name = "base", .offset = 102, .count = 3, .legacy_ref = true}, - {.name = "const", .offset = 105, .count = 6, .legacy_ref = false}, - {.name = "contains", .offset = 111, .count = 8, .legacy_ref = false}, - {.name = "contentEncoding", .offset = 119, .count = 13, .legacy_ref = true}, - {.name = "contentMediaType", - .offset = 132, - .count = 6, - .legacy_ref = false}, - {.name = "contentSchema", .offset = 138, .count = 2, .legacy_ref = false}, - {.name = "default", .offset = 140, .count = 16, .legacy_ref = false}, - {.name = "definitions", .offset = 156, .count = 10, .legacy_ref = false}, - {.name = "dependencies", .offset = 166, .count = 8, .legacy_ref = false}, + {.name = "allOf", .offset = 77, .count = 8, .legacy_ref = false}, + {.name = "alternate", .offset = 85, .count = 3, .legacy_ref = false}, + {.name = "anchor", .offset = 88, .count = 2, .legacy_ref = true}, + {.name = "anchorPointer", .offset = 90, .count = 2, .legacy_ref = true}, + {.name = "anyOf", .offset = 92, .count = 8, .legacy_ref = false}, + {.name = "base", .offset = 100, .count = 3, .legacy_ref = true}, + {.name = "const", .offset = 103, .count = 6, .legacy_ref = false}, + {.name = "contains", .offset = 109, .count = 8, .legacy_ref = false}, + {.name = "contentEncoding", .offset = 117, .count = 11, .legacy_ref = true}, + {.name = "contentMediaType", .offset = 128, .count = 4, .legacy_ref = true}, + {.name = "contentSchema", .offset = 132, .count = 2, .legacy_ref = false}, + {.name = "default", .offset = 134, .count = 16, .legacy_ref = false}, + {.name = "definitions", .offset = 150, .count = 10, .legacy_ref = false}, + {.name = "dependencies", .offset = 160, .count = 8, .legacy_ref = false}, {.name = "dependentRequired", - .offset = 174, + .offset = 168, .count = 2, .legacy_ref = false}, {.name = "dependentSchemas", - .offset = 176, + .offset = 170, .count = 2, .legacy_ref = false}, - {.name = "deprecated", .offset = 178, .count = 2, .legacy_ref = false}, - {.name = "description", .offset = 180, .count = 16, .legacy_ref = false}, - {.name = "disallow", .offset = 196, .count = 8, .legacy_ref = false}, - {.name = "discriminator", .offset = 204, .count = 2, .legacy_ref = false}, - {.name = "divisibleBy", .offset = 206, .count = 4, .legacy_ref = false}, - {.name = "else", .offset = 210, .count = 4, .legacy_ref = false}, - {.name = "encType", .offset = 214, .count = 1, .legacy_ref = true}, - {.name = "enctype", .offset = 215, .count = 4, .legacy_ref = true}, - {.name = "enum", .offset = 219, .count = 16, .legacy_ref = false}, - {.name = "example", .offset = 235, .count = 2, .legacy_ref = false}, - {.name = "examples", .offset = 237, .count = 6, .legacy_ref = false}, + {.name = "deprecated", .offset = 172, .count = 2, .legacy_ref = false}, + {.name = "description", .offset = 174, .count = 16, .legacy_ref = false}, + {.name = "disallow", .offset = 190, .count = 8, .legacy_ref = false}, + {.name = "discriminator", .offset = 198, .count = 2, .legacy_ref = false}, + {.name = "divisibleBy", .offset = 200, .count = 4, .legacy_ref = false}, + {.name = "else", .offset = 204, .count = 4, .legacy_ref = false}, + {.name = "encType", .offset = 208, .count = 1, .legacy_ref = true}, + {.name = "enctype", .offset = 209, .count = 4, .legacy_ref = true}, + {.name = "enum", .offset = 213, .count = 16, .legacy_ref = false}, + {.name = "example", .offset = 229, .count = 2, .legacy_ref = false}, + {.name = "examples", .offset = 231, .count = 6, .legacy_ref = false}, {.name = "exclusiveMaximum", - .offset = 243, + .offset = 237, .count = 10, .legacy_ref = false}, {.name = "exclusiveMinimum", - .offset = 253, + .offset = 247, .count = 10, .legacy_ref = false}, - {.name = "extends", .offset = 263, .count = 8, .legacy_ref = false}, - {.name = "externalDocs", .offset = 271, .count = 2, .legacy_ref = false}, - {.name = "format", .offset = 273, .count = 17, .legacy_ref = false}, + {.name = "extends", .offset = 257, .count = 8, .legacy_ref = false}, + {.name = "externalDocs", .offset = 265, .count = 2, .legacy_ref = false}, + {.name = "format", .offset = 267, .count = 17, .legacy_ref = false}, {.name = "fragmentResolution", - .offset = 290, + .offset = 284, .count = 5, .legacy_ref = true}, - {.name = "headerSchema", .offset = 295, .count = 2, .legacy_ref = true}, - {.name = "href", .offset = 297, .count = 8, .legacy_ref = true}, - {.name = "hrefSchema", .offset = 305, .count = 3, .legacy_ref = true}, - {.name = "id", .offset = 308, .count = 10, .legacy_ref = false}, - {.name = "if", .offset = 318, .count = 4, .legacy_ref = false}, - {.name = "items", .offset = 322, .count = 16, .legacy_ref = false}, - {.name = "links", .offset = 338, .count = 8, .legacy_ref = true}, - {.name = "maxContains", .offset = 346, .count = 2, .legacy_ref = false}, - {.name = "maxDecimal", .offset = 348, .count = 4, .legacy_ref = false}, - {.name = "maxItems", .offset = 352, .count = 16, .legacy_ref = false}, - {.name = "maxLength", .offset = 368, .count = 16, .legacy_ref = false}, - {.name = "maxProperties", .offset = 384, .count = 8, .legacy_ref = false}, - {.name = "maximum", .offset = 392, .count = 16, .legacy_ref = false}, - {.name = "maximumCanEqual", .offset = 408, .count = 6, .legacy_ref = false}, - {.name = "media", .offset = 414, .count = 2, .legacy_ref = true}, - {.name = "mediaType", .offset = 416, .count = 6, .legacy_ref = true}, - {.name = "method", .offset = 422, .count = 5, .legacy_ref = true}, - {.name = "minContains", .offset = 427, .count = 2, .legacy_ref = false}, - {.name = "minItems", .offset = 429, .count = 16, .legacy_ref = false}, - {.name = "minLength", .offset = 445, .count = 16, .legacy_ref = false}, - {.name = "minProperties", .offset = 461, .count = 8, .legacy_ref = false}, - {.name = "minimum", .offset = 469, .count = 16, .legacy_ref = false}, - {.name = "minimumCanEqual", .offset = 485, .count = 6, .legacy_ref = false}, - {.name = "multipleOf", .offset = 491, .count = 8, .legacy_ref = false}, - {.name = "not", .offset = 499, .count = 8, .legacy_ref = false}, - {.name = "oneOf", .offset = 507, .count = 8, .legacy_ref = false}, - {.name = "optional", .offset = 515, .count = 6, .legacy_ref = false}, - {.name = "pathStart", .offset = 521, .count = 5, .legacy_ref = true}, - {.name = "pattern", .offset = 526, .count = 16, .legacy_ref = false}, + {.name = "headerSchema", .offset = 289, .count = 2, .legacy_ref = true}, + {.name = "href", .offset = 291, .count = 8, .legacy_ref = true}, + {.name = "hrefSchema", .offset = 299, .count = 3, .legacy_ref = true}, + {.name = "id", .offset = 302, .count = 10, .legacy_ref = false}, + {.name = "if", .offset = 312, .count = 4, .legacy_ref = false}, + {.name = "items", .offset = 316, .count = 16, .legacy_ref = false}, + {.name = "links", .offset = 332, .count = 8, .legacy_ref = true}, + {.name = "maxContains", .offset = 340, .count = 2, .legacy_ref = false}, + {.name = "maxDecimal", .offset = 342, .count = 4, .legacy_ref = false}, + {.name = "maxItems", .offset = 346, .count = 16, .legacy_ref = false}, + {.name = "maxLength", .offset = 362, .count = 16, .legacy_ref = false}, + {.name = "maxProperties", .offset = 378, .count = 8, .legacy_ref = false}, + {.name = "maximum", .offset = 386, .count = 16, .legacy_ref = false}, + {.name = "maximumCanEqual", .offset = 402, .count = 6, .legacy_ref = false}, + {.name = "media", .offset = 408, .count = 2, .legacy_ref = true}, + {.name = "mediaType", .offset = 410, .count = 6, .legacy_ref = true}, + {.name = "method", .offset = 416, .count = 5, .legacy_ref = true}, + {.name = "minContains", .offset = 421, .count = 2, .legacy_ref = false}, + {.name = "minItems", .offset = 423, .count = 16, .legacy_ref = false}, + {.name = "minLength", .offset = 439, .count = 16, .legacy_ref = false}, + {.name = "minProperties", .offset = 455, .count = 8, .legacy_ref = false}, + {.name = "minimum", .offset = 463, .count = 16, .legacy_ref = false}, + {.name = "minimumCanEqual", .offset = 479, .count = 6, .legacy_ref = false}, + {.name = "multipleOf", .offset = 485, .count = 8, .legacy_ref = false}, + {.name = "not", .offset = 493, .count = 8, .legacy_ref = false}, + {.name = "oneOf", .offset = 501, .count = 8, .legacy_ref = false}, + {.name = "optional", .offset = 509, .count = 6, .legacy_ref = false}, + {.name = "pathStart", .offset = 515, .count = 5, .legacy_ref = true}, + {.name = "pattern", .offset = 520, .count = 16, .legacy_ref = false}, {.name = "patternProperties", - .offset = 542, + .offset = 536, .count = 10, .legacy_ref = false}, - {.name = "prefixItems", .offset = 552, .count = 1, .legacy_ref = false}, - {.name = "properties", .offset = 553, .count = 18, .legacy_ref = false}, - {.name = "propertyNames", .offset = 571, .count = 6, .legacy_ref = false}, - {.name = "readOnly", .offset = 577, .count = 6, .legacy_ref = true}, - {.name = "readonly", .offset = 583, .count = 4, .legacy_ref = true}, - {.name = "rel", .offset = 587, .count = 8, .legacy_ref = true}, - {.name = "required", .offset = 595, .count = 10, .legacy_ref = false}, - {.name = "requires", .offset = 605, .count = 6, .legacy_ref = false}, - {.name = "root", .offset = 611, .count = 4, .legacy_ref = true}, - {.name = "schema", .offset = 615, .count = 1, .legacy_ref = true}, + {.name = "prefixItems", .offset = 546, .count = 1, .legacy_ref = false}, + {.name = "properties", .offset = 547, .count = 18, .legacy_ref = false}, + {.name = "propertyNames", .offset = 565, .count = 6, .legacy_ref = false}, + {.name = "readOnly", .offset = 571, .count = 5, .legacy_ref = true}, + {.name = "readonly", .offset = 576, .count = 4, .legacy_ref = true}, + {.name = "rel", .offset = 580, .count = 8, .legacy_ref = true}, + {.name = "required", .offset = 588, .count = 10, .legacy_ref = false}, + {.name = "requires", .offset = 598, .count = 6, .legacy_ref = false}, + {.name = "root", .offset = 604, .count = 4, .legacy_ref = true}, + {.name = "schema", .offset = 608, .count = 1, .legacy_ref = true}, {.name = "submissionEncType", - .offset = 616, + .offset = 609, .count = 1, .legacy_ref = true}, {.name = "submissionMediaType", - .offset = 617, + .offset = 610, .count = 2, .legacy_ref = true}, - {.name = "submissionSchema", .offset = 619, .count = 3, .legacy_ref = true}, - {.name = "targetHints", .offset = 622, .count = 2, .legacy_ref = true}, - {.name = "targetMediaType", .offset = 624, .count = 2, .legacy_ref = true}, - {.name = "targetSchema", .offset = 626, .count = 6, .legacy_ref = true}, - {.name = "templatePointers", .offset = 632, .count = 2, .legacy_ref = true}, - {.name = "templateRequired", .offset = 634, .count = 2, .legacy_ref = true}, - {.name = "then", .offset = 636, .count = 4, .legacy_ref = false}, - {.name = "title", .offset = 640, .count = 16, .legacy_ref = false}, - {.name = "type", .offset = 656, .count = 18, .legacy_ref = false}, + {.name = "submissionSchema", .offset = 612, .count = 3, .legacy_ref = true}, + {.name = "targetHints", .offset = 615, .count = 2, .legacy_ref = true}, + {.name = "targetMediaType", .offset = 617, .count = 2, .legacy_ref = true}, + {.name = "targetSchema", .offset = 619, .count = 6, .legacy_ref = true}, + {.name = "templatePointers", .offset = 625, .count = 2, .legacy_ref = true}, + {.name = "templateRequired", .offset = 627, .count = 2, .legacy_ref = true}, + {.name = "then", .offset = 629, .count = 4, .legacy_ref = false}, + {.name = "title", .offset = 633, .count = 16, .legacy_ref = false}, + {.name = "type", .offset = 649, .count = 18, .legacy_ref = false}, {.name = "unevaluatedItems", - .offset = 674, + .offset = 667, .count = 3, .legacy_ref = false}, {.name = "unevaluatedProperties", - .offset = 677, + .offset = 670, .count = 3, .legacy_ref = false}, - {.name = "uniqueItems", .offset = 680, .count = 12, .legacy_ref = false}, - {.name = "writeOnly", .offset = 692, .count = 6, .legacy_ref = false}, - {.name = "xml", .offset = 698, .count = 2, .legacy_ref = false}, + {.name = "uniqueItems", .offset = 673, .count = 12, .legacy_ref = false}, + {.name = "writeOnly", .offset = 685, .count = 4, .legacy_ref = true}, + {.name = "xml", .offset = 689, .count = 2, .legacy_ref = false}, }}; constexpr auto REF_DEPENDENCIES{std::to_array({"$ref"})}; diff --git a/vendor/core/src/core/markdown/CMakeLists.txt b/vendor/core/src/core/markdown/CMakeLists.txt index 048612f09..db0aa8c11 100644 --- a/vendor/core/src/core/markdown/CMakeLists.txt +++ b/vendor/core/src/core/markdown/CMakeLists.txt @@ -1,11 +1,14 @@ sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME markdown + PRIVATE_HEADERS error.h SOURCES markdown.cc) if(SOURCEMETA_CORE_INSTALL) sourcemeta_library_install(NAMESPACE sourcemeta PROJECT core NAME markdown) endif() -target_link_libraries(sourcemeta_core_markdown PRIVATE CMarkGFM::cmark_gfm) - target_link_libraries(sourcemeta_core_markdown PRIVATE - sourcemeta::core::unicode) + sourcemeta::core::email + sourcemeta::core::html + sourcemeta::core::text + sourcemeta::core::unicode + sourcemeta::core::uri) diff --git a/vendor/core/src/core/markdown/blocks.h b/vendor/core/src/core/markdown/blocks.h new file mode 100644 index 000000000..1866754ad --- /dev/null +++ b/vendor/core/src/core/markdown/blocks.h @@ -0,0 +1,1336 @@ +#ifndef SOURCEMETA_CORE_MARKDOWN_BLOCKS_H_ +#define SOURCEMETA_CORE_MARKDOWN_BLOCKS_H_ + +#include +#include + +#include "characters.h" +#include "document.h" +#include "references.h" +#include "scanners.h" + +#include // std::min, std::max +#include // std::size_t, std::ptrdiff_t +#include // std::int32_t, std::int64_t, std::uint8_t, std::uint32_t +#include // std::memchr +#include // std::string +#include // std::string_view +#include // std::vector + +namespace sourcemeta::core::markdown { + +constexpr std::ptrdiff_t TAB_STOP{4}; +constexpr std::ptrdiff_t CODE_INDENT{4}; +// GFM section 4.10: "If there are a number of cells fewer than the number of +// cells in the header row, empty cells are inserted", which lets a small input +// turn into a huge table, so the conversion throws once a table inserts more +// empty cells than this +constexpr std::int64_t MAXIMUM_AUTOCOMPLETED_CELLS{0x80000}; +// The destinations and titles that rendered link references expand to can take +// up to this many times the size of the input or the minimum below, whichever +// is larger, before the conversion throws +constexpr std::size_t REFERENCE_SIZE_FACTOR{16}; +constexpr std::size_t MINIMUM_REFERENCE_SIZE_LIMIT{1048576}; + +struct TableCellSpan { + std::size_t offset; + std::size_t length; +}; + +inline auto is_block_type(const NodeType type) noexcept -> bool { + return type <= NodeType::TableCell; +} + +inline auto is_inline_type(const NodeType type) noexcept -> bool { + return type > NodeType::TableCell; +} + +inline auto accepts_lines(const NodeType type) noexcept -> bool { + return type == NodeType::Paragraph || type == NodeType::Heading || + type == NodeType::CodeBlock; +} + +// Whether the content is blank up to its first line ending +inline auto is_blank_until_line_end(const std::string_view content) noexcept + -> bool { + for (const auto character : content) { + if (character == '\r' || character == '\n') { + return true; + } + + if (character != ' ' && character != '\t') { + return false; + } + } + + return true; +} + +// The position of the next line feed, or the size of the input if there is +// none +inline auto find_line_feed(const std::string_view input, + const std::size_t position) noexcept -> std::size_t { + const auto *const found{static_cast( + std::memchr(input.data() + position, '\n', input.size() - position))}; + return found == nullptr ? input.size() + : static_cast(found - input.data()); +} + +// A row of the GFM table extension, where a string of several lines resolves +// to the row on its last line, whose offset is reported +inline auto parse_table_row(const std::string_view string, + std::vector &cells, + std::size_t &last_line_offset) -> bool { + cells.clear(); + last_line_offset = 0; + const auto length{string.size()}; + auto offset{scan_table_cell_end(string, 0)}; + bool expect_more_cells{true}; + while (offset < length && expect_more_cells) { + const auto cell_length{scan_table_cell(string, offset)}; + const auto pipe_length{scan_table_cell_end(string, offset + cell_length)}; + if (cell_length > 0 || pipe_length > 0) { + cells.push_back({.offset = offset, .length = cell_length}); + } + + offset += cell_length + pipe_length; + if (pipe_length > 0) { + continue; + } + + const auto row_end{scan_table_row_end(string, offset)}; + offset += row_end; + if (row_end > 0 && offset != length) { + last_line_offset = offset; + cells.clear(); + offset += scan_table_cell_end(string, offset); + } else { + expect_more_cells = false; + } + } + + return offset == length && !cells.empty(); +} + +// The block structure of GFM section 4 and 5 and of the table and task list +// extensions, following the parsing strategy of the specification appendix +class BlockParser { +public: + explicit BlockParser(Document &document) : document_{document} {} + + auto parse(const std::string_view input, const std::size_t total_size) + -> void { + this->current_ = ROOT_NODE; + this->line_number_ = 0; + this->blank_line_matched_everything_ = false; + this->skip_blank_continuations_ = false; + this->open_footnote_definitions_ = 0; + this->last_blank_container_ = NO_NODE; + const auto size{input.size()}; + const auto has_carriage_return{input.find('\r') != std::string_view::npos}; + std::size_t position{0}; + while (position < size) { + auto end{size}; + if (has_carriage_return) { + end = position; + while (end < size && input[end] != '\n' && input[end] != '\r') { + ++end; + } + } else { + end = find_line_feed(input, position); + } + + if (end < size && input[end] == '\n') { + this->process_line(input.substr(position, end + 1 - position)); + position = end + 1; + continue; + } + + this->line_buffer_.assign(input.substr(position, end - position)); + this->line_buffer_.push_back('\n'); + this->process_line(this->line_buffer_); + position = end; + if (position < size) { + ++position; + if (position < size && input[position] == '\n') { + ++position; + } + } + } + + while (this->current_ != ROOT_NODE) { + this->current_ = this->finalize(this->current_); + } + + this->finalize(ROOT_NODE); + this->document_.reference_size_limit = std::max( + total_size * REFERENCE_SIZE_FACTOR, MINIMUM_REFERENCE_SIZE_LIMIT); + } + +private: + auto node(const std::uint32_t index) -> Node & { + return this->document_.nodes[index]; + } + + [[nodiscard]] auto peek(const std::ptrdiff_t index) const noexcept -> char { + return index >= 0 && static_cast(index) < this->line_.size() + ? this->line_[static_cast(index)] + : '\0'; + } + + [[nodiscard]] auto line_size() const noexcept -> std::ptrdiff_t { + return static_cast(this->line_.size()); + } + + auto process_line(const std::string_view line) -> void { + this->line_ = line; + this->line_end_ = this->line_size(); + this->offset_ = 0; + this->column_ = 0; + this->first_nonspace_ = 0; + this->first_nonspace_column_ = 0; + this->thematic_break_kill_position_ = 0; + this->indent_ = 0; + this->blank_ = false; + this->partially_consumed_tab_ = false; + if (this->line_number_ == 0 && line.starts_with("\xEF\xBB\xBF")) { + this->offset_ += 3; + } + + ++this->line_number_; + const auto starting_tip{this->current_}; + const auto starting_nodes{this->document_.nodes.size()}; + const auto starting_offset{static_cast(this->offset_)}; + // An open footnote definition only continues on an unindented blank line + // when the line is empty, and an item without blocks does not continue on + // a blank line at all + this->skip_blank_continuations_ = + this->blank_line_matched_everything_ && + is_blank_until_line_end(line.substr(starting_offset)) && + (this->open_footnote_definitions_ == 0 || this->peek(0) == '\n' || + (this->peek(0) == '\r' && this->peek(1) == '\n')) && + !(this->node(starting_tip).type == NodeType::Item && + this->node(starting_tip).first_child == NO_NODE); + this->blank_line_matched_everything_ = false; + bool all_matched{true}; + const auto last_matched{this->check_open_blocks(all_matched)}; + if (last_matched == NO_NODE) { + return; + } + + auto container{last_matched}; + this->open_new_blocks(container, all_matched); + this->add_text_to_container(container, last_matched); + this->blank_line_matched_everything_ = + all_matched && last_matched == starting_tip && + this->current_ == starting_tip && + this->document_.nodes.size() == starting_nodes && this->blank_ && + is_blank_until_line_end(line.substr(starting_offset)); + } + + auto find_first_nonspace() -> void { + auto chars_to_tab{TAB_STOP - (this->column_ % TAB_STOP)}; + if (this->first_nonspace_ <= this->offset_) { + this->first_nonspace_ = this->offset_; + this->first_nonspace_column_ = this->column_; + while (true) { + const auto character{this->peek(this->first_nonspace_)}; + if (character == ' ') { + ++this->first_nonspace_; + ++this->first_nonspace_column_; + --chars_to_tab; + if (chars_to_tab == 0) { + chars_to_tab = TAB_STOP; + } + } else if (character == '\t') { + ++this->first_nonspace_; + this->first_nonspace_column_ += chars_to_tab; + chars_to_tab = TAB_STOP; + } else { + break; + } + } + } + + this->indent_ = this->first_nonspace_column_ - this->column_; + this->blank_ = is_line_end(this->peek(this->first_nonspace_)); + } + + // Advance by a number of bytes, or by a number of columns where a tab might + // only be partially consumed + auto advance_offset(std::ptrdiff_t count, const bool columns) -> void { + // Without tabs, advancing by bytes also advances by the same columns + if (!columns && count > 0 && this->offset_ + count <= this->line_size() && + std::memchr(this->line_.data() + this->offset_, '\t', + static_cast(count)) == nullptr) { + this->partially_consumed_tab_ = false; + this->offset_ += count; + this->column_ += count; + return; + } + + while (count > 0) { + const auto character{this->peek(this->offset_)}; + if (character == '\0') { + break; + } + + if (character != '\t') { + this->partially_consumed_tab_ = false; + ++this->offset_; + ++this->column_; + --count; + continue; + } + + const auto chars_to_tab{TAB_STOP - (this->column_ % TAB_STOP)}; + if (columns) { + this->partially_consumed_tab_ = chars_to_tab > count; + const auto chars_to_advance{std::min(count, chars_to_tab)}; + this->column_ += chars_to_advance; + this->offset_ += this->partially_consumed_tab_ ? 0 : 1; + count -= chars_to_advance; + } else { + this->partially_consumed_tab_ = false; + this->column_ += chars_to_tab; + ++this->offset_; + --count; + } + } + } + + auto advance_to_line_end() -> void { + this->advance_offset(this->line_size() - 1 - this->offset_, false); + } + + auto advance_to_first_nonspace() -> void { + this->advance_offset(this->first_nonspace_ - this->offset_, false); + } + + auto last_child_is_open(const std::uint32_t index) -> bool { + const auto last_child{this->node(index).last_child}; + return last_child != NO_NODE && has_flag(this->node(last_child), FLAG_OPEN); + } + + auto can_contain(const std::uint32_t parent, const NodeType child) -> bool { + const auto &parent_node{this->node(parent)}; + switch (parent_node.type) { + case NodeType::Document: + case NodeType::BlockQuote: + case NodeType::FootnoteDefinition: + return is_block_type(child) && child != NodeType::Item; + case NodeType::Item: + return has_flag(parent_node, FLAG_TASK) || + (is_block_type(child) && child != NodeType::Item); + case NodeType::List: + return child == NodeType::Item; + case NodeType::Table: + return child == NodeType::TableRow; + case NodeType::TableRow: + return child == NodeType::TableCell; + case NodeType::Paragraph: + case NodeType::Heading: + return is_inline_type(child); + case NodeType::CodeBlock: + case NodeType::HTMLBlock: + case NodeType::ThematicBreak: + case NodeType::TableCell: + case NodeType::Text: + case NodeType::SoftBreak: + case NodeType::LineBreak: + case NodeType::Code: + case NodeType::HTMLInline: + case NodeType::Emphasis: + case NodeType::Strong: + case NodeType::Link: + case NodeType::Image: + case NodeType::FootnoteReference: + case NodeType::Strikethrough: + return false; + } + + return false; + } + + auto add_child(std::uint32_t parent, const NodeType type) -> std::uint32_t { + while (!this->can_contain(parent, type)) { + parent = this->finalize(parent); + } + + const auto child{this->document_.create(type)}; + this->node(child).flags = FLAG_OPEN; + this->document_.append_child(parent, child); + if (type == NodeType::FootnoteDefinition) { + ++this->open_footnote_definitions_; + } + + return child; + } + + auto add_line(const std::uint32_t index) -> void { + auto &content{this->document_.content}; + auto &target{this->node(index)}; + if (target.content_length == 0) { + target.content_offset = static_cast(content.size()); + } else if (target.content_offset + target.content_length != + content.size()) { + this->relocation_buffer_.assign(this->document_.content_of(target)); + target.content_offset = static_cast(content.size()); + content.append(this->relocation_buffer_); + } + + const auto before{content.size()}; + if (this->partially_consumed_tab_) { + ++this->offset_; + const auto chars_to_tab{TAB_STOP - (this->column_ % TAB_STOP)}; + content.append(static_cast(chars_to_tab), ' '); + } + + if (this->line_end_ > this->offset_) { + content.append(this->line_.substr( + static_cast(this->offset_), + static_cast(this->line_end_ - this->offset_))); + } + + target.content_length += + static_cast(content.size() - before); + } + + auto resolve_reference_definitions(const std::uint32_t index) -> bool { + const auto content{this->document_.content_of(this->node(index))}; + std::size_t position{0}; + while (position < content.size() && content[position] == '[') { + const auto consumed{ + parse_reference_definition(this->document_, content.substr(position), + this->label_buffer_, this->value_buffer_)}; + if (consumed == 0) { + break; + } + + position += consumed; + } + + auto &target{this->node(index)}; + target.content_offset += static_cast(position); + target.content_length -= static_cast(position); + return !is_blank_until_line_end(content.substr(position)); + } + + auto ends_with_blank_line(std::uint32_t index) -> bool { + while (true) { + auto ¤t{this->node(index)}; + if (has_flag(current, FLAG_LAST_LINE_CHECKED)) { + return has_flag(current, FLAG_LAST_LINE_BLANK); + } + + set_flag(current, FLAG_LAST_LINE_CHECKED, true); + if ((current.type == NodeType::List || current.type == NodeType::Item) && + current.last_child != NO_NODE) { + index = current.last_child; + continue; + } + + return has_flag(current, FLAG_LAST_LINE_BLANK); + } + } + + auto finalize_list(const std::uint32_t index) -> void { + bool tight{true}; + for (auto item{this->node(index).first_child}; item != NO_NODE && tight; + item = this->node(item).next) { + if (has_flag(this->node(item), FLAG_LAST_LINE_BLANK) && + this->node(item).next != NO_NODE) { + tight = false; + break; + } + + for (auto child{this->node(item).first_child}; child != NO_NODE; + child = this->node(child).next) { + if ((this->node(item).next != NO_NODE || + this->node(child).next != NO_NODE) && + this->ends_with_blank_line(child)) { + tight = false; + break; + } + } + } + + set_flag(this->node(index), FLAG_TIGHT, tight); + } + + auto finalize_code_block(const std::uint32_t index) -> void { + auto &target{this->node(index)}; + const auto content{this->document_.content_of(target)}; + if (!has_flag(target, FLAG_FENCED)) { + auto end{content.size()}; + while (end > 0 && (content[end - 1] == ' ' || content[end - 1] == '\t' || + is_line_end(content[end - 1]))) { + --end; + } + + if (end == 0) { + target.content_length = 0; + target.literal = "\n"; + return; + } + + const auto line_end{content.find_first_of("\r\n", end - 1)}; + if (line_end == std::string_view::npos) { + this->value_buffer_.assign(content); + this->value_buffer_.push_back('\n'); + target.literal = this->document_.strings.store(this->value_buffer_); + return; + } + + if (content[line_end] == '\n') { + target.content_length = static_cast(line_end + 1); + return; + } + + this->value_buffer_.assign(content.substr(0, line_end)); + this->value_buffer_.push_back('\n'); + target.literal = this->document_.strings.store(this->value_buffer_); + + return; + } + + auto position{content.find_first_of("\r\n")}; + if (position == std::string_view::npos) { + position = content.size(); + } + + this->value_buffer_.clear(); + decode_escapes_and_references(this->value_buffer_, + content.substr(0, position)); + target.title = this->document_.strings.store( + sourcemeta::core::trim(this->value_buffer_, is_space)); + if (character_at(content, position) == '\r') { + ++position; + } + + if (character_at(content, position) == '\n') { + ++position; + } + + position = std::min(position, content.size()); + target.content_offset += static_cast(position); + target.content_length -= static_cast(position); + } + + auto finalize(const std::uint32_t index) -> std::uint32_t { + const auto parent{this->node(index).parent}; + set_flag(this->node(index), FLAG_OPEN, false); + const auto type{this->node(index).type}; + if (type == NodeType::FootnoteDefinition) { + --this->open_footnote_definitions_; + } + + if (type == NodeType::Paragraph) { + if (!this->resolve_reference_definitions(index)) { + this->document_.unlink(index); + } + } else if (type == NodeType::CodeBlock) { + this->finalize_code_block(index); + } else if (type == NodeType::List) { + this->finalize_list(index); + } + + return parent; + } + + auto parse_block_quote_prefix() -> bool { + if (this->indent_ > 3 || this->peek(this->first_nonspace_) != '>') { + return false; + } + + this->advance_offset(this->indent_ + 1, true); + if (is_space_or_tab(this->peek(this->offset_))) { + this->advance_offset(1, true); + } + + return true; + } + + auto parse_footnote_definition_prefix() -> bool { + if (this->indent_ >= CODE_INDENT) { + this->advance_offset(CODE_INDENT, true); + return true; + } + + return this->peek(0) == '\n' || + (this->peek(0) == '\r' && this->peek(1) == '\n'); + } + + auto parse_item_prefix(const std::uint32_t index) -> bool { + const auto &data{this->document_.lists[this->node(index).data]}; + const auto width{static_cast(data.marker_offset) + + static_cast(data.padding)}; + if (this->indent_ >= width) { + this->advance_offset(width, true); + return true; + } + + if (this->blank_ && this->node(index).first_child != NO_NODE) { + this->advance_to_first_nonspace(); + return true; + } + + return false; + } + + auto parse_code_block_prefix(const std::uint32_t index, bool &should_continue) + -> bool { + if (!has_flag(this->node(index), FLAG_FENCED)) { + if (this->indent_ >= CODE_INDENT) { + this->advance_offset(CODE_INDENT, true); + return true; + } + + if (this->blank_) { + this->advance_to_first_nonspace(); + return true; + } + + return false; + } + + std::size_t matched{0}; + if (this->indent_ <= 3 && + static_cast(this->peek(this->first_nonspace_)) == + this->node(index).data) { + matched = scan_close_code_fence( + this->line_, static_cast(this->first_nonspace_)); + } + + if (matched > 0 && matched >= this->node(index).level) { + should_continue = false; + this->advance_offset(static_cast(matched), false); + this->current_ = this->finalize(index); + return false; + } + + auto remaining{static_cast(this->node(index).extra)}; + while (remaining > 0 && is_space_or_tab(this->peek(this->offset_))) { + this->advance_offset(1, true); + --remaining; + } + + return true; + } + + auto table_row_matches() -> bool { + std::size_t last_line_offset{0}; + this->cached_row_valid_ = parse_table_row( + this->line_.substr(static_cast(this->first_nonspace_)), + this->cells_, last_line_offset); + this->cached_row_line_ = this->line_number_; + this->cached_row_offset_ = this->first_nonspace_; + return this->cached_row_valid_; + } + + auto continues_container(const std::uint32_t index, bool &should_continue) + -> bool { + switch (this->node(index).type) { + case NodeType::BlockQuote: + return this->parse_block_quote_prefix(); + case NodeType::Item: + return this->parse_item_prefix(index); + case NodeType::CodeBlock: + return this->parse_code_block_prefix(index, should_continue); + case NodeType::HTMLBlock: + return this->node(index).level <= 5 || !this->blank_; + case NodeType::Paragraph: + return !this->blank_; + case NodeType::FootnoteDefinition: + return this->parse_footnote_definition_prefix(); + case NodeType::Table: + return this->table_row_matches(); + // GFM section 4.1 makes a thematic break out of a single line, so it does + // not continue, and a blank line after it reaches the blocks around it + case NodeType::Heading: + case NodeType::ThematicBreak: + case NodeType::TableRow: + case NodeType::TableCell: + return false; + case NodeType::Document: + case NodeType::List: + case NodeType::Text: + case NodeType::SoftBreak: + case NodeType::LineBreak: + case NodeType::Code: + case NodeType::HTMLInline: + case NodeType::Emphasis: + case NodeType::Strong: + case NodeType::Link: + case NodeType::Image: + case NodeType::FootnoteReference: + case NodeType::Strikethrough: + return true; + } + + return true; + } + + auto check_open_blocks(bool &all_matched) -> std::uint32_t { + bool should_continue{true}; + all_matched = true; + auto container{ROOT_NODE}; + while (this->last_child_is_open(container)) { + container = this->node(container).last_child; + this->find_first_nonspace(); + // Once a blank line has no indentation left, every remaining open block + // continues without consuming anything if the previous line was blank, + // matched every open block, and changed nothing, which spares walking + // through deeply nested blocks for every blank line + if (this->skip_blank_continuations_ && this->blank_ && + this->indent_ == 0) { + return this->current_; + } + + if (!this->continues_container(container, should_continue)) { + all_matched = false; + break; + } + } + + if (!all_matched) { + container = this->node(container).parent; + } + + return should_continue ? container : NO_NODE; + } + + auto scan_thematic_break(const std::ptrdiff_t position) -> std::ptrdiff_t { + const auto marker{this->peek(position)}; + if (marker != '*' && marker != '_' && marker != '-') { + this->thematic_break_kill_position_ = position; + return 0; + } + + std::ptrdiff_t count{1}; + auto index{position}; + char next{'\0'}; + while (true) { + ++index; + next = this->peek(index); + if (next == '\0') { + break; + } + + if (next == marker) { + ++count; + } else if (next != ' ' && next != '\t') { + break; + } + } + + if (count >= 3 && (next == '\r' || next == '\n')) { + return index - position + 1; + } + + this->thematic_break_kill_position_ = index; + return 0; + } + + auto parse_list_marker(const std::ptrdiff_t position, + const bool interrupts_paragraph, ListData &data) + -> std::ptrdiff_t { + auto cursor{position}; + const auto marker{this->peek(cursor)}; + if (marker == '*' || marker == '-' || marker == '+') { + ++cursor; + if (!is_space(this->peek(cursor))) { + return 0; + } + + if (interrupts_paragraph) { + auto index{cursor}; + while (is_space_or_tab(this->peek(index))) { + ++index; + } + + if (this->peek(index) == '\n') { + return 0; + } + } + + data = ListData{}; + data.bullet_character = marker; + return cursor - position; + } + + if (!sourcemeta::core::is_digit(marker)) { + return 0; + } + + std::int32_t start{0}; + std::int32_t digits{0}; + while (true) { + start = (10 * start) + (this->peek(cursor) - '0'); + ++cursor; + ++digits; + if (digits >= 9 || !sourcemeta::core::is_digit(this->peek(cursor))) { + break; + } + } + + if (interrupts_paragraph && start != 1) { + return 0; + } + + const auto delimiter{this->peek(cursor)}; + if (delimiter != '.' && delimiter != ')') { + return 0; + } + + ++cursor; + if (!is_space(this->peek(cursor))) { + return 0; + } + + if (interrupts_paragraph) { + auto index{cursor}; + while (is_space_or_tab(this->peek(index))) { + ++index; + } + + if (is_line_end(this->peek(index))) { + return 0; + } + } + + data = ListData{}; + data.start = start; + data.delimiter = delimiter; + data.ordered = true; + return cursor - position; + } + + auto append_table_cell_content(const std::uint32_t cell, + const std::string_view raw) -> void { + const auto text{sourcemeta::core::trim(raw, is_space)}; + auto &content{this->document_.content}; + auto &target{this->node(cell)}; + target.content_offset = static_cast(content.size()); + std::size_t run_start{0}; + for (std::size_t index{0}; index + 1 < text.size(); ++index) { + if (text[index] == '\\' && text[index + 1] == '|') { + content.append(text.substr(run_start, index - run_start)); + run_start = index + 1; + } + } + + content.append(text.substr(run_start)); + + target.content_length = + static_cast(content.size() - target.content_offset); + } + + auto try_opening_table_header(const std::uint32_t paragraph) + -> std::uint32_t { + this->cached_row_line_ = -1; + if (has_flag(this->node(paragraph), FLAG_TABLE_VISITED)) { + return paragraph; + } + + const auto nonspace{static_cast(this->first_nonspace_)}; + std::size_t last_line_offset{0}; + if (scan_table_start(this->line_, nonspace) == 0 || + !parse_table_row(this->line_.substr(nonspace), this->cells_, + last_line_offset)) { + return paragraph; + } + + this->header_buffer_.assign( + this->document_.content_of(this->node(paragraph))); + if (!parse_table_row(this->header_buffer_, this->header_cells_, + last_line_offset) || + this->header_cells_.size() != this->cells_.size()) { + set_flag(this->node(paragraph), FLAG_TABLE_VISITED, true); + return paragraph; + } + + if (last_line_offset > 0) { + const auto preceding{this->document_.create(NodeType::Paragraph)}; + this->append_table_cell_content( + preceding, + std::string_view{this->header_buffer_}.substr(0, last_line_offset)); + this->document_.insert_before(paragraph, preceding); + } + + const auto table_index{ + static_cast(this->document_.tables.size())}; + this->document_.tables.push_back( + {.alignments_offset = + static_cast(this->document_.alignments.size()), + .columns = static_cast(this->header_cells_.size()), + .rows = 1, + .nonempty_cells = + static_cast(this->header_cells_.size())}); + for (const auto &cell : this->cells_) { + const auto marker{sourcemeta::core::trim( + this->line_.substr(nonspace + cell.offset, cell.length), is_space)}; + const auto left{!marker.empty() && marker.front() == ':'}; + const auto right{!marker.empty() && marker.back() == ':'}; + std::uint8_t alignment{0}; + if (left && right) { + alignment = 'c'; + } else if (left) { + alignment = 'l'; + } else if (right) { + alignment = 'r'; + } + + this->document_.alignments.push_back(alignment); + } + + auto &table{this->node(paragraph)}; + table.type = NodeType::Table; + table.data = table_index; + const auto row{this->add_child(paragraph, NodeType::TableRow)}; + set_flag(this->node(row), FLAG_HEADER, true); + for (std::size_t index{0}; index < this->header_cells_.size(); ++index) { + const auto cell{this->add_child(row, NodeType::TableCell)}; + this->node(cell).data = static_cast(index); + this->append_table_cell_content( + cell, std::string_view{this->header_buffer_}.substr( + this->header_cells_[index].offset, + this->header_cells_[index].length)); + } + + this->advance_to_line_end(); + return paragraph; + } + + auto try_opening_table_row(const std::uint32_t table) -> std::uint32_t { + if (this->blank_) { + return NO_NODE; + } + + const auto table_index{this->node(table).data}; + + const auto row{this->add_child(table, NodeType::TableRow)}; + const auto nonspace{static_cast(this->first_nonspace_)}; + std::size_t last_line_offset{0}; + const auto cached{this->cached_row_line_ == this->line_number_ && + this->cached_row_offset_ == this->first_nonspace_}; + if (!(cached ? this->cached_row_valid_ + : parse_table_row(this->line_.substr(nonspace), this->cells_, + last_line_offset))) { + this->document_.unlink(row); + return NO_NODE; + } + + const auto columns{this->document_.tables[table_index].columns}; + std::size_t index{0}; + for (; index < this->cells_.size() && index < columns; ++index) { + const auto cell{this->add_child(row, NodeType::TableCell)}; + this->node(cell).data = static_cast(index); + this->append_table_cell_content( + cell, this->line_.substr(nonspace + this->cells_[index].offset, + this->cells_[index].length)); + } + + auto &data{this->document_.tables[table_index]}; + data.rows += 1; + data.nonempty_cells += static_cast(index); + if ((static_cast(data.columns) * data.rows) - + data.nonempty_cells > + MAXIMUM_AUTOCOMPLETED_CELLS) { + throw sourcemeta::core::MarkdownError{ + "The table inserts more empty cells than its bound"}; + } + for (; index < columns; ++index) { + const auto cell{this->add_child(row, NodeType::TableCell)}; + this->node(cell).data = static_cast(index); + } + + this->advance_to_line_end(); + return row; + } + + // A list item whose first block is a paragraph that starts with a task list + // item marker of GFM section 5.3, which the item can only get while it has + // no block yet + auto open_task_list_item(const std::uint32_t item) -> void { + if (this->node(item).type != NodeType::Item || + this->node(item).first_child != NO_NODE || + !scan_task_list_marker( + this->line_, static_cast(this->first_nonspace_))) { + return; + } + + set_flag(this->node(item), FLAG_TASK, true); + // GFM section 5.3: "If the character between the brackets is a whitespace + // character, the checkbox is unchecked. Otherwise, the checkbox is checked" + const auto state{this->peek(this->first_nonspace_ + 1)}; + set_flag(this->node(item), FLAG_CHECKED, state == 'x' || state == 'X'); + this->advance_offset(this->first_nonspace_ + 3 - this->offset_, false); + } + + auto register_footnote_definition(const std::uint32_t definition) -> void { + for (auto ancestor{this->node(definition).parent}; ancestor != NO_NODE; + ancestor = this->node(ancestor).parent) { + if (this->node(ancestor).type == NodeType::FootnoteDefinition) { + this->document_.nested_footnote_definitions = true; + break; + } + } + + this->document_.footnote_definition_nodes.push_back(definition); + } + + auto open_block(std::uint32_t &container, const NodeType container_type, + const bool all_matched, const bool maybe_lazy) -> bool { + const auto indented{this->indent_ >= CODE_INDENT}; + const auto nonspace{static_cast(this->first_nonspace_)}; + const auto character{this->peek(this->first_nonspace_)}; + if (!indented && this->peek(this->first_nonspace_) == '>') { + this->advance_offset(this->first_nonspace_ + 1 - this->offset_, false); + if (is_space_or_tab(this->peek(this->offset_))) { + this->advance_offset(1, true); + } + + container = this->add_child(container, NodeType::BlockQuote); + return true; + } + + if (!indented && character == '#') { + const auto matched{scan_atx_heading_start(this->line_, nonspace)}; + if (matched > 0) { + this->advance_offset(this->first_nonspace_ + + static_cast(matched) - + this->offset_, + false); + container = this->add_child(container, NodeType::Heading); + auto hash{this->line_.find('#', nonspace)}; + std::uint8_t level{0}; + while (hash < this->line_.size() && this->line_[hash] == '#') { + ++level; + ++hash; + } + + this->node(container).level = level; + return true; + } + } + + if (!indented && (character == '`' || character == '~')) { + const auto matched{scan_open_code_fence(this->line_, nonspace)}; + if (matched > 0) { + container = this->add_child(container, NodeType::CodeBlock); + auto &code{this->node(container)}; + set_flag(code, FLAG_FENCED, true); + code.data = + static_cast(this->peek(this->first_nonspace_)); + code.level = + static_cast(std::min(matched, 255)); + code.extra = + static_cast(this->first_nonspace_ - this->offset_); + this->advance_offset(this->first_nonspace_ + + static_cast(matched) - + this->offset_, + false); + return true; + } + } + + if (!indented && character == '<') { + auto condition{scan_html_block_start(this->line_, nonspace)}; + if (condition == 0 && container_type != NodeType::Paragraph && + scan_html_block_start_7(this->line_, nonspace)) { + condition = 7; + } + + if (condition > 0) { + container = this->add_child(container, NodeType::HTMLBlock); + this->node(container).level = static_cast(condition); + return true; + } + } + + if (!indented && container_type == NodeType::Paragraph && + (character == '=' || character == '-')) { + const auto level{scan_setext_heading_line(this->line_, nonspace)}; + if (level > 0) { + if (this->resolve_reference_definitions(container)) { + auto &heading{this->node(container)}; + heading.type = NodeType::Heading; + heading.level = level; + set_flag(heading, FLAG_SETEXT, true); + this->advance_to_line_end(); + } + + return true; + } + } + + if (!indented && + (character == '*' || character == '_' || character == '-') && + !(container_type == NodeType::Paragraph && !all_matched) && + this->thematic_break_kill_position_ <= this->first_nonspace_ && + this->scan_thematic_break(this->first_nonspace_) > 0) { + container = this->add_child(container, NodeType::ThematicBreak); + this->advance_to_line_end(); + return true; + } + + if (!indented && character == '[') { + const auto matched{scan_footnote_definition(this->line_, nonspace)}; + if (matched > 0) { + auto label{this->line_.substr(nonspace + 2, matched - 2)}; + while (!label.empty() && label.back() != ']') { + label.remove_suffix(1); + } + + if (!label.empty()) { + label.remove_suffix(1); + } + + const auto stored{this->document_.strings.store(label)}; + this->advance_offset(this->first_nonspace_ + + static_cast(matched) - + this->offset_, + false); + container = this->add_child(container, NodeType::FootnoteDefinition); + this->register_footnote_definition(container); + this->node(container).literal = stored; + return true; + } + } + + if ((character == '*' || character == '-' || character == '+' || + sourcemeta::core::is_digit(character)) && + (!indented || container_type == NodeType::List) && + this->indent_ < CODE_INDENT) { + ListData data{}; + const auto matched{this->parse_list_marker( + this->first_nonspace_, container_type == NodeType::Paragraph, data)}; + if (matched > 0) { + this->advance_offset(this->first_nonspace_ + matched - this->offset_, + false); + const auto saved_partially_consumed_tab{this->partially_consumed_tab_}; + const auto saved_offset{this->offset_}; + const auto saved_column{this->column_}; + while (this->column_ - saved_column <= 5 && + is_space_or_tab(this->peek(this->offset_))) { + this->advance_offset(1, true); + } + + const auto spaces{this->column_ - saved_column}; + if (spaces >= 5 || spaces < 1 || + is_line_end(this->peek(this->offset_))) { + data.padding = static_cast(matched + 1); + this->offset_ = saved_offset; + this->column_ = saved_column; + this->partially_consumed_tab_ = saved_partially_consumed_tab; + if (spaces > 0) { + this->advance_offset(1, true); + } + } else { + data.padding = static_cast(matched + spaces); + } + + data.marker_offset = static_cast(this->indent_); + auto &lists{this->document_.lists}; + if (container_type != NodeType::List || + !lists_match(lists[this->node(container).data], data)) { + container = this->add_child(container, NodeType::List); + this->node(container).data = static_cast(lists.size()); + lists.push_back(data); + } + + data.start_line = this->line_number_; + container = this->add_child(container, NodeType::Item); + this->node(container).data = static_cast(lists.size()); + lists.push_back(data); + return true; + } + } + + if (indented && !maybe_lazy && !this->blank_) { + this->advance_offset(CODE_INDENT, true); + container = this->add_child(container, NodeType::CodeBlock); + return true; + } + + if (!indented && container_type == NodeType::Paragraph) { + if (character == '|' || character == ':' || character == '-' || + character == '\v' || character == '\f') { + container = this->try_opening_table_header(container); + } + return true; + } + + if (!indented && container_type == NodeType::Table) { + const auto row{this->try_opening_table_row(container)}; + if (row != NO_NODE) { + container = row; + return true; + } + } + + this->open_task_list_item(container); + return false; + } + + static auto lists_match(const ListData &list, const ListData &item) noexcept + -> bool { + return list.ordered == item.ordered && list.delimiter == item.delimiter && + list.bullet_character == item.bullet_character; + } + + auto open_new_blocks(std::uint32_t &container, const bool all_matched) + -> void { + bool maybe_lazy{this->node(this->current_).type == NodeType::Paragraph}; + auto container_type{this->node(container).type}; + while (container_type != NodeType::CodeBlock && + container_type != NodeType::HTMLBlock) { + this->find_first_nonspace(); + if (!this->open_block(container, container_type, all_matched, + maybe_lazy)) { + break; + } + + container_type = this->node(container).type; + if (accepts_lines(container_type)) { + break; + } + + maybe_lazy = false; + } + } + + auto chop_trailing_hashes() -> void { + auto length{this->line_end_}; + while (length > 0 && is_space(this->peek(length - 1))) { + --length; + } + + auto position{length - 1}; + while (position >= 0 && this->peek(position) == '#') { + --position; + } + + if (position != length - 1 && position >= 0 && + is_space_or_tab(this->peek(position))) { + length = position; + while (length > 0 && is_space(this->peek(length - 1))) { + --length; + } + } + + this->line_end_ = length; + } + + auto add_text_to_container(std::uint32_t container, + const std::uint32_t last_matched) -> void { + this->find_first_nonspace(); + if (this->blank_ && this->node(container).last_child != NO_NODE) { + set_flag(this->node(this->node(container).last_child), + FLAG_LAST_LINE_BLANK, true); + } + + const auto container_type{this->node(container).type}; + // A table only contains the lines of its rows, as GFM section 4.10 says + // that "The table is broken at the first empty line", so it never ends with + // a blank line, even when its delimiter row consumed the rest of its line + const auto last_line_blank{ + this->blank_ && container_type != NodeType::BlockQuote && + container_type != NodeType::Heading && + container_type != NodeType::ThematicBreak && + container_type != NodeType::Table && + container_type != NodeType::TableRow && + !(container_type == NodeType::CodeBlock && + has_flag(this->node(container), FLAG_FENCED)) && + !(container_type == NodeType::Item && + this->node(container).first_child == NO_NODE && + this->document_.lists[this->node(container).data].start_line == + this->line_number_)}; + // The ancestors of the container do not end with a blank line. The only + // open block that can is the container of the previous line, which is the + // deepest open block when this line starts, so it is an ancestor exactly + // when this line matched it and opened blocks under it + const auto previous_blank{this->last_blank_container_}; + if (previous_blank != NO_NODE && previous_blank == last_matched && + previous_blank != container && + has_flag(this->node(previous_blank), FLAG_OPEN)) { + set_flag(this->node(previous_blank), FLAG_LAST_LINE_BLANK, false); + } + + set_flag(this->node(container), FLAG_LAST_LINE_BLANK, last_line_blank); + this->last_blank_container_ = last_line_blank ? container : NO_NODE; + + if (this->current_ != last_matched && container == last_matched && + !this->blank_ && + this->node(this->current_).type == NodeType::Paragraph) { + this->add_line(this->current_); + return; + } + + while (this->current_ != last_matched) { + this->current_ = this->finalize(this->current_); + } + + if (container_type == NodeType::CodeBlock) { + this->add_line(container); + } else if (container_type == NodeType::HTMLBlock) { + this->add_line(container); + const auto condition{this->node(container).level}; + if (condition <= 5 && + scan_html_block_end(this->line_, + static_cast(this->first_nonspace_), + condition)) { + container = this->finalize(container); + } + } else if (this->blank_) { + // Blank lines only separate blocks + } else if (accepts_lines(container_type)) { + if (container_type == NodeType::Heading && + !has_flag(this->node(container), FLAG_SETEXT)) { + this->chop_trailing_hashes(); + } + + this->advance_to_first_nonspace(); + this->add_line(container); + } else { + container = this->add_child(container, NodeType::Paragraph); + this->advance_to_first_nonspace(); + this->add_line(container); + } + + this->current_ = container; + } + + Document &document_; + std::string_view line_; + std::ptrdiff_t line_end_{0}; + std::string line_buffer_; + std::string relocation_buffer_; + std::string label_buffer_; + std::string value_buffer_; + std::string header_buffer_; + std::vector cells_; + std::vector header_cells_; + std::int32_t cached_row_line_{-1}; + std::ptrdiff_t cached_row_offset_{0}; + bool cached_row_valid_{false}; + std::uint32_t current_{ROOT_NODE}; + std::int32_t line_number_{0}; + std::ptrdiff_t offset_{0}; + std::ptrdiff_t column_{0}; + std::ptrdiff_t first_nonspace_{0}; + std::ptrdiff_t first_nonspace_column_{0}; + std::ptrdiff_t thematic_break_kill_position_{0}; + std::ptrdiff_t indent_{0}; + bool blank_{false}; + bool partially_consumed_tab_{false}; + bool blank_line_matched_everything_{false}; + bool skip_blank_continuations_{false}; + std::size_t open_footnote_definitions_{0}; + std::uint32_t last_blank_container_{NO_NODE}; +}; + +} // namespace sourcemeta::core::markdown + +#endif diff --git a/vendor/core/src/core/markdown/characters.h b/vendor/core/src/core/markdown/characters.h new file mode 100644 index 000000000..e1ed0fcd4 --- /dev/null +++ b/vendor/core/src/core/markdown/characters.h @@ -0,0 +1,270 @@ +#ifndef SOURCEMETA_CORE_MARKDOWN_CHARACTERS_H_ +#define SOURCEMETA_CORE_MARKDOWN_CHARACTERS_H_ + +#include +#include +#include + +#include // std::min +#include // std::size_t +#include // std::string +#include // std::string_view + +namespace sourcemeta::core::markdown { + +// The ASCII whitespace that the parser trims is only the tab, the line feed, +// the carriage return, and the space +inline auto is_space(const char character) noexcept -> bool { + return character == ' ' || character == '\t' || character == '\n' || + character == '\r'; +} + +// GFM section 2.1: "A whitespace character is a space (U+0020), tab (U+0009), +// newline (U+000A), line tabulation (U+000B), form feed (U+000C), or carriage +// return (U+000D)" +inline auto is_whitespace_character(const char character) noexcept -> bool { + return character == ' ' || character == '\t' || character == '\n' || + character == '\v' || character == '\f' || character == '\r'; +} + +// GFM section 6.6: a link destination that is not enclosed in angle brackets +// "does not include ASCII space or control characters" +inline auto is_space_or_control(const char character) noexcept -> bool { + const auto byte{static_cast(character)}; + return byte <= 0x20 || byte == 0x7F; +} + +inline auto is_space_or_tab(const char character) noexcept -> bool { + return character == ' ' || character == '\t'; +} + +inline auto is_line_end(const char character) noexcept -> bool { + return character == '\n' || character == '\r'; +} + +// The Unicode whitespace of GFM section 2.1 +inline auto is_unicode_whitespace(const char32_t codepoint) noexcept -> bool { + if (codepoint < 0x80) { + return codepoint == U'\t' || codepoint == U'\n' || codepoint == U'\f' || + codepoint == U'\r' || codepoint == U' '; + } + + return sourcemeta::core::general_category(codepoint) == + sourcemeta::core::GeneralCategory::SpaceSeparator; +} + +// The punctuation of GFM section 2.1 +inline auto is_unicode_punctuation(const char32_t codepoint) noexcept -> bool { + if (codepoint < 0x80) { + return sourcemeta::core::is_punctuation(static_cast(codepoint)); + } + + const auto category{sourcemeta::core::general_category(codepoint)}; + return category == sourcemeta::core::GeneralCategory::ConnectorPunctuation || + category == sourcemeta::core::GeneralCategory::DashPunctuation || + category == sourcemeta::core::GeneralCategory::OpenPunctuation || + category == sourcemeta::core::GeneralCategory::ClosePunctuation || + category == sourcemeta::core::GeneralCategory::InitialPunctuation || + category == sourcemeta::core::GeneralCategory::FinalPunctuation || + category == sourcemeta::core::GeneralCategory::OtherPunctuation; +} + +// Decode the character reference that follows an ampersand as GFM section 6.2 +// describes, appending its characters and returning the number of bytes it +// takes after the ampersand, or zero if the input does not start with one +inline auto decode_character_reference(std::string &output, + const std::string_view input) + -> std::size_t { + const auto size{input.size()}; + if (size >= 3 && input[0] == '#') { + char32_t codepoint{0}; + std::size_t index{0}; + std::size_t digits{0}; + // GFM section 6.2: "Decimal numeric character references consist of &# + + // a string of 1-7 arabic digits" followed by a semicolon, and "Hexadecimal + // numeric character references consist of &# + either X or x + a string + // of 1-6 hexadecimal digits" followed by a semicolon + std::size_t maximum_digits{0}; + if (sourcemeta::core::is_digit(input[1])) { + for (index = 1; index < size && sourcemeta::core::is_digit(input[index]); + ++index) { + codepoint = + (codepoint * 10) + static_cast(input[index] - '0'); + codepoint = std::min(codepoint, char32_t{0x110000}); + } + + digits = index - 1; + maximum_digits = 7; + } else if (input[1] == 'x' || input[1] == 'X') { + for (index = 2; index < size; ++index) { + const auto value{sourcemeta::core::hex_digit_value(input[index])}; + if (value < 0) { + break; + } + + codepoint = (codepoint * 16) + static_cast(value); + codepoint = std::min(codepoint, char32_t{0x110000}); + } + + digits = index - 2; + maximum_digits = 6; + } + + if (digits >= 1 && digits <= maximum_digits && index < size && + input[index] == ';') { + if (codepoint == 0 || !sourcemeta::core::is_valid_codepoint(codepoint)) { + codepoint = 0xFFFD; + } + + sourcemeta::core::codepoint_to_utf8(codepoint, output); + return index + 1; + } + + return 0; + } + + // The longest name is 31 characters long, so there is no point in looking + // for a semicolon any further + const auto limit{size > 32 ? std::size_t{32} : size}; + for (std::size_t index{2}; index < limit; ++index) { + if (input[index] == ' ') { + break; + } + + if (input[index] == ';') { + const auto characters{ + sourcemeta::core::html_entity(input.substr(0, index + 1))}; + if (!characters.empty()) { + output.append(characters); + return index + 1; + } + + break; + } + } + + return 0; +} + +// Replace every character reference of the input, returning whether the input +// had any ampersand at all, in which case the output holds the result +inline auto decode_character_references(std::string &output, + const std::string_view input) -> bool { + auto ampersand{input.find('&')}; + if (ampersand == std::string_view::npos) { + return false; + } + + std::size_t index{0}; + while (ampersand != std::string_view::npos) { + output.append(input.substr(index, ampersand - index)); + index = ampersand + 1; + const auto consumed{ + decode_character_reference(output, input.substr(index))}; + if (consumed == 0) { + output.push_back('&'); + } else { + index += consumed; + } + + ampersand = input.find('&', index); + } + + output.append(input.substr(index)); + return true; +} + +// Resolve the backslash escapes of GFM section 2.4 and the character +// references of GFM section 6.5 in one pass from left to right, so that an +// escaped ampersand stays literal rather than opening a character reference, +// as GFM section 2.4 example 310 requires +inline auto decode_escapes_and_references(std::string &output, + const std::string_view input) + -> void { + const auto size{input.size()}; + std::size_t index{0}; + auto next{input.find_first_of("&\\")}; + while (next != std::string_view::npos) { + output.append(input.substr(index, next - index)); + index = next; + if (input[index] == '\\') { + if (index + 1 < size && + sourcemeta::core::is_punctuation(input[index + 1])) { + output.push_back(input[index + 1]); + index += 2; + } else { + output.push_back('\\'); + index += 1; + } + } else { + const auto consumed{ + decode_character_reference(output, input.substr(index + 1))}; + if (consumed == 0) { + output.push_back('&'); + index += 1; + } else { + index += consumed + 1; + } + } + + next = input.find_first_of("&\\", index); + } + + output.append(input.substr(index)); +} + +// Normalise a link label as GFM section 4.7 describes, folding its case, +// trimming it, and collapsing every run of whitespace into a single space +inline auto normalize_label(std::string &output, const std::string_view label) + -> void { + output.clear(); + bool pending_space{false}; + std::size_t index{0}; + while (index < label.size()) { + const auto byte{static_cast(label[index])}; + if (byte < 0x80) { + if (is_whitespace_character(label[index])) { + pending_space = !output.empty(); + ++index; + continue; + } + + if (pending_space) { + output.push_back(' '); + pending_space = false; + } + + output.push_back(sourcemeta::core::to_lowercase(label[index])); + ++index; + continue; + } + + if (pending_space) { + output.push_back(' '); + pending_space = false; + } + + const auto decoded{sourcemeta::core::utf8_decode(label, index)}; + if (!decoded.has_value()) { + sourcemeta::core::codepoint_to_utf8(0xFFFD, output); + ++index; + continue; + } + + const auto [codepoint, length]{decoded.value()}; + const auto folded{sourcemeta::core::case_fold(codepoint)}; + if (folded.empty()) { + output.append(label.substr(index, length)); + } else { + for (const auto character : folded) { + sourcemeta::core::codepoint_to_utf8(character, output); + } + } + + index += length; + } +} + +} // namespace sourcemeta::core::markdown + +#endif diff --git a/vendor/core/src/core/markdown/document.h b/vendor/core/src/core/markdown/document.h new file mode 100644 index 000000000..89aa6228e --- /dev/null +++ b/vendor/core/src/core/markdown/document.h @@ -0,0 +1,278 @@ +#ifndef SOURCEMETA_CORE_MARKDOWN_DOCUMENT_H_ +#define SOURCEMETA_CORE_MARKDOWN_DOCUMENT_H_ + +#include // std::max +#include // std::size_t +#include // std::int32_t, std::uint8_t, std::uint16_t, std::uint32_t +#include // std::memcpy +#include // std::string +#include // std::string_view +#include // std::unordered_map +#include // std::vector + +namespace sourcemeta::core::markdown { + +enum class NodeType : std::uint8_t { + Document, + BlockQuote, + List, + Item, + CodeBlock, + HTMLBlock, + Paragraph, + Heading, + ThematicBreak, + FootnoteDefinition, + Table, + TableRow, + TableCell, + Text, + SoftBreak, + LineBreak, + Code, + HTMLInline, + Emphasis, + Strong, + Link, + Image, + FootnoteReference, + Strikethrough +}; + +constexpr std::uint32_t NO_NODE{0xFFFFFFFF}; +constexpr std::uint32_t ROOT_NODE{0}; + +constexpr std::uint16_t FLAG_OPEN{1U << 0U}; +constexpr std::uint16_t FLAG_LAST_LINE_BLANK{1U << 1U}; +constexpr std::uint16_t FLAG_LAST_LINE_CHECKED{1U << 2U}; +constexpr std::uint16_t FLAG_TABLE_VISITED{1U << 3U}; +constexpr std::uint16_t FLAG_TASK{1U << 4U}; +constexpr std::uint16_t FLAG_CHECKED{1U << 5U}; +constexpr std::uint16_t FLAG_HEADER{1U << 6U}; +constexpr std::uint16_t FLAG_FENCED{1U << 7U}; +constexpr std::uint16_t FLAG_SETEXT{1U << 8U}; +constexpr std::uint16_t FLAG_TIGHT{1U << 9U}; +constexpr std::uint16_t FLAG_REFERENCED{1U << 10U}; +constexpr std::uint16_t FLAG_ATTACHED{1U << 11U}; +constexpr std::uint16_t FLAG_DETACHED{1U << 12U}; +constexpr std::uint16_t FLAG_REFERENCE_LINK{1U << 13U}; + +// A block or inline element, whose generic fields mean different things for +// different types of nodes, such as the fence of a code block or the numbering +// of a footnote +struct Node { + std::string_view literal; + std::string_view title; + std::uint32_t parent{NO_NODE}; + std::uint32_t first_child{NO_NODE}; + std::uint32_t last_child{NO_NODE}; + std::uint32_t previous{NO_NODE}; + std::uint32_t next{NO_NODE}; + std::uint32_t content_offset{0}; + std::uint32_t content_length{0}; + std::uint32_t data{0}; + std::uint32_t extra{0}; + std::uint16_t flags{0}; + NodeType type{NodeType::Document}; + std::uint8_t level{0}; +}; + +inline auto has_flag(const Node &node, const std::uint16_t flag) noexcept + -> bool { + return (node.flags & flag) != 0; +} + +inline auto set_flag(Node &node, const std::uint16_t flag, + const bool value) noexcept -> void { + node.flags = value ? static_cast(node.flags | flag) + : static_cast(node.flags & ~flag); +} + +struct ListData { + std::int32_t start{0}; + std::int32_t marker_offset{0}; + std::int32_t padding{0}; + std::int32_t start_line{0}; + char bullet_character{0}; + char delimiter{0}; + bool ordered{false}; +}; + +struct TableData { + std::uint32_t alignments_offset{0}; + std::uint32_t columns{0}; + std::int64_t rows{0}; + std::int64_t nonempty_cells{0}; +}; + +struct Reference { + std::string_view url; + std::string_view title; +}; + +// Strings that stay at the same address until the arena is cleared +class StringArena { +public: + auto clear() -> void { + if (this->blocks_.empty()) { + return; + } + + if (this->blocks_.size() > 1) { + this->blocks_.erase(this->blocks_.begin() + 1, this->blocks_.end()); + } + + this->cursor_ = this->blocks_.front().data(); + this->remaining_ = this->blocks_.front().size(); + } + + auto allocate(const std::size_t size) -> char * { + if (this->remaining_ < size) [[unlikely]] { + const auto capacity{std::max(size, BLOCK_SIZE)}; + this->blocks_.emplace_back(capacity, '\0'); + this->cursor_ = this->blocks_.back().data(); + this->remaining_ = capacity; + } + + auto *const result{this->cursor_}; + this->cursor_ += size; + this->remaining_ -= size; + return result; + } + + auto store(const std::string_view value) -> std::string_view { + if (value.empty()) { + return {}; + } + + auto *const target{this->allocate(value.size())}; + std::memcpy(target, value.data(), value.size()); + return {target, value.size()}; + } + +private: + static constexpr std::size_t BLOCK_SIZE{16384}; + std::vector blocks_; + char *cursor_{nullptr}; + std::size_t remaining_{0}; +}; + +struct Document { + auto clear() -> void { + this->nodes.clear(); + this->content.clear(); + this->strings.clear(); + this->lists.clear(); + this->tables.clear(); + this->alignments.clear(); + this->references.clear(); + this->reference_size_limit = 0; + this->footnote_definition_nodes.clear(); + this->footnote_reference_nodes.clear(); + this->nested_footnote_definitions = false; + this->nodes.emplace_back().flags = FLAG_OPEN; + } + + auto create(const NodeType type) -> std::uint32_t { + const auto index{static_cast(this->nodes.size())}; + this->nodes.emplace_back().type = type; + return index; + } + + [[nodiscard]] auto content_of(const Node &node) const -> std::string_view { + return std::string_view{this->content}.substr(node.content_offset, + node.content_length); + } + + auto append_child(const std::uint32_t parent, const std::uint32_t child) + -> void { + auto &parent_node{this->nodes[parent]}; + auto &child_node{this->nodes[child]}; + child_node.parent = parent; + child_node.next = NO_NODE; + child_node.previous = parent_node.last_child; + if (parent_node.last_child == NO_NODE) { + parent_node.first_child = child; + } else { + this->nodes[parent_node.last_child].next = child; + } + + parent_node.last_child = child; + } + + auto unlink(const std::uint32_t index) -> void { + auto &node{this->nodes[index]}; + if (node.previous != NO_NODE) { + this->nodes[node.previous].next = node.next; + } + + if (node.next != NO_NODE) { + this->nodes[node.next].previous = node.previous; + } + + if (node.parent != NO_NODE) { + auto &parent{this->nodes[node.parent]}; + if (parent.first_child == index) { + parent.first_child = node.next; + } + + if (parent.last_child == index) { + parent.last_child = node.previous; + } + } + + node.parent = NO_NODE; + node.previous = NO_NODE; + node.next = NO_NODE; + } + + auto insert_before(const std::uint32_t index, const std::uint32_t sibling) + -> void { + this->unlink(sibling); + auto &node{this->nodes[index]}; + auto &sibling_node{this->nodes[sibling]}; + sibling_node.parent = node.parent; + sibling_node.next = index; + sibling_node.previous = node.previous; + if (node.previous != NO_NODE) { + this->nodes[node.previous].next = sibling; + } else if (node.parent != NO_NODE) { + this->nodes[node.parent].first_child = sibling; + } + + node.previous = sibling; + } + + auto insert_after(const std::uint32_t index, const std::uint32_t sibling) + -> void { + this->unlink(sibling); + auto &node{this->nodes[index]}; + auto &sibling_node{this->nodes[sibling]}; + sibling_node.parent = node.parent; + sibling_node.previous = index; + sibling_node.next = node.next; + if (node.next != NO_NODE) { + this->nodes[node.next].previous = sibling; + } else if (node.parent != NO_NODE) { + this->nodes[node.parent].last_child = sibling; + } + + node.next = sibling; + } + + std::vector nodes; + std::string content; + StringArena strings; + std::vector lists; + std::vector tables; + std::vector alignments; + std::unordered_map references; + std::size_t reference_size_limit{0}; + std::vector footnote_definition_nodes; + std::vector footnote_reference_nodes; + bool nested_footnote_definitions{false}; +}; + +} // namespace sourcemeta::core::markdown + +#endif diff --git a/vendor/core/src/core/markdown/include/sourcemeta/core/markdown.h b/vendor/core/src/core/markdown/include/sourcemeta/core/markdown.h index 910b207d2..6901d12eb 100644 --- a/vendor/core/src/core/markdown/include/sourcemeta/core/markdown.h +++ b/vendor/core/src/core/markdown/include/sourcemeta/core/markdown.h @@ -5,6 +5,10 @@ #include #endif +// NOLINTBEGIN(misc-include-cleaner) +#include +// NOLINTEND(misc-include-cleaner) + #include // std::string #include // std::string_view @@ -27,7 +31,11 @@ namespace sourcemeta::core { /// links are suppressed by default, so the result is safe to render from /// untrusted input. Passing a false safe argument lets raw HTML and unsafe /// links pass through unchanged, which must only be done for trusted input. -/// For example: +/// The specification lets link references and short table rows expand to an +/// output far larger than the input, so the conversion throws `MarkdownError` +/// once the rendered link references expand past the larger of 16 times the +/// input size and 1,048,576 bytes, or once a table inserts more than 524,288 +/// empty cells. For example: /// /// ```cpp /// #include diff --git a/vendor/core/src/core/markdown/include/sourcemeta/core/markdown_error.h b/vendor/core/src/core/markdown/include/sourcemeta/core/markdown_error.h new file mode 100644 index 000000000..9d6b2dd78 --- /dev/null +++ b/vendor/core/src/core/markdown/include/sourcemeta/core/markdown_error.h @@ -0,0 +1,47 @@ +#ifndef SOURCEMETA_CORE_MARKDOWN_ERROR_H_ +#define SOURCEMETA_CORE_MARKDOWN_ERROR_H_ + +#ifndef SOURCEMETA_CORE_MARKDOWN_EXPORT +#include +#endif + +#include // std::exception +#include // std::string +#include // std::string_view + +namespace sourcemeta::core { + +// Exporting symbols that depends on the standard C++ library is considered +// safe. +// https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-2-c4275?view=msvc-170&redirectedfrom=MSDN +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4251 4275) +#endif + +/// @ingroup markdown +/// An error that represents a Markdown conversion that would exceed one of the +/// bounds on the size of its output +class SOURCEMETA_CORE_MARKDOWN_EXPORT MarkdownError : public std::exception { +public: + /// Construct an error with the given message + MarkdownError(const char *message) : message_{message} {} + MarkdownError(std::string message) = delete; + MarkdownError(std::string &&message) = delete; + MarkdownError(std::string_view message) = delete; + + [[nodiscard]] auto what() const noexcept -> const char * override { + return this->message_; + } + +private: + const char *message_; +}; + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +} // namespace sourcemeta::core + +#endif diff --git a/vendor/core/src/core/markdown/inlines.h b/vendor/core/src/core/markdown/inlines.h new file mode 100644 index 000000000..4b893b3ca --- /dev/null +++ b/vendor/core/src/core/markdown/inlines.h @@ -0,0 +1,1244 @@ +#ifndef SOURCEMETA_CORE_MARKDOWN_INLINES_H_ +#define SOURCEMETA_CORE_MARKDOWN_INLINES_H_ + +#include +#include + +#include "characters.h" +#include "document.h" +#include "references.h" +#include "scanners.h" + +#include // std::min +#include // std::array +#include // std::size_t, std::ptrdiff_t +#include // std::uint8_t, std::uint32_t +#include // std::memchr +#include // std::less +#include // std::string +#include // std::string_view +#include // std::vector + +namespace sourcemeta::core::markdown { + +constexpr std::uint32_t NO_DELIMITER{0xFFFFFFFF}; + +constexpr std::uint8_t SKIP_HTML_CDATA{1U << 0U}; +constexpr std::uint8_t SKIP_HTML_DECLARATION{1U << 1U}; +constexpr std::uint8_t SKIP_HTML_PROCESSING_INSTRUCTION{1U << 2U}; + +// The bytes that may start an inline other than plain text, which are the +// line endings, the backslash, the backtick, the ampersand, the angle bracket, +// the emphasis and strikethrough delimiters, the brackets and the exclamation +// mark, and the colon and the letter that may start an extended autolink +constexpr std::array INLINE_SPECIAL{{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, // 0x00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 + 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, // 0x20 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, // 0x30 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, // 0x50 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60 + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, // 0x70 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xB0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xD0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xF0 +}}; + +struct Delimiter { + std::uint32_t previous{NO_DELIMITER}; + std::uint32_t next{NO_DELIMITER}; + std::uint32_t text{NO_NODE}; + std::size_t position{0}; + std::size_t length{0}; + char character{0}; + bool can_open{false}; + bool can_close{false}; +}; + +struct Bracket { + std::uint32_t text{NO_NODE}; + std::size_t position{0}; + std::ptrdiff_t start_column{0}; + bool image{false}; + bool bracket_after{false}; +}; + +// A character of a segment of a valid domain of GFM section 6.9, which +// "consists of segments of alphanumeric characters, underscores (_) and hyphens +// (-) separated by periods (.)", where alphanumeric characters are ASCII as +// the whitespace characters of GFM section 2.1 are, which the specification +// only extends to Unicode when it says so +inline auto is_domain_character(const char character) noexcept -> bool { + return sourcemeta::core::is_alphanum(character) || character == '_' || + character == '-'; +} + +// GFM section 6.9: "All such recognized autolinks can only come at the +// beginning of a line, after whitespace, or any of the delimiting characters +// *, _, ~, and (" +inline auto may_precede_extended_autolink(const char character) noexcept + -> bool { + return is_whitespace_character(character) || character == '*' || + character == '_' || character == '~' || character == '('; +} + +// The end of an extended autolink once its trailing punctuation, unbalanced +// parentheses, and entity references are removed as GFM section 6.9 describes +inline auto trim_autolink_end(const std::string_view data, + std::size_t link_end) noexcept -> std::size_t { + std::size_t opening{0}; + std::size_t closing{0}; + for (std::size_t index{0}; index < link_end; ++index) { + const auto character{data[index]}; + if (character == '<') { + link_end = index; + break; + } + + if (character == '(') { + ++opening; + } else if (character == ')') { + ++closing; + } + } + + while (link_end > 0) { + switch (data[link_end - 1]) { + case ')': + if (closing <= opening) { + return link_end; + } + + --closing; + --link_end; + break; + // GFM section 6.9: "Trailing punctuation (specifically, ?, !, ., ,, :, + // *, _, and ~) will not be considered part of the autolink" + case '?': + case '!': + case '.': + case ',': + case ':': + case '*': + case '_': + case '~': + --link_end; + break; + case ';': { + if (link_end < 2) { + --link_end; + break; + } + + // GFM section 6.9 only excludes a semicolon from an autolink along + // with an entity reference lookalike, which is "& followed by one or + // more alphanumeric characters" + auto entity_start{link_end - 2}; + while (entity_start > 0 && + sourcemeta::core::is_alphanum(data[entity_start])) { + --entity_start; + } + + if (entity_start < link_end - 2 && data[entity_start] == '&') { + link_end = entity_start; + break; + } + + return link_end; + } + + default: + return link_end; + } + } + + return link_end; +} + +// Whether the lengths of the delimiter runs of an opener and a closer of the +// same character let them match. GFM section 6.5 wraps strikethrough text in +// "a matching pair of one or two tildes", while GFM section 6.4 says that "If +// one of the delimiters can both open and close emphasis, then the sum of the +// lengths of the delimiter runs containing the opening and closing delimiters +// must not be a multiple of 3 unless both lengths are multiples of 3" +inline auto delimiter_lengths_match(const Delimiter &opener, + const Delimiter &closer) noexcept -> bool { + if (closer.character == '~') { + return opener.length == closer.length; + } + + return !(closer.can_open || opener.can_close) || closer.length % 3 == 0 || + (opener.length + closer.length) % 3 != 0; +} + +// The inlines of GFM section 6 and of the strikethrough and autolink +// extensions +class InlineParser { +public: + explicit InlineParser(Document &document) : document_{document} {} + + auto parse(const std::uint32_t parent) -> void { + this->parent_ = parent; + this->input_ = sourcemeta::core::strip_right( + this->document_.content_of(this->document_.nodes[parent]), is_space); + this->position_ = 0; + this->column_offset_ = 0; + this->last_delimiter_ = NO_DELIMITER; + this->delimiters_.clear(); + this->brackets_.clear(); + this->backticks_.clear(); + this->scanned_for_backticks_ = false; + this->rejected_domain_start_ = 0; + this->rejected_domain_limit_ = 0; + this->last_link_opener_position_ = 0; + this->flags_ = 0; + while (this->position_ < this->input_.size()) { + this->parse_inline(); + } + + this->process_emphasis(0); + } + +private: + auto node(const std::uint32_t index) -> Node & { + return this->document_.nodes[index]; + } + + [[nodiscard]] auto peek() const noexcept -> char { + return character_at(this->input_, this->position_); + } + + auto append(const NodeType type, const std::string_view literal) + -> std::uint32_t { + const auto index{this->document_.create(type)}; + this->node(index).literal = literal; + this->document_.append_child(this->parent_, index); + return index; + } + + auto append_text_child(const std::uint32_t parent, + const std::string_view literal) -> void { + const auto index{this->document_.create(NodeType::Text)}; + this->node(index).literal = literal; + this->document_.append_child(parent, index); + } + + auto parse_inline() -> void { + const auto character{this->input_[this->position_]}; + switch (character) { + case '\n': + case '\r': + this->handle_newline(); + return; + case '`': + this->handle_backticks(); + return; + case '\\': + this->handle_backslash(); + return; + case '&': + this->handle_entity(); + return; + case '<': + this->handle_pointy_brace(); + return; + case '*': + case '_': + this->handle_delimiter(character); + return; + case '\'': + case '"': + case '-': + case '.': + this->append(NodeType::Text, this->input_.substr(this->position_, 1)); + ++this->position_; + return; + case '[': + ++this->position_; + this->push_bracket( + false, this->append(NodeType::Text, + this->input_.substr(this->position_ - 1, 1))); + return; + case ']': + this->handle_close_bracket(); + return; + case '!': + this->handle_bang(); + return; + case '~': + this->handle_tilde(); + return; + default: + break; + } + + if (character == ':' && this->match_url_autolink()) { + return; + } + + if (character == 'w' && this->match_www_autolink()) { + return; + } + + const auto end{this->find_special_character(this->position_ + 1)}; + auto contents{this->input_.substr(this->position_, end - this->position_)}; + this->position_ = end; + if (end < this->input_.size() && is_line_end(this->input_[end])) { + contents = sourcemeta::core::strip_right(contents, is_space); + } + + this->append(NodeType::Text, contents); + } + + // Extended autolinks do not start inside brackets that may turn into link + // text. GFM section 6.6 says that autolinks "bind more tightly than the + // brackets in link text", but the path of an extended autolink of GFM + // section 6.9 takes "zero or more non-space non-< characters", so it would + // take the rest of a link such as [www.example.com](/x) along with it + [[nodiscard]] auto + may_start_www_autolink(const std::size_t index) const noexcept -> bool { + if (!this->brackets_.empty()) { + return false; + } + + if (index > 0 && !may_precede_extended_autolink(this->input_[index - 1])) { + return false; + } + + return this->input_.substr(index, 4) == "www."; + } + + [[nodiscard]] auto + may_start_url_autolink(const std::size_t index) const noexcept -> bool { + return this->brackets_.empty() && index + 3 < this->input_.size() && + this->input_[index + 1] == '/' && this->input_[index + 2] == '/'; + } + + [[nodiscard]] auto + find_special_character(const std::size_t from) const noexcept -> std::size_t { + const auto size{this->input_.size()}; + for (auto index{from}; index < size; ++index) { + const auto character{this->input_[index]}; + if (INLINE_SPECIAL[static_cast(character)] == 0) { + continue; + } + + if ((character == 'w' && !this->may_start_www_autolink(index)) || + (character == ':' && !this->may_start_url_autolink(index))) { + continue; + } + + return index; + } + + return size; + } + + auto handle_newline() -> void { + const auto newline_position{this->position_}; + if (this->input_[this->position_] == '\r') { + ++this->position_; + } + + if (this->peek() == '\n') { + ++this->position_; + } + + this->column_offset_ = -static_cast(this->position_); + skip_spaces(this->input_, this->position_); + if (newline_position > 1 && this->input_[newline_position - 1] == ' ' && + this->input_[newline_position - 2] == ' ') { + this->append(NodeType::LineBreak, {}); + } else { + this->append(NodeType::SoftBreak, {}); + } + } + + auto scan_to_closing_backticks(const std::size_t opening_length) + -> std::size_t { + // GFM section 6.3 puts no bound on the length of a backtick string. Once + // the rest of the input was scanned, the last position of every backtick + // string length is known, so an opening backtick string without a closing + // one of the same length after it is rejected without scanning again + if (this->scanned_for_backticks_ && + (opening_length >= this->backticks_.size() || + this->backticks_[opening_length] <= this->position_)) { + return 0; + } + + const auto size{this->input_.size()}; + while (this->position_ < size) { + const auto *const found{static_cast(std::memchr( + this->input_.data() + this->position_, '`', size - this->position_))}; + if (found == nullptr) { + this->position_ = size; + break; + } + + this->position_ = static_cast(found - this->input_.data()); + std::size_t count{0}; + while (this->position_ < size && this->input_[this->position_] == '`') { + ++this->position_; + ++count; + } + + if (count >= this->backticks_.size()) { + this->backticks_.resize(count + 1, 0); + } + + // A scan that starts after a complete one must not replace the last + // position of a backtick string length with an earlier one + this->backticks_[count] = + std::max(this->backticks_[count], this->position_ - count); + + if (count == opening_length) { + return this->position_; + } + } + + this->scanned_for_backticks_ = true; + return 0; + } + + // The content of a code span of GFM section 6.3: "First, line endings are + // converted to spaces. If the resulting string both begins and ends with a + // space character, but does not consist entirely of space characters, a + // single space character is removed from the front and back" + auto normalize_code(const std::string_view raw) -> std::string_view { + if (raw.find_first_of("\r\n") == std::string_view::npos) { + if (raw.size() >= 2 && raw.front() == ' ' && raw.back() == ' ' && + raw.find_first_not_of(' ') != std::string_view::npos) { + return raw.substr(1, raw.size() - 2); + } + + return raw; + } + + auto &buffer{this->buffer_}; + buffer.assign(raw); + const auto size{buffer.size()}; + std::size_t write{0}; + bool contains_nonspace{false}; + for (std::size_t read{0}; read < size; ++read) { + const auto character{buffer[read]}; + if (character == '\r') { + if (read + 1 >= size || buffer[read + 1] != '\n') { + buffer[write] = ' '; + ++write; + } + } else if (character == '\n') { + buffer[write] = ' '; + ++write; + } else { + buffer[write] = character; + ++write; + if (character != ' ') { + contains_nonspace = true; + } + } + } + + if (contains_nonspace && write >= 2 && buffer[0] == ' ' && + buffer[write - 1] == ' ') { + return this->document_.strings.store( + std::string_view{buffer}.substr(1, write - 2)); + } + + return this->document_.strings.store( + std::string_view{buffer}.substr(0, write)); + } + + auto handle_backticks() -> void { + const auto start{this->position_}; + while (this->peek() == '`') { + ++this->position_; + } + + const auto opening_length{this->position_ - start}; + const auto content_start{this->position_}; + const auto end{this->scan_to_closing_backticks(opening_length)}; + if (end == 0) { + this->position_ = content_start; + this->append(NodeType::Text, this->input_.substr(start, opening_length)); + return; + } + + this->append(NodeType::Code, + this->normalize_code(this->input_.substr( + content_start, end - content_start - opening_length))); + } + + auto handle_backslash() -> void { + ++this->position_; + const auto next{this->peek()}; + if (sourcemeta::core::is_punctuation(next)) { + ++this->position_; + this->append(NodeType::Text, this->input_.substr(this->position_ - 1, 1)); + return; + } + + if (next == '\r' || next == '\n') { + skip_line_end(this->input_, this->position_); + this->append(NodeType::LineBreak, {}); + return; + } + + this->append(NodeType::Text, "\\"); + } + + auto handle_entity() -> void { + ++this->position_; + this->buffer_.clear(); + const auto consumed{decode_character_reference( + this->buffer_, this->input_.substr(this->position_))}; + if (consumed == 0) { + this->append(NodeType::Text, this->input_.substr(this->position_ - 1, 1)); + return; + } + + this->position_ += consumed; + this->append(NodeType::Text, this->document_.strings.store(this->buffer_)); + } + + auto make_autolink(const std::string_view contents, const bool is_email) + -> void { + const auto trimmed{sourcemeta::core::trim(contents, is_space)}; + const auto link{this->append(NodeType::Link, {})}; + if (!trimmed.empty()) { + this->buffer_.clear(); + if (is_email) { + this->buffer_.append("mailto:"); + } + + if (!decode_character_references(this->buffer_, trimmed)) { + this->buffer_.append(trimmed); + } + + this->node(link).literal = this->document_.strings.store(this->buffer_); + } + + this->buffer_.clear(); + this->append_text_child(link, + decode_character_references(this->buffer_, trimmed) + ? this->document_.strings.store(this->buffer_) + : trimmed); + } + + auto scan_raw_html() -> std::size_t { + const auto size{this->input_.size()}; + const auto position{this->position_}; + if (position + 2 > size) { + return 0; + } + + const auto character{this->input_[position]}; + if (character == '!') { + const auto next{this->input_[position + 1]}; + if (next == '-' && character_at(this->input_, position + 2) == '-') { + const auto length{scan_html_comment(this->input_, position + 1)}; + return length > 0 ? length + 1 : 0; + } + + if (next == '[') { + if ((this->flags_ & SKIP_HTML_CDATA) != 0) { + return 0; + } + + const auto length{scan_html_cdata(this->input_, position + 2)}; + if (length == 0) { + return 0; + } + + if (position + length + 5 > size) { + this->flags_ |= SKIP_HTML_CDATA; + return 0; + } + + return length + 5; + } + + if ((this->flags_ & SKIP_HTML_DECLARATION) != 0) { + return 0; + } + + const auto length{scan_html_declaration(this->input_, position + 1)}; + if (length == 0) { + return 0; + } + + if (position + length + 2 > size) { + this->flags_ |= SKIP_HTML_DECLARATION; + return 0; + } + + return length + 2; + } + + if (character == '?') { + if ((this->flags_ & SKIP_HTML_PROCESSING_INSTRUCTION) != 0) { + return 0; + } + + const auto length{ + scan_html_processing_instruction(this->input_, position + 1) + 3}; + if (position + length > size) { + this->flags_ |= SKIP_HTML_PROCESSING_INSTRUCTION; + return 0; + } + + return length; + } + + return scan_html_tag(this->input_, position); + } + + auto handle_pointy_brace() -> void { + ++this->position_; + auto length{scan_autolink_uri(this->input_, this->position_)}; + if (length > 0) { + const auto contents{this->input_.substr(this->position_, length - 1)}; + this->position_ += length; + this->make_autolink(contents, false); + return; + } + + length = scan_autolink_email(this->input_, this->position_); + if (length > 0) { + const auto contents{this->input_.substr(this->position_, length - 1)}; + this->position_ += length; + this->make_autolink(contents, true); + return; + } + + length = this->scan_raw_html(); + if (length > 0) { + const auto contents{this->input_.substr(this->position_ - 1, length + 1)}; + this->position_ += length; + this->append(NodeType::HTMLInline, contents); + return; + } + + this->append(NodeType::Text, this->input_.substr(this->position_ - 1, 1)); + } + + // The characters around a delimiter run of GFM section 6.4, where "the + // beginning and the end of the line count as Unicode whitespace" + [[nodiscard]] auto character_before_delimiters() const noexcept -> char32_t { + if (this->position_ == 0) { + return U'\n'; + } + + auto index{this->position_ - 1}; + while (index > 0 && sourcemeta::core::is_utf8_continuation( + static_cast(this->input_[index]))) { + --index; + } + + const auto preceding{sourcemeta::core::utf8_decode( + this->input_.substr(index, this->position_ - index), 0)}; + return preceding.has_value() ? preceding->first : U'\n'; + } + + [[nodiscard]] auto character_after_delimiters() const noexcept -> char32_t { + const auto following{ + sourcemeta::core::utf8_decode(this->input_, this->position_)}; + return following.has_value() ? following->first : U'\n'; + } + + auto handle_delimiter(const char character) -> void { + const auto before{this->character_before_delimiters()}; + const auto start{this->position_}; + while (this->peek() == character) { + ++this->position_; + } + + const auto count{this->position_ - start}; + const auto after{this->character_after_delimiters()}; + const auto space_before{is_unicode_whitespace(before)}; + const auto space_after{is_unicode_whitespace(after)}; + const auto punctuation_before{is_unicode_punctuation(before)}; + const auto punctuation_after{is_unicode_punctuation(after)}; + const auto left_flanking{ + !space_after && + (!punctuation_after || space_before || punctuation_before)}; + const auto right_flanking{ + !space_before && + (!punctuation_before || space_after || punctuation_after)}; + bool can_open{left_flanking}; + bool can_close{right_flanking}; + if (character == '_') { + can_open = left_flanking && (!right_flanking || punctuation_before); + can_close = right_flanking && (!left_flanking || punctuation_after); + } + + const auto text{ + this->append(NodeType::Text, this->input_.substr(start, count))}; + if (can_open || can_close) { + this->push_delimiter(character, can_open, can_close, text); + } + } + + // GFM section 6.5: "Strikethrough text is any text wrapped in a matching pair + // of one or two tildes (~)", and "Three or more tildes do not create a + // strikethrough" + auto handle_tilde() -> void { + const auto before{this->character_before_delimiters()}; + const auto start{this->position_}; + while (this->peek() == '~') { + ++this->position_; + } + + const auto count{this->position_ - start}; + const auto after{this->character_after_delimiters()}; + const auto space_before{is_unicode_whitespace(before)}; + const auto space_after{is_unicode_whitespace(after)}; + const auto punctuation_before{is_unicode_punctuation(before)}; + const auto punctuation_after{is_unicode_punctuation(after)}; + const auto left_flanking{ + !space_after && + (!punctuation_after || space_before || punctuation_before)}; + const auto right_flanking{ + !space_before && + (!punctuation_before || space_after || punctuation_after)}; + const auto text{ + this->append(NodeType::Text, this->input_.substr(start, count))}; + if ((left_flanking || right_flanking) && count <= 2) { + this->push_delimiter('~', left_flanking, right_flanking, text); + } + } + + auto handle_bang() -> void { + ++this->position_; + if (this->peek() == '[' && + character_at(this->input_, this->position_ + 1) != '^') { + ++this->position_; + this->push_bracket( + true, this->append(NodeType::Text, + this->input_.substr(this->position_ - 2, 2))); + return; + } + + this->append(NodeType::Text, this->input_.substr(this->position_ - 1, 1)); + } + + auto push_delimiter(const char character, const bool can_open, + const bool can_close, const std::uint32_t text) -> void { + const auto index{static_cast(this->delimiters_.size())}; + this->delimiters_.push_back({.previous = this->last_delimiter_, + .next = NO_DELIMITER, + .text = text, + .position = this->position_, + .length = this->node(text).literal.size(), + .character = character, + .can_open = can_open, + .can_close = can_close}); + if (this->last_delimiter_ != NO_DELIMITER) { + this->delimiters_[this->last_delimiter_].next = index; + } + + this->last_delimiter_ = index; + } + + auto remove_delimiter(const std::uint32_t index) -> void { + const auto &delimiter{this->delimiters_[index]}; + if (delimiter.next == NO_DELIMITER) { + this->last_delimiter_ = delimiter.previous; + } else { + this->delimiters_[delimiter.next].previous = delimiter.previous; + } + + if (delimiter.previous != NO_DELIMITER) { + this->delimiters_[delimiter.previous].next = delimiter.next; + } + } + + auto push_bracket(const bool image, const std::uint32_t text) -> void { + if (!this->brackets_.empty()) { + this->brackets_.back().bracket_after = true; + } + + const auto position{static_cast(this->position_)}; + this->brackets_.push_back( + {.text = text, + .position = this->position_, + .start_column = + (image ? position - 1 : position) + this->column_offset_, + .image = image, + .bracket_after = false}); + } + + static auto delimiter_index(const char character) noexcept -> std::size_t { + if (character == '*') { + return 0; + } + + return character == '_' ? 1 : 2; + } + + // Move the inlines between two siblings into a new parent that takes the + // place right after the first sibling + auto wrap_between(const std::uint32_t first, const std::uint32_t last, + const std::uint32_t wrapper) -> void { + auto current{this->node(first).next}; + while (current != NO_NODE && current != last) { + const auto next{this->node(current).next}; + this->document_.unlink(current); + this->document_.append_child(wrapper, current); + current = next; + } + } + + auto insert_emphasis(const std::uint32_t opener, std::uint32_t closer) + -> std::uint32_t { + const auto opener_text{this->delimiters_[opener].text}; + const auto closer_text{this->delimiters_[closer].text}; + auto opener_characters{this->node(opener_text).literal.size()}; + auto closer_characters{this->node(closer_text).literal.size()}; + const std::size_t used{ + closer_characters >= 2 && opener_characters >= 2 ? 2U : 1U}; + opener_characters -= used; + closer_characters -= used; + this->node(opener_text).literal = + this->node(opener_text).literal.substr(0, opener_characters); + this->node(closer_text).literal = + this->node(closer_text).literal.substr(0, closer_characters); + + auto between{this->delimiters_[closer].previous}; + while (between != NO_DELIMITER && between != opener) { + const auto previous{this->delimiters_[between].previous}; + this->remove_delimiter(between); + between = previous; + } + + const auto emphasis{this->document_.create(used == 1 ? NodeType::Emphasis + : NodeType::Strong)}; + this->wrap_between(opener_text, closer_text, emphasis); + this->document_.insert_after(opener_text, emphasis); + if (opener_characters == 0) { + this->document_.unlink(opener_text); + this->remove_delimiter(opener); + } + + if (closer_characters == 0) { + this->document_.unlink(closer_text); + const auto next{this->delimiters_[closer].next}; + this->remove_delimiter(closer); + closer = next; + } + + return closer; + } + + auto insert_strikethrough(const std::uint32_t opener, + const std::uint32_t closer) -> std::uint32_t { + const auto result{this->delimiters_[closer].next}; + const auto opener_text{this->delimiters_[opener].text}; + const auto closer_text{this->delimiters_[closer].text}; + this->node(opener_text).type = NodeType::Strikethrough; + this->node(opener_text).literal = {}; + this->wrap_between(opener_text, closer_text, opener_text); + this->document_.unlink(closer_text); + + auto current{closer}; + while (current != NO_DELIMITER && current != opener) { + const auto previous{this->delimiters_[current].previous}; + this->remove_delimiter(current); + current = previous; + } + + this->remove_delimiter(opener); + return result; + } + + auto process_emphasis(const std::size_t stack_bottom) -> void { + std::array, 3> openers_bottom{}; + for (auto &row : openers_bottom) { + row.fill(stack_bottom); + } + + auto closer{NO_DELIMITER}; + auto candidate{this->last_delimiter_}; + while (candidate != NO_DELIMITER && + this->delimiters_[candidate].position >= stack_bottom) { + closer = candidate; + candidate = this->delimiters_[candidate].previous; + } + + while (closer != NO_DELIMITER) { + const auto closer_delimiter{this->delimiters_[closer]}; + if (!closer_delimiter.can_close) { + closer = closer_delimiter.next; + continue; + } + + const auto kind{delimiter_index(closer_delimiter.character)}; + const auto remainder{closer_delimiter.length % 3}; + auto opener{closer_delimiter.previous}; + bool opener_found{false}; + while (opener != NO_DELIMITER && + this->delimiters_[opener].position >= stack_bottom && + this->delimiters_[opener].position >= + openers_bottom[remainder][kind]) { + const auto &opener_delimiter{this->delimiters_[opener]}; + if (opener_delimiter.can_open && + opener_delimiter.character == closer_delimiter.character && + delimiter_lengths_match(opener_delimiter, closer_delimiter)) { + opener_found = true; + break; + } + + opener = opener_delimiter.previous; + } + + if (opener_found) { + closer = closer_delimiter.character == '~' + ? this->insert_strikethrough(opener, closer) + : this->insert_emphasis(opener, closer); + continue; + } + + openers_bottom[remainder][kind] = closer_delimiter.position; + const auto next{closer_delimiter.next}; + if (!closer_delimiter.can_open) { + this->remove_delimiter(closer); + } + + closer = next; + } + + while (this->last_delimiter_ != NO_DELIMITER && + this->delimiters_[this->last_delimiter_].position >= stack_bottom) { + this->remove_delimiter(this->last_delimiter_); + } + } + + auto handle_close_bracket() -> void { + ++this->position_; + const auto initial_position{this->position_}; + if (this->brackets_.empty()) { + this->append(NodeType::Text, this->input_.substr(this->position_ - 1, 1)); + return; + } + + const auto opener{this->brackets_.back()}; + // GFM section 6.6: "Links may not contain other links, at any level of + // nesting", so a bracket that opens before the latest link cannot close + // another one + if (!opener.image && opener.position < this->last_link_opener_position_) { + this->brackets_.pop_back(); + this->append(NodeType::Text, this->input_.substr(this->position_ - 1, 1)); + return; + } + + std::string_view url; + std::string_view title; + bool matched{false}; + bool from_reference{false}; + if (this->peek() == '(') { + const auto spaces{scan_spacechars(this->input_, this->position_ + 1)}; + std::string_view destination; + const auto destination_length{scan_link_destination( + this->input_, this->position_ + 1 + spaces, destination)}; + if (destination_length >= 0) { + const auto url_end{this->position_ + 1 + spaces + + static_cast(destination_length)}; + const auto title_start{url_end + + scan_spacechars(this->input_, url_end)}; + const auto title_end{ + title_start == url_end + ? title_start + : title_start + scan_link_title(this->input_, title_start)}; + const auto end{title_end + scan_spacechars(this->input_, title_end)}; + if (character_at(this->input_, end) == ')') { + this->position_ = end + 1; + url = clean_url(this->document_, destination, this->buffer_, true); + title = clean_title( + this->document_, + this->input_.substr(title_start, title_end - title_start), + this->buffer_, true); + matched = true; + } + } + } + + if (!matched) { + this->position_ = initial_position; + std::string_view label; + auto found_label{scan_link_label(this->input_, this->position_, label)}; + if ((!found_label || label.empty()) && !opener.bracket_after) { + label = this->input_.substr(opener.position, + initial_position - opener.position - 1); + found_label = true; + } + + const auto *const reference{ + found_label + ? find_reference(this->document_, label, this->label_buffer_) + : nullptr}; + if (reference != nullptr) { + url = reference->url; + title = reference->title; + matched = true; + from_reference = true; + } + } + + if (!matched) { + this->handle_unmatched_bracket(opener, initial_position); + return; + } + + const auto link{this->document_.create(opener.image ? NodeType::Image + : NodeType::Link)}; + this->node(link).literal = url; + this->node(link).title = title; + set_flag(this->node(link), FLAG_REFERENCE_LINK, from_reference); + this->document_.insert_before(opener.text, link); + this->wrap_between(opener.text, NO_NODE, link); + this->document_.unlink(opener.text); + this->process_emphasis(opener.position); + this->brackets_.pop_back(); + if (!opener.image) { + this->last_link_opener_position_ = + std::max(this->last_link_opener_position_, opener.position); + } + } + + // A bracket that is neither a link nor an image might still be a footnote + // reference, whose label is the text between its brackets + auto handle_unmatched_bracket(const Bracket &opener, + const std::size_t initial_position) -> void { + const auto after_opener{this->node(opener.text).next}; + if (after_opener != NO_NODE && + this->node(after_opener).type == NodeType::Text) { + const auto literal{this->node(after_opener).literal}; + if (!literal.empty() && literal.front() == '^' && + (literal.size() > 1 || this->node(after_opener).next != NO_NODE)) { + this->position_ = initial_position; + const auto end_column{static_cast(this->position_) + + this->column_offset_}; + const auto length{ + opener.start_column + 2 <= end_column + ? static_cast(end_column - opener.start_column - 2) + : std::size_t{0}}; + const auto *const label_start{literal.data() + 1}; + const auto *const input_start{this->input_.data()}; + const auto *const input_end{this->input_.data() + this->input_.size()}; + const std::less before{}; + const auto available{ + !before(label_start, input_start) && !before(input_end, label_start) + ? static_cast(input_end - label_start) + : literal.size() - 1}; + const auto reference{ + this->document_.create(NodeType::FootnoteReference)}; + this->document_.footnote_reference_nodes.push_back(reference); + this->node(reference).literal = + std::string_view{label_start, std::min(length, available)}; + this->document_.insert_before(opener.text, reference); + this->process_emphasis(opener.position); + auto current{this->node(opener.text).next}; + while (current != NO_NODE) { + const auto next{this->node(current).next}; + this->document_.unlink(current); + current = next; + } + + this->document_.unlink(opener.text); + this->brackets_.pop_back(); + return; + } + } + + this->brackets_.pop_back(); + this->position_ = initial_position; + this->append(NodeType::Text, this->input_.substr(this->position_ - 1, 1)); + } + + // GFM section 6.9: "An extended url autolink will be recognised when one of + // the schemes http://, or https://, followed by a valid domain", where RFC + // 3986 Section 3.1 says that "schemes are case-insensitive" + static auto + starts_with_extended_url_scheme(const std::string_view link) noexcept + -> bool { + for (const auto scheme : + std::array{{"http://", "https://"}}) { + if (link.size() > scheme.size() && + sourcemeta::core::starts_with_ignore_case(link, scheme) && + is_domain_character(link[scheme.size()])) { + return true; + } + } + + return false; + } + + // The length of the valid domain of GFM section 6.9 at a position of the + // input, or zero if there is none. "There must be at least one period, and + // no underscores may be present in the last two segments of the domain" + auto scan_autolink_domain(const std::size_t start) -> std::size_t { + // A later start within a domain that was rejected for its underscores has + // the same last two segments until the second to last period, so it is + // rejected without scanning the same characters again + if (start > this->rejected_domain_start_ && + start < this->rejected_domain_limit_) { + return 0; + } + + const auto data{this->input_.substr(start)}; + std::size_t index{0}; + std::size_t periods{0}; + std::size_t last_period{0}; + std::size_t second_to_last_period{0}; + std::size_t underscores_before_last_period{0}; + std::size_t underscores_after_last_period{0}; + for (; index < data.size(); ++index) { + const auto character{data[index]}; + if (character == '.') { + // The segments that periods separate have at least one character + if (index + 1 >= data.size() || !is_domain_character(data[index + 1])) { + break; + } + + underscores_before_last_period = underscores_after_last_period; + underscores_after_last_period = 0; + second_to_last_period = last_period; + last_period = index; + ++periods; + } else if (character == '_') { + ++underscores_after_last_period; + } else if (!is_domain_character(character)) { + break; + } + } + + if (underscores_before_last_period > 0 || + underscores_after_last_period > 0) { + if (periods >= 2) { + this->rejected_domain_start_ = start; + this->rejected_domain_limit_ = start + second_to_last_period; + } + + return 0; + } + + return periods > 0 ? index : 0; + } + + auto match_www_autolink() -> bool { + if (!this->may_start_www_autolink(this->position_)) { + return false; + } + + const auto data{this->input_.substr(this->position_)}; + auto link_end{this->scan_autolink_domain(this->position_)}; + if (link_end == 0) { + return false; + } + + while (link_end < data.size() && !is_space(data[link_end]) && + data[link_end] != '<') { + ++link_end; + } + + link_end = trim_autolink_end(data, link_end); + if (link_end == 0) { + return false; + } + + this->position_ += link_end; + this->buffer_.assign("http://"); + this->buffer_.append(data.substr(0, link_end)); + const auto link{this->append(NodeType::Link, + this->document_.strings.store(this->buffer_))}; + this->append_text_child(link, data.substr(0, link_end)); + return true; + } + + auto remove_trailing_text(std::size_t count) -> void { + auto index{this->node(this->parent_).last_child}; + while (count > 0 && index != NO_NODE && + this->node(index).type == NodeType::Text) { + auto &literal{this->node(index).literal}; + if (literal.size() < count) { + count -= literal.size(); + literal = literal.substr(0, 0); + } else { + literal = literal.substr(0, literal.size() - count); + count = 0; + } + + index = this->node(index).previous; + } + } + + auto match_url_autolink() -> bool { + if (!this->may_start_url_autolink(this->position_)) { + return false; + } + + const auto data{this->input_.substr(this->position_)}; + std::size_t rewind{0}; + while (rewind < this->position_ && + sourcemeta::core::is_alpha( + this->input_[this->position_ - rewind - 1])) { + ++rewind; + } + + const auto start{this->position_ - rewind}; + if ((start > 0 && + !may_precede_extended_autolink(this->input_[start - 1])) || + !starts_with_extended_url_scheme(this->input_.substr(start))) { + return false; + } + + const auto domain_length{this->scan_autolink_domain(this->position_ + 3)}; + if (domain_length == 0) { + return false; + } + + auto link_end{3 + domain_length}; + while (link_end < data.size() && !is_space(data[link_end]) && + data[link_end] != '<') { + ++link_end; + } + + link_end = trim_autolink_end(data, link_end); + if (link_end == 0) { + return false; + } + + this->position_ += link_end; + this->remove_trailing_text(rewind); + const auto url{this->input_.substr(start, link_end + rewind)}; + const auto link{this->append(NodeType::Link, url)}; + this->append_text_child(link, url); + return true; + } + + Document &document_; + std::uint32_t parent_{NO_NODE}; + std::string_view input_; + std::size_t position_{0}; + std::ptrdiff_t column_offset_{0}; + std::uint32_t last_delimiter_{NO_DELIMITER}; + std::vector delimiters_; + std::vector brackets_; + std::vector backticks_; + bool scanned_for_backticks_{false}; + std::size_t rejected_domain_start_{0}; + std::size_t rejected_domain_limit_{0}; + std::uint8_t flags_{0}; + std::string buffer_; + std::string label_buffer_; + std::size_t last_link_opener_position_{0}; +}; + +} // namespace sourcemeta::core::markdown + +#endif diff --git a/vendor/core/src/core/markdown/markdown.cc b/vendor/core/src/core/markdown/markdown.cc index a35ffc599..ae2584cb7 100644 --- a/vendor/core/src/core/markdown/markdown.cc +++ b/vendor/core/src/core/markdown/markdown.cc @@ -1,75 +1,95 @@ #include +#include #include -#include // cmark_gfm_core_extensions_ensure_registered -#include // cmark_find_syntax_extension, cmark_parser_attach_syntax_extension, cmark_parser_get_syntax_extensions -#include // cmark_parser_new, cmark_parser_feed, cmark_parser_finish, cmark_parser_free, cmark_render_html, cmark_node_free +#include "blocks.h" +#include "characters.h" +#include "document.h" +#include "inlines.h" +#include "postprocess.h" +#include "render.h" -#include // std::array #include // std::size_t -#include // std::free -#include // std::mutex, std::scoped_lock +#include // std::uint32_t +#include // std::numeric_limits +#include // std::optional #include // std::string #include // std::string_view -namespace sourcemeta::core { +namespace { -auto markdown_to_html(const std::string_view input, const bool safe) - -> std::string { - [[maybe_unused]] static const bool CMARK_INITIALIZED{ - (cmark_gfm_core_extensions_ensure_registered(), true)}; +// An input past this size gives up the state of its thread once it is done, +// so that an unusually large conversion does not hold on to the memory it +// needed for the rest of the life of the thread. Inputs this large are far +// past what documentation is made of, so paying for their buffers again is +// better than keeping them around +constexpr std::size_t MAXIMUM_RETAINED_INPUT{0x800000}; - // Byte sequences that are not UTF-8 become one replacement character per - // maximal subpart, as the Unicode Standard recommends, rather than the one - // replacement character per sequence that the parser would produce - std::size_t valid_length{0}; - while (valid_length < input.size()) { - const auto length{utf8_codepoint_length(input, valid_length)}; - if (length == 0) { - break; - } +// The state of every thread is kept across calls, so that rendering many +// small inputs does not allocate the same buffers over and over +struct MarkdownConverter { + sourcemeta::core::markdown::Document document; + sourcemeta::core::markdown::BlockParser blocks{document}; + sourcemeta::core::markdown::InlineParser inlines{document}; + sourcemeta::core::markdown::PostProcessor postprocessor{document}; + sourcemeta::core::markdown::HTMLRenderer renderer{document}; + std::string repaired; +}; - valid_length += length; +// Give up the state of the thread even when the conversion throws +struct ConverterRelease { + std::optional &converter; + bool oversized; + ~ConverterRelease() { + if (this->oversized) { + this->converter.reset(); + } } +}; - const auto is_valid{valid_length == input.size()}; - const auto repaired{is_valid ? std::string{} : to_valid_utf8(input)}; - const std::string_view source{is_valid ? input : std::string_view{repaired}}; +auto replace_invalid_characters(const std::string_view input, + std::string &output) -> void { + output = sourcemeta::core::to_valid_utf8(input); + if (output.find('\0') != std::string::npos) { + output = sourcemeta::core::replace(output, std::string_view{"\0", 1}, + "\xEF\xBF\xBD"); + } +} - // cmark-gfm toggles process-global special-character tables when syntax - // extensions are attached and detached, so parser construction through - // teardown cannot run concurrently - static std::mutex cmark_mutex; - const std::scoped_lock lock{cmark_mutex}; +} // namespace - static constexpr auto BASE_OPTIONS{ - CMARK_OPT_VALIDATE_UTF8 | CMARK_OPT_FOOTNOTES | - CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE | CMARK_OPT_GITHUB_PRE_LANG}; - // This cmark-gfm suppresses raw HTML and unsafe links by default, so raw - // output requires explicitly opting out through CMARK_OPT_UNSAFE - const int options{safe ? BASE_OPTIONS : (BASE_OPTIONS | CMARK_OPT_UNSAFE)}; +namespace sourcemeta::core { - auto *parser{cmark_parser_new(options)}; +auto markdown_to_html(const std::string_view input, const bool safe) + -> std::string { + thread_local std::optional state; + if (!state.has_value()) { + state.emplace(); + } - static constexpr std::array EXTENSION_NAMES{ - {"table", "autolink", "strikethrough", "tagfilter", "tasklist"}}; - for (const auto *name : EXTENSION_NAMES) { - auto *extension{cmark_find_syntax_extension(name)}; - if (extension != nullptr) { - cmark_parser_attach_syntax_extension(parser, extension); - } + const ConverterRelease release{ + .converter = state, .oversized = input.size() > MAXIMUM_RETAINED_INPUT}; + auto &converter{state.value()}; + converter.document.clear(); + auto source{input}; + // GFM section 2.3 requires replacing the NUL character, and byte sequences + // that are not well-formed UTF-8 are replaced too + if (input.find('\0') != std::string_view::npos || + !sourcemeta::core::is_valid_utf8(input)) { + replace_invalid_characters(input, converter.repaired); + source = converter.repaired; } - cmark_parser_feed(parser, source.data(), source.size()); - auto *document{cmark_parser_finish(parser)}; - auto *result{cmark_render_html(document, options, - cmark_parser_get_syntax_extensions(parser))}; + // The parser addresses the input through 32-bit offsets + if (source.size() > std::numeric_limits::max()) { + throw MarkdownError{"The input is larger than the supported size bound"}; + } - std::string output{result}; - std::free(result); - cmark_node_free(document); - cmark_parser_free(parser); - return output; + converter.blocks.parse(source, input.size()); + converter.postprocessor.parse_inlines(converter.inlines); + converter.postprocessor.process_footnotes(); + return converter.renderer.render(!safe, + source.size() + (source.size() / 2) + 64); } } // namespace sourcemeta::core diff --git a/vendor/core/src/core/markdown/postprocess.h b/vendor/core/src/core/markdown/postprocess.h new file mode 100644 index 000000000..a06b0088d --- /dev/null +++ b/vendor/core/src/core/markdown/postprocess.h @@ -0,0 +1,524 @@ +#ifndef SOURCEMETA_CORE_MARKDOWN_POSTPROCESS_H_ +#define SOURCEMETA_CORE_MARKDOWN_POSTPROCESS_H_ + +#include +#include + +#include "characters.h" +#include "document.h" +#include "inlines.h" +#include "references.h" + +#include // std::sort +#include // std::array +#include // std::size_t +#include // std::uint32_t +#include // std::memchr +#include // std::less +#include // std::string +#include // std::string_view +#include // std::unordered_map +#include // std::vector + +namespace sourcemeta::core::markdown { + +inline auto is_leaf_type(const NodeType type) noexcept -> bool { + return type == NodeType::HTMLBlock || type == NodeType::ThematicBreak || + type == NodeType::CodeBlock || type == NodeType::Text || + type == NodeType::SoftBreak || type == NodeType::LineBreak || + type == NodeType::Code || type == NodeType::HTMLInline; +} + +// The node after the given one in document order when skipping its +// descendants, without leaving the subtree of the given root, or no node at +// the end of that subtree +inline auto next_skipping_descendants(const Document &document, + std::uint32_t index, + const std::uint32_t root) noexcept + -> std::uint32_t { + while (index != root && index != NO_NODE) { + const auto ¤t{document.nodes[index]}; + if (current.next != NO_NODE) { + return current.next; + } + + index = current.parent; + } + + return NO_NODE; +} + +// A character of the part of an email address before the at sign, which GFM +// section 6.9 makes of characters "which are alphanumeric, or ., -, _, or +" +inline auto is_email_local_character(const char character) noexcept -> bool { + return sourcemeta::core::is_alphanum(character) || character == '.' || + character == '-' || character == '_' || character == '+'; +} + +// The passes that run on the block structure once it is complete +class PostProcessor { +public: + explicit PostProcessor(Document &document) : document_{document} {} + + // Parse the inlines of every leaf block in document order, which is the + // order in which references count towards their expansion limit. Blocks + // without footnote references are finished right away, while their nodes + // are still in the cache, and the rest wait for footnotes to resolve + auto parse_inlines(InlineParser &parser) -> void { + this->deferred_.clear(); + auto current{this->document_.nodes[ROOT_NODE].first_child}; + while (current != NO_NODE) { + const auto type{this->document_.nodes[current].type}; + if (type == NodeType::Paragraph || type == NodeType::Heading || + type == NodeType::TableCell) { + const auto references{this->document_.footnote_reference_nodes.size()}; + parser.parse(current); + if (this->document_.footnote_reference_nodes.size() == references) { + this->finish_inlines(current); + } else { + this->deferred_.push_back(current); + } + + current = + next_skipping_descendants(this->document_, current, ROOT_NODE); + } else if (this->document_.nodes[current].first_child != NO_NODE) { + current = this->document_.nodes[current].first_child; + } else { + current = + next_skipping_descendants(this->document_, current, ROOT_NODE); + } + } + } + + // Number footnote definitions in the order in which they are first + // referenced and move them to the end of the document, dropping those that + // are never referenced or that repeat a label + auto process_footnotes() -> void { + const auto &definitions{this->document_.footnote_definition_nodes}; + const auto &references{this->document_.footnote_reference_nodes}; + if (definitions.empty() && references.empty()) { + return; + } + + auto &nodes{this->document_.nodes}; + this->definitions_.clear(); + this->definition_nodes_.clear(); + // Without nesting, the order in which definitions were opened matches the + // order in which they end, which is the order in which labels claim them + if (this->document_.nested_footnote_definitions) { + this->register_definitions_in_post_order(); + } else { + for (const auto definition : definitions) { + this->register_definition(definition); + } + } + + std::uint32_t last_index{0}; + for (const auto reference : references) { + if (this->is_attached(reference)) { + this->resolve_reference(reference, last_index); + } + } + + this->ordered_.clear(); + for (const auto &entry : this->definitions_) { + this->ordered_.push_back(entry.second); + } + + std::sort(this->ordered_.begin(), this->ordered_.end(), + [&nodes](const std::uint32_t left, const std::uint32_t right) { + return nodes[left].extra < nodes[right].extra; + }); + for (const auto definition : this->ordered_) { + this->document_.unlink(definition); + if (nodes[definition].extra > 0) { + set_flag(nodes[definition], FLAG_REFERENCED, true); + this->document_.append_child(ROOT_NODE, definition); + } + } + + for (const auto definition : this->definition_nodes_) { + if (!has_flag(nodes[definition], FLAG_REFERENCED)) { + this->document_.unlink(definition); + } + } + + for (const auto block : this->deferred_) { + this->finish_inlines(block); + } + } + +private: + // Merge the adjacent text nodes of a leaf block and turn the email + // addresses of GFM section 6.9 that appear outside of links into links + auto finish_inlines(const std::uint32_t block) -> void { + auto current{this->document_.nodes[block].first_child}; + while (current != NO_NODE) { + if (this->document_.nodes[current].type == NodeType::Text) { + this->merge_following_text(current); + } + + if (this->document_.nodes[current].first_child != NO_NODE) { + current = this->document_.nodes[current].first_child; + } else { + current = next_skipping_descendants(this->document_, current, block); + } + } + + // Only text with an at sign, which a character reference may produce, can + // have email addresses + const auto content{ + this->document_.content_of(this->document_.nodes[block])}; + if (content.empty() || + (std::memchr(content.data(), '@', content.size()) == nullptr && + std::memchr(content.data(), '&', content.size()) == nullptr)) { + return; + } + + current = this->document_.nodes[block].first_child; + while (current != NO_NODE) { + const auto type{this->document_.nodes[current].type}; + if (type == NodeType::Text) { + const auto next{ + next_skipping_descendants(this->document_, current, block)}; + this->link_emails_in_text(current); + current = next; + } else if (type != NodeType::Link && + this->document_.nodes[current].first_child != NO_NODE) { + current = this->document_.nodes[current].first_child; + } else { + current = next_skipping_descendants(this->document_, current, block); + } + } + } + + auto register_definitions_in_post_order() -> void { + const auto &nodes{this->document_.nodes}; + auto current{ROOT_NODE}; + bool entering{true}; + while (true) { + if (entering && !is_leaf_type(nodes[current].type) && + nodes[current].first_child != NO_NODE) { + current = nodes[current].first_child; + continue; + } + + if (nodes[current].type == NodeType::FootnoteDefinition) { + this->register_definition(current); + } + + if (current == ROOT_NODE) { + break; + } + + entering = nodes[current].next != NO_NODE; + current = entering ? nodes[current].next : nodes[current].parent; + } + } + + auto register_definition(const std::uint32_t index) -> void { + normalize_label(this->label_buffer_, this->document_.nodes[index].literal); + if (this->label_buffer_.empty()) { + return; + } + + this->definition_nodes_.push_back(index); + if (!this->definitions_.contains(std::string_view{this->label_buffer_})) { + this->definitions_.emplace( + this->document_.strings.store(this->label_buffer_), index); + } + } + + auto resolve_reference(const std::uint32_t index, std::uint32_t &last_index) + -> void { + auto &nodes{this->document_.nodes}; + const auto label{nodes[index].literal}; + auto definition{NO_NODE}; + if (sourcemeta::core::utf8_codepoint_within(label, 1, + MAXIMUM_LINK_LABEL_LENGTH)) { + normalize_label(this->label_buffer_, label); + const auto match{ + this->definitions_.find(std::string_view{this->label_buffer_})}; + if (match != this->definitions_.end()) { + definition = match->second; + } + } + + if (definition == NO_NODE) { + this->buffer_.assign("[^"); + this->buffer_.append(label); + this->buffer_.push_back(']'); + const auto text{this->document_.create(NodeType::Text)}; + nodes[text].literal = this->document_.strings.store(this->buffer_); + this->document_.insert_after(index, text); + this->document_.unlink(index); + return; + } + + if (nodes[definition].extra == 0) { + ++last_index; + nodes[definition].extra = last_index; + } + + ++nodes[definition].data; + nodes[index].data = definition; + nodes[index].extra = nodes[definition].data; + sourcemeta::core::DigitsBuffer digits; + nodes[index].literal = this->document_.strings.store( + sourcemeta::core::digits_view(nodes[definition].extra, digits)); + } + + [[nodiscard]] auto is_in_content(const std::string_view value) const noexcept + -> bool { + const std::less before{}; + const auto *const begin{this->document_.content.data()}; + const auto *const end{begin + this->document_.content.size()}; + return !before(value.data(), begin) && + !before(end, value.data() + value.size()); + } + + auto merge_following_text(const std::uint32_t index) -> void { + auto &nodes{this->document_.nodes}; + auto next{nodes[index].next}; + if (next == NO_NODE || nodes[next].type != NodeType::Text) { + return; + } + + auto literal{nodes[index].literal}; + bool buffered{false}; + while (next != NO_NODE && nodes[next].type == NodeType::Text) { + const auto piece{nodes[next].literal}; + if (buffered) { + this->buffer_.append(piece); + } else if (literal.empty()) { + literal = piece; + } else if (!piece.empty()) { + if (literal.data() + literal.size() == piece.data() && + this->is_in_content(literal) && this->is_in_content(piece)) { + literal = + std::string_view{literal.data(), literal.size() + piece.size()}; + } else { + this->buffer_.assign(literal); + this->buffer_.append(piece); + buffered = true; + } + } + + const auto following{nodes[next].next}; + this->document_.unlink(next); + next = following; + } + + nodes[index].literal = + buffered ? this->document_.strings.store(this->buffer_) : literal; + } + + // Whether a node is still part of the document, remembering the answer for + // every ancestor on the way, so that the references of a deeply nested block + // do not walk the same ancestors over and over + auto is_attached(const std::uint32_t index) -> bool { + auto &nodes{this->document_.nodes}; + this->ancestors_.clear(); + auto current{index}; + while (current != ROOT_NODE && current != NO_NODE && + !has_flag(nodes[current], FLAG_ATTACHED) && + !has_flag(nodes[current], FLAG_DETACHED)) { + this->ancestors_.push_back(current); + current = nodes[current].parent; + } + + const auto attached{ + current == ROOT_NODE || + (current != NO_NODE && has_flag(nodes[current], FLAG_ATTACHED))}; + for (const auto ancestor : this->ancestors_) { + set_flag(nodes[ancestor], attached ? FLAG_ATTACHED : FLAG_DETACHED, true); + } + + return attached; + } + + // Whether an extended autolink may start at the beginning of a text node, + // where GFM section 6.9 says that such autolinks "can only come at the + // beginning of a line, after whitespace, or any of the delimiting characters + // *, _, ~, and (", which are also the characters around emphasis, strong + // emphasis, and strikethrough + [[nodiscard]] auto may_start_autolink_at(std::uint32_t text) const noexcept + -> bool { + const auto &nodes{this->document_.nodes}; + while (true) { + const auto previous{nodes[text].previous}; + if (previous == NO_NODE) { + return nodes[nodes[text].parent].type != NodeType::Image; + } + + const auto &node{nodes[previous]}; + switch (node.type) { + case NodeType::Text: + if (!node.literal.empty()) { + return may_precede_extended_autolink(node.literal.back()); + } + + text = previous; + break; + case NodeType::SoftBreak: + case NodeType::LineBreak: + case NodeType::Emphasis: + case NodeType::Strong: + case NodeType::Strikethrough: + return true; + case NodeType::Document: + case NodeType::BlockQuote: + case NodeType::List: + case NodeType::Item: + case NodeType::CodeBlock: + case NodeType::HTMLBlock: + case NodeType::Paragraph: + case NodeType::Heading: + case NodeType::ThematicBreak: + case NodeType::FootnoteDefinition: + case NodeType::Table: + case NodeType::TableRow: + case NodeType::TableCell: + case NodeType::Code: + case NodeType::HTMLInline: + case NodeType::Link: + case NodeType::Image: + case NodeType::FootnoteReference: + return false; + } + } + } + + // Turn the email addresses of GFM section 6.9 in a text node into links, + // along with the mailto and xmpp protocols that may come before them + auto link_emails_in_text(std::uint32_t text) -> void { + auto &nodes{this->document_.nodes}; + const auto data{nodes[text].literal}; + const auto first_text{text}; + // The position of the data at which the current text node starts + std::size_t consumed{0}; + std::size_t search{0}; + while (search < data.size()) { + const auto *const found{static_cast( + std::memchr(data.data() + search, '@', data.size() - search))}; + if (found == nullptr) { + break; + } + + const auto separator{static_cast(found - data.data())}; + search = separator + 1; + auto link_start{separator}; + while (link_start > consumed && + is_email_local_character(data[link_start - 1])) { + --link_start; + } + + if (link_start == separator) { + continue; + } + + // GFM section 6.9: "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 _", where "only . may occur at + // the end of the email address, in which case it will not be considered + // part of the address" + auto end{separator + 1}; + std::size_t periods{0}; + while (end < data.size()) { + if (is_domain_character(data[end])) { + ++end; + } else if (data[end] == '.' && end > separator + 1 && + end + 1 < data.size() && + is_domain_character(data[end + 1])) { + ++periods; + ++end; + } else { + break; + } + } + + if (periods == 0 || data[end - 1] == '-' || data[end - 1] == '_') { + continue; + } + + // GFM section 6.9: "An extended protocol autolink will be recognised + // when a protocol is recognised within any text node", where the valid + // protocols are mailto and xmpp + bool has_protocol{false}; + bool xmpp{false}; + for (const auto protocol : + std::array{{"mailto:", "xmpp:"}}) { + if (link_start - consumed >= protocol.size() && + sourcemeta::core::starts_with_ignore_case( + data.substr(link_start - protocol.size(), protocol.size()), + protocol)) { + link_start -= protocol.size(); + has_protocol = true; + xmpp = protocol == "xmpp:"; + break; + } + } + + // GFM section 6.9: xmpp "offers an optional / followed by a resource. + // The resource can contain all alphanumeric characters, as well as @ and + // .", while "Further / characters are not considered part of the domain" + if (xmpp && end + 1 < data.size() && data[end] == '/') { + auto resource_end{end + 1}; + while (resource_end < data.size() && + (sourcemeta::core::is_alphanum(data[resource_end]) || + data[resource_end] == '@' || data[resource_end] == '.')) { + ++resource_end; + } + + while (resource_end > end + 1 && data[resource_end - 1] == '.') { + --resource_end; + } + + if (resource_end > end + 1) { + end = resource_end; + } + } + + if (link_start == consumed + ? consumed > 0 || !this->may_start_autolink_at(first_text) + : !may_precede_extended_autolink(data[link_start - 1])) { + continue; + } + + const auto address{data.substr(link_start, end - link_start)}; + const auto link{this->document_.create(NodeType::Link)}; + if (has_protocol) { + nodes[link].literal = address; + } else { + this->buffer_.assign("mailto:"); + this->buffer_.append(address); + nodes[link].literal = this->document_.strings.store(this->buffer_); + } + + const auto link_text{this->document_.create(NodeType::Text)}; + nodes[link_text].literal = address; + this->document_.append_child(link, link_text); + this->document_.insert_after(text, link); + const auto after{this->document_.create(NodeType::Text)}; + nodes[after].literal = data.substr(end); + this->document_.insert_after(link, after); + nodes[text].literal = data.substr(consumed, link_start - consumed); + text = after; + consumed = end; + search = end; + } + } + + Document &document_; + std::unordered_map definitions_; + std::vector definition_nodes_; + std::vector ordered_; + std::vector deferred_; + std::vector ancestors_; + std::string label_buffer_; + std::string buffer_; +}; + +} // namespace sourcemeta::core::markdown + +#endif diff --git a/vendor/core/src/core/markdown/references.h b/vendor/core/src/core/markdown/references.h new file mode 100644 index 000000000..6fcc5fc21 --- /dev/null +++ b/vendor/core/src/core/markdown/references.h @@ -0,0 +1,310 @@ +#ifndef SOURCEMETA_CORE_MARKDOWN_REFERENCES_H_ +#define SOURCEMETA_CORE_MARKDOWN_REFERENCES_H_ + +#include + +#include "characters.h" +#include "document.h" +#include "scanners.h" + +#include // std::size_t, std::ptrdiff_t +#include // std::string +#include // std::string_view + +namespace sourcemeta::core::markdown { + +// GFM section 6.6: "A link label can have at most 999 characters inside the +// square brackets", where GFM section 2.1 says that "A character is a Unicode +// code point" +constexpr std::size_t MAXIMUM_LINK_LABEL_LENGTH{999}; + +// GFM section 6.6: "Implementations may impose limits on parentheses nesting to +// avoid performance issues, but at least three levels of nesting should be +// supported" +constexpr std::size_t MAXIMUM_DESTINATION_PARENTHESES{32}; + +// A link label of GFM section 4.7, moving the position past it on success +inline auto scan_link_label(const std::string_view input, std::size_t &position, + std::string_view &label) noexcept -> bool { + const auto start{position}; + if (character_at(input, start) != '[') { + return false; + } + + auto cursor{start + 1}; + std::size_t length{0}; + while (cursor < input.size()) { + const auto character{input[cursor]}; + if (character == '[' || character == ']') { + break; + } + + ++cursor; + if (!sourcemeta::core::is_utf8_continuation( + static_cast(character))) { + ++length; + } + + if (character == '\\' && + sourcemeta::core::is_punctuation(character_at(input, cursor))) { + ++cursor; + ++length; + } + + if (length > MAXIMUM_LINK_LABEL_LENGTH) { + return false; + } + } + + if (character_at(input, cursor) != ']') { + return false; + } + + label = sourcemeta::core::trim(input.substr(start + 1, cursor - start - 1), + is_space); + position = cursor + 1; + return true; +} + +// A link destination of GFM section 6.3, returning the length it takes +// including any angle brackets, or minus one if there is none +inline auto scan_link_destination(const std::string_view input, + const std::size_t offset, + std::string_view &destination) noexcept + -> std::ptrdiff_t { + const auto size{input.size()}; + auto index{offset}; + if (index < size && input[index] == '<') { + ++index; + while (index < size) { + const auto character{input[index]}; + if (character == '>') { + ++index; + break; + } + + // GFM section 6.3: a link destination can be "a sequence of zero or + // more characters between an opening < and a closing > that contains + // no line breaks or unescaped < or > characters", where GFM section 2.4 + // only lets "Any ASCII punctuation character" be backslash-escaped + if (character == '\\' && index + 1 < size && + sourcemeta::core::is_punctuation(input[index + 1])) { + index += 2; + } else if (character == '\n' || character == '\r' || character == '<') { + return -1; + } else { + ++index; + } + } + + if (index >= size) { + return -1; + } + + destination = input.substr(offset + 1, index - offset - 2); + return static_cast(index - offset); + } + + std::size_t parentheses{0}; + while (index < size) { + const auto character{input[index]}; + if (character == '\\' && index + 1 < size && + sourcemeta::core::is_punctuation(input[index + 1])) { + index += 2; + } else if (character == '(') { + ++parentheses; + ++index; + if (parentheses > MAXIMUM_DESTINATION_PARENTHESES) { + return -1; + } + } else if (character == ')') { + if (parentheses == 0) { + break; + } + + --parentheses; + ++index; + } else if (is_space_or_control(character)) { + if (index == offset) { + return -1; + } + + break; + } else { + ++index; + } + } + + if (index >= size) { + return -1; + } + + destination = input.substr(offset, index - offset); + return static_cast(index - offset); +} + +// Resolve the character references and backslash escapes of a link +// destination, where a destination that needs neither and lives in stable +// storage is returned as it is +inline auto clean_url(Document &document, const std::string_view url, + std::string &buffer, const bool stable) + -> std::string_view { + if (url.empty()) { + return {}; + } + + if (stable && url.find_first_of("&\\") == std::string_view::npos) { + return url; + } + + buffer.clear(); + decode_escapes_and_references(buffer, url); + return document.strings.store(buffer); +} + +// Resolve the character references and backslash escapes of a link title, +// dropping its surrounding delimiters +inline auto clean_title(Document &document, const std::string_view title, + std::string &buffer, const bool stable) + -> std::string_view { + if (title.empty()) { + return {}; + } + + const auto first{title.front()}; + const auto last{title.back()}; + auto inner{title}; + if ((first == '\'' && last == '\'') || (first == '(' && last == ')') || + (first == '"' && last == '"')) { + inner = title.size() < 2 ? std::string_view{} + : title.substr(1, title.size() - 2); + } + + if (stable && inner.find_first_of("&\\") == std::string_view::npos) { + return inner; + } + + buffer.clear(); + decode_escapes_and_references(buffer, inner); + return document.strings.store(buffer); +} + +inline auto skip_spaces(const std::string_view input, + std::size_t &position) noexcept -> void { + while (position < input.size() && + (input[position] == ' ' || input[position] == '\t')) { + ++position; + } +} + +inline auto skip_line_end(const std::string_view input, + std::size_t &position) noexcept -> bool { + bool seen{false}; + if (character_at(input, position) == '\r') { + ++position; + seen = true; + } + + if (character_at(input, position) == '\n') { + ++position; + seen = true; + } + + return seen || position >= input.size(); +} + +// Spaces or tabs, including up to one line ending +inline auto skip_spaces_and_line_end(const std::string_view input, + std::size_t &position) noexcept -> void { + skip_spaces(input, position); + if (skip_line_end(input, position)) { + skip_spaces(input, position); + } +} + +// A link reference definition of GFM section 4.7 at the start of the input, +// which is registered unless a previous definition has the same label, +// returning the length it takes or zero if there is none +inline auto +parse_reference_definition(Document &document, const std::string_view input, + std::string &label_buffer, std::string &value_buffer) + -> std::size_t { + std::size_t position{0}; + std::string_view label; + if (!scan_link_label(input, position, label) || label.empty() || + character_at(input, position) != ':') { + return 0; + } + + ++position; + skip_spaces_and_line_end(input, position); + std::string_view url; + const auto url_length{scan_link_destination(input, position, url)}; + if (url_length < 0) { + return 0; + } + + position += static_cast(url_length); + const auto before_title{position}; + skip_spaces_and_line_end(input, position); + const auto title_length{ + position == before_title ? 0 : scan_link_title(input, position)}; + std::string_view title; + if (title_length > 0) { + title = input.substr(position, title_length); + position += title_length; + } else { + position = before_title; + } + + skip_spaces(input, position); + if (!skip_line_end(input, position)) { + if (title_length == 0) { + return 0; + } + + position = before_title; + skip_spaces(input, position); + if (!skip_line_end(input, position)) { + return 0; + } + + // GFM section 4.7, example 179: a title followed by other text on its line + // leaves "a link reference definition, but it has no title" + title = {}; + } + + normalize_label(label_buffer, label); + if (!label_buffer.empty() && + !document.references.contains(std::string_view{label_buffer})) { + const auto key{document.strings.store(label_buffer)}; + const auto cleaned_url{clean_url(document, url, value_buffer, false)}; + const auto cleaned_title{clean_title(document, title, value_buffer, false)}; + document.references.emplace( + key, Reference{.url = cleaned_url, .title = cleaned_title}); + } + + return position; +} + +// Find the definition of a link label +inline auto find_reference(const Document &document, + const std::string_view label, std::string &buffer) + -> const Reference * { + if (document.references.empty() || !sourcemeta::core::utf8_codepoint_within( + label, 1, MAXIMUM_LINK_LABEL_LENGTH)) { + return nullptr; + } + + normalize_label(buffer, label); + if (buffer.empty()) { + return nullptr; + } + + const auto match{document.references.find(std::string_view{buffer})}; + return match == document.references.end() ? nullptr : &match->second; +} + +} // namespace sourcemeta::core::markdown + +#endif diff --git a/vendor/core/src/core/markdown/render.h b/vendor/core/src/core/markdown/render.h new file mode 100644 index 000000000..a176b393d --- /dev/null +++ b/vendor/core/src/core/markdown/render.h @@ -0,0 +1,625 @@ +#ifndef SOURCEMETA_CORE_MARKDOWN_RENDER_H_ +#define SOURCEMETA_CORE_MARKDOWN_RENDER_H_ + +#include +#include +#include +#include + +#include "characters.h" +#include "document.h" +#include "postprocess.h" +#include "scanners.h" + +#include // std::array +#include // std::size_t +#include // std::uint8_t, std::uint32_t +#include // std::string +#include // std::string_view + +namespace sourcemeta::core::markdown { + +// The tags that the GFM tag filter of section 6.11 disallows +constexpr std::array FILTERED_TAG_NAMES{ + {"title", "textarea", "style", "xmp", "iframe", "noembed", "noframes", + "script", "plaintext"}}; + +// Whether raw HTML starts with a tag that the tag filter disallows. The tag +// name state of the HTML Standard tokenizer ends a tag name at "U+0009 +// CHARACTER TABULATION (tab) U+000A LINE FEED (LF) U+000C FORM FEED (FF) +// U+0020 SPACE", at "U+002F SOLIDUS (/)", and at "U+003E GREATER-THAN SIGN +// (>)", where a carriage return reaches the tokenizer as a line feed once the +// input stream normalizes newlines +inline auto is_filtered_tag(const std::string_view tag) noexcept -> bool { + if (tag.size() < 3 || tag[0] != '<') { + return false; + } + + for (const auto name : FILTERED_TAG_NAMES) { + std::size_t index{tag[1] == '/' ? 2U : 1U}; + std::size_t name_index{0}; + while (index < tag.size() && name_index < name.size() && + sourcemeta::core::to_lowercase(tag[index]) == name[name_index]) { + ++index; + ++name_index; + } + + if (name_index < name.size() || index == tag.size()) { + continue; + } + + switch (tag[index]) { + case '\t': + case '\n': + case '\f': + case '\r': + case ' ': + case '/': + case '>': + return true; + default: + break; + } + } + + return false; +} + +class HTMLRenderer { +public: + explicit HTMLRenderer(const Document &document) : document_{document} {} + + auto render(const bool unsafe, const std::size_t capacity) -> std::string { + // A conversion that threw while rendering leaves its partial output behind + this->writer_.clear(); + this->writer_.reserve(capacity); + this->reference_size_ = 0; + this->unsafe_ = unsafe; + this->footnote_index_ = 0; + this->written_footnote_index_ = 0; + this->needs_closing_table_body_ = false; + this->in_table_header_ = false; + const auto &nodes{this->document_.nodes}; + auto current{ROOT_NODE}; + bool entering{true}; + while (true) { + this->render_node(current, entering); + const auto &node{nodes[current]}; + // An image renders the text of its descendants as its alternative text + // when entering it, so they are not visited on their own + if (entering && !is_leaf_type(node.type) && + node.type != NodeType::Image) { + if (node.first_child != NO_NODE) { + current = node.first_child; + } else { + entering = false; + } + + continue; + } + + if (current == ROOT_NODE) { + break; + } + + entering = node.next != NO_NODE; + current = entering ? node.next : node.parent; + } + + if (this->footnote_index_ > 0) { + this->writer_.close().raw("\n").close().raw("\n"); + } + + return this->writer_.take(); + } + +private: + // A link destination, which safe mode drops when its scheme can run code or + // read local files + auto destination(const std::string_view url) -> std::string_view { + this->value_.clear(); + if (this->unsafe_ || !is_dangerous_url(url)) { + sourcemeta::core::URI::escape_reference(url, this->value_); + } + + return this->value_.view(); + } + + // The fragment that links to a footnote element, including the number sign + // that introduces it. The label is part of the fragment, where RFC 3986 + // Section 3.5 leaves no room for another number sign + auto footnote_fragment(const std::string_view prefix, + const std::string_view label) -> std::string_view { + this->fragment_.clear(); + this->fragment_.append('#'); + this->fragment_.append(prefix); + this->fragment_.append(label); + this->value_.clear(); + sourcemeta::core::URI::escape_reference(this->fragment_.view(), + this->value_); + return this->value_.view(); + } + + // The alternative text of an image, which is the text of its descendants + // without their markup + auto alternative_text(const std::uint32_t image) -> std::string_view { + this->value_.clear(); + const auto &nodes{this->document_.nodes}; + auto current{nodes[image].first_child}; + while (current != NO_NODE) { + const auto &node{nodes[current]}; + if (node.type == NodeType::Text || node.type == NodeType::Code || + node.type == NodeType::HTMLInline) { + this->value_.append(node.literal); + } else if (node.type == NodeType::SoftBreak || + node.type == NodeType::LineBreak) { + this->value_.append(' '); + } + + current = + node.first_child != NO_NODE + ? node.first_child + : next_skipping_descendants(this->document_, current, image); + } + + return this->value_.view(); + } + + auto append_footnote_backreference(const Node &definition) -> bool { + if (this->written_footnote_index_ >= this->footnote_index_) { + return false; + } + + this->written_footnote_index_ = this->footnote_index_; + auto &writer{this->writer_}; + writer.a().attribute("href", + this->footnote_fragment("fnref-", definition.literal)); + writer.attribute("class", "footnote-backref") + .attribute("data-footnote-backref"); + sourcemeta::core::DigitsBuffer written_digits; + const auto written_index{sourcemeta::core::digits_view( + this->written_footnote_index_, written_digits)}; + writer.attribute("data-footnote-backref-idx", written_index); + this->value_.clear(); + this->value_.append("Back to reference "); + this->value_.append(written_index); + writer.attribute("aria-label", this->value_.view()); + writer.raw("\xE2\x86\xA9").close(); + for (std::uint32_t index{2}; index <= definition.data; ++index) { + sourcemeta::core::DigitsBuffer repeat_digits; + const auto repeat{sourcemeta::core::digits_view(index, repeat_digits)}; + writer.raw(" "); + this->footnote_fragment("fnref-", definition.literal); + this->value_.append('-'); + this->value_.append(repeat); + writer.a().attribute("href", this->value_.view()); + writer.attribute("class", "footnote-backref") + .attribute("data-footnote-backref"); + this->value_.clear(); + this->value_.append(written_index); + this->value_.append('-'); + this->value_.append(repeat); + writer.attribute("data-footnote-backref-idx", this->value_.view()); + this->value_.clear(); + this->value_.append("Back to reference "); + this->value_.append(written_index); + this->value_.append('-'); + this->value_.append(repeat); + writer.attribute("aria-label", this->value_.view()); + writer.raw("\xE2\x86\xA9"); + writer.sup().attribute("class", "footnote-ref").text(repeat); + writer.close().close(); + } + + return true; + } + + [[nodiscard]] auto is_tight_paragraph(const Node ¶graph) const noexcept + -> bool { + const auto &nodes{this->document_.nodes}; + const auto grandparent{nodes[paragraph.parent].parent}; + return grandparent != NO_NODE && + nodes[grandparent].type == NodeType::List && + has_flag(nodes[grandparent], FLAG_TIGHT); + } + + auto open_heading(const std::uint8_t level) -> void { + switch (level) { + case 1: + this->writer_.h1(); + break; + case 2: + this->writer_.h2(); + break; + case 3: + this->writer_.h3(); + break; + case 4: + this->writer_.h4(); + break; + case 5: + this->writer_.h5(); + break; + default: + this->writer_.h6(); + break; + } + } + + // The destinations and titles that rendered link references expand to, which + // the specification lets grow quadratically with the input + auto count_reference_expansion(const Node &node) -> void { + if (!has_flag(node, FLAG_REFERENCE_LINK)) { + return; + } + + this->reference_size_ += node.literal.size() + node.title.size(); + if (this->reference_size_ > this->document_.reference_size_limit) { + throw sourcemeta::core::MarkdownError{ + "The link references expand past the size bound"}; + } + } + + auto render_code_block(const Node &node) -> void { + auto &writer{this->writer_}; + writer.ensure_line_feed(); + writer.pre().code(); + const auto info{node.title}; + if (!info.empty()) { + std::size_t first_tag{0}; + while (first_tag < info.size() && !is_space(info[first_tag])) { + ++first_tag; + } + + // GFM section 4.5: "The first word of the info string is typically used + // to specify the language of the code sample, and rendered in the class + // attribute of the code tag", which is how the HTML Standard marks the + // language of computer code too, "by adding a class prefixed with + // "language-" to the element", as its lang attribute is for the + // language of the text + this->value_.clear(); + this->value_.append("language-"); + this->value_.append(info.substr(0, first_tag)); + writer.attribute("class", this->value_.view()); + } + + writer.text(node.literal.data() != nullptr + ? node.literal + : this->document_.content_of(node)); + writer.close().close().raw("\n"); + } + + auto render_table_cell(const Node &node, const bool entering) -> void { + auto &writer{this->writer_}; + if (!entering) { + writer.close(); + return; + } + + writer.ensure_line_feed(); + if (this->in_table_header_) { + writer.th(); + } else { + writer.td(); + } + + const auto &nodes{this->document_.nodes}; + const auto &table{nodes[nodes[node.parent].parent]}; + const auto &data{this->document_.tables[table.data]}; + switch (this->document_.alignments[data.alignments_offset + node.data]) { + case 'l': + writer.attribute("align", "left"); + break; + case 'c': + writer.attribute("align", "center"); + break; + case 'r': + writer.attribute("align", "right"); + break; + default: + break; + } + } + + auto render_node(const std::uint32_t index, const bool entering) -> void { + const auto &nodes{this->document_.nodes}; + const auto &node{nodes[index]}; + auto &writer{this->writer_}; + switch (node.type) { + case NodeType::Document: + break; + case NodeType::BlockQuote: + writer.ensure_line_feed(); + if (entering) { + writer.blockquote(); + } else { + writer.close(); + } + + writer.raw("\n"); + break; + case NodeType::List: { + if (!entering) { + writer.close().raw("\n"); + break; + } + + const auto &data{this->document_.lists[node.data]}; + writer.ensure_line_feed(); + if (!data.ordered) { + writer.ul(); + } else { + writer.ol(); + if (data.start != 1) { + sourcemeta::core::DigitsBuffer digits; + writer.attribute("start", + sourcemeta::core::digits_view(data.start, digits)); + } + } + + writer.raw("\n"); + break; + } + + case NodeType::Item: + if (!entering) { + writer.close().raw("\n"); + break; + } + + writer.ensure_line_feed(); + writer.li(); + if (has_flag(node, FLAG_TASK)) { + writer.input().attribute("type", "checkbox"); + if (has_flag(node, FLAG_CHECKED)) { + writer.attribute("checked", ""); + } + + writer.attribute("disabled", "").raw(" "); + } + + break; + case NodeType::Heading: + if (entering) { + writer.ensure_line_feed(); + this->open_heading(node.level); + } else { + writer.close().raw("\n"); + } + + break; + case NodeType::CodeBlock: + this->render_code_block(node); + break; + case NodeType::HTMLBlock: + writer.ensure_line_feed(); + if (!this->unsafe_) { + writer.raw(""); + } else { + this->append_filtered_html(this->document_.content_of(node)); + } + + writer.ensure_line_feed(); + break; + case NodeType::ThematicBreak: + writer.ensure_line_feed(); + writer.hr().raw("\n"); + break; + case NodeType::Paragraph: + if (this->is_tight_paragraph(node)) { + break; + } + + if (entering) { + writer.ensure_line_feed(); + writer.p(); + break; + } + + if (nodes[node.parent].type == NodeType::FootnoteDefinition && + node.next == NO_NODE) { + writer.raw(" "); + this->append_footnote_backreference(nodes[node.parent]); + } + + writer.close().raw("\n"); + break; + case NodeType::Text: + writer.text(node.literal); + break; + case NodeType::SoftBreak: + writer.raw("\n"); + break; + case NodeType::LineBreak: + writer.br().raw("\n"); + break; + case NodeType::Code: + writer.code(node.literal); + break; + case NodeType::HTMLInline: + if (!this->unsafe_) { + writer.raw(""); + } else if (is_filtered_tag(node.literal)) { + writer.raw("<").raw(node.literal.substr(1)); + } else { + writer.raw(node.literal); + } + + break; + // GFM section 6.4, example 473: "****foo****" renders as + // "

foo

" + case NodeType::Strong: + if (entering) { + writer.strong(); + } else { + writer.close(); + } + + break; + case NodeType::Emphasis: + if (entering) { + writer.em(); + } else { + writer.close(); + } + + break; + case NodeType::Strikethrough: + if (entering) { + writer.del(); + } else { + writer.close(); + } + + break; + case NodeType::Link: + if (!entering) { + writer.close(); + break; + } + + this->count_reference_expansion(node); + writer.a().attribute("href", this->destination(node.literal)); + if (!node.title.empty()) { + writer.attribute("title", node.title); + } + + break; + case NodeType::Image: + this->count_reference_expansion(node); + writer.img().attribute("src", this->destination(node.literal)); + writer.attribute("alt", this->alternative_text(index)); + if (!node.title.empty()) { + writer.attribute("title", node.title); + } + + break; + case NodeType::FootnoteDefinition: + if (entering) { + if (this->footnote_index_ == 0) { + writer.section() + .attribute("class", "footnotes") + .attribute("data-footnotes") + .raw("\n"); + writer.ol().raw("\n"); + } + + ++this->footnote_index_; + writer.li() + .attribute("id", + this->footnote_fragment("fn-", node.literal).substr(1)) + .raw("\n"); + break; + } + + if (this->append_footnote_backreference(node)) { + writer.raw("\n"); + } + + writer.close().raw("\n"); + break; + case NodeType::FootnoteReference: { + if (!entering) { + break; + } + + const auto &definition{nodes[node.data]}; + writer.sup().attribute("class", "footnote-ref"); + writer.a().attribute( + "href", this->footnote_fragment("fn-", definition.literal)); + this->footnote_fragment("fnref-", definition.literal); + if (node.extra > 1) { + sourcemeta::core::DigitsBuffer extra_digits; + this->value_.append('-'); + this->value_.append( + sourcemeta::core::digits_view(node.extra, extra_digits)); + } + + writer.attribute("id", this->value_.view().substr(1)) + .attribute("data-footnote-ref"); + writer.text(node.literal).close().close(); + break; + } + + case NodeType::Table: + if (entering) { + writer.ensure_line_feed(); + writer.table(); + this->needs_closing_table_body_ = false; + break; + } + + if (this->needs_closing_table_body_) { + writer.ensure_line_feed(); + writer.close(); + writer.ensure_line_feed(); + } + + this->needs_closing_table_body_ = false; + writer.ensure_line_feed(); + writer.close(); + writer.ensure_line_feed(); + break; + case NodeType::TableRow: + writer.ensure_line_feed(); + if (!entering) { + writer.close(); + if (has_flag(node, FLAG_HEADER)) { + writer.ensure_line_feed(); + writer.close(); + this->in_table_header_ = false; + } + + break; + } + + if (has_flag(node, FLAG_HEADER)) { + this->in_table_header_ = true; + writer.thead(); + writer.ensure_line_feed(); + } else if (!this->needs_closing_table_body_) { + writer.tbody(); + writer.ensure_line_feed(); + this->needs_closing_table_body_ = true; + } + + writer.tr(); + break; + case NodeType::TableCell: + this->render_table_cell(node, entering); + break; + } + } + + auto append_filtered_html(std::string_view html) -> void { + auto &writer{this->writer_}; + while (!html.empty()) { + const auto bracket{html.find('<')}; + if (bracket == std::string_view::npos) { + break; + } + + writer.raw(html.substr(0, bracket)); + html.remove_prefix(bracket); + writer.raw(is_filtered_tag(html) ? "<" : "<"); + html.remove_prefix(1); + } + + writer.raw(html); + } + + const Document &document_; + sourcemeta::core::HTMLWriter writer_; + sourcemeta::core::HTMLBuffer value_; + sourcemeta::core::HTMLBuffer fragment_; + std::size_t reference_size_{0}; + bool unsafe_{false}; + std::uint32_t footnote_index_{0}; + std::uint32_t written_footnote_index_{0}; + bool needs_closing_table_body_{false}; + bool in_table_header_{false}; +}; + +} // namespace sourcemeta::core::markdown + +#endif diff --git a/vendor/core/src/core/markdown/scanners.h b/vendor/core/src/core/markdown/scanners.h new file mode 100644 index 000000000..66caa0b37 --- /dev/null +++ b/vendor/core/src/core/markdown/scanners.h @@ -0,0 +1,857 @@ +#ifndef SOURCEMETA_CORE_MARKDOWN_SCANNERS_H_ +#define SOURCEMETA_CORE_MARKDOWN_SCANNERS_H_ + +#include +#include +#include + +#include "characters.h" + +#include // std::binary_search +#include // std::array +#include // std::size_t +#include // std::uint8_t +#include // std::string_view + +// Every scanner matches at the given offset of the input, never looks past +// its end, and returns the length of the match, where zero means no match + +namespace sourcemeta::core::markdown { + +inline auto character_at(const std::string_view input, + const std::size_t index) noexcept -> char { + return index < input.size() ? input[index] : '\0'; +} + +// The whitespace that raw HTML allows between its parts +inline auto is_html_space(const char character) noexcept -> bool { + return character == ' ' || character == '\t' || character == '\v' || + character == '\f' || character == '\r' || character == '\n'; +} + +// The whitespace that the table and task list extensions allow within a line +inline auto is_line_space(const char character) noexcept -> bool { + return character == ' ' || character == '\t' || character == '\v' || + character == '\f'; +} + +inline auto scan_spacechars(const std::string_view input, + const std::size_t offset) noexcept -> std::size_t { + auto position{offset}; + while (position < input.size() && is_html_space(input[position])) { + ++position; + } + + return position - offset; +} + +// An absolute URI of GFM section 6.9, right after the opening angle bracket +inline auto scan_autolink_uri(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + auto position{offset}; + if (!sourcemeta::core::is_alpha(character_at(input, position))) { + return 0; + } + + ++position; + std::size_t scheme_length{0}; + while (scheme_length < 31) { + const auto character{character_at(input, position)}; + if (!sourcemeta::core::is_alphanum(character) && character != '.' && + character != '+' && character != '-') { + break; + } + + ++position; + ++scheme_length; + } + + if (scheme_length == 0 || character_at(input, position) != ':') { + return 0; + } + + ++position; + while (position < input.size()) { + const auto character{static_cast(input[position])}; + if (character <= 0x20 || character == '<' || character == '>') { + break; + } + + ++position; + } + + if (character_at(input, position) != '>') { + return 0; + } + + return position + 1 - offset; +} + +// An email address of GFM section 6.9, right after the opening angle bracket, +// which is a valid email address of the HTML Standard up to the closing angle +// bracket +inline auto scan_autolink_email(const std::string_view input, + const std::size_t offset) -> std::size_t { + auto position{offset}; + while (position < input.size()) { + const auto character{static_cast(input[position])}; + if (character <= 0x20 || character == '<' || character == '>') { + break; + } + + ++position; + } + + if (character_at(input, position) != '>' || + !sourcemeta::core::is_html_email( + input.substr(offset, position - offset))) { + return 0; + } + + return position + 1 - offset; +} + +inline auto scan_tag_name(const std::string_view input, + const std::size_t offset) noexcept -> std::size_t { + if (!sourcemeta::core::is_alpha(character_at(input, offset))) { + return 0; + } + + auto position{offset + 1}; + while (position < input.size() && + (sourcemeta::core::is_alphanum(input[position]) || + input[position] == '-')) { + ++position; + } + + return position - offset; +} + +inline auto is_attribute_name_start(const char character) noexcept -> bool { + return sourcemeta::core::is_alpha(character) || character == '_' || + character == ':'; +} + +inline auto is_attribute_name_character(const char character) noexcept -> bool { + return sourcemeta::core::is_alphanum(character) || character == '_' || + character == ':' || character == '.' || character == '-'; +} + +// The value of an attribute, at the equals sign or the whitespace before it +inline auto +scan_attribute_value_specification(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + auto position{offset + scan_spacechars(input, offset)}; + if (character_at(input, position) != '=') { + return 0; + } + + ++position; + position += scan_spacechars(input, position); + const auto quote{character_at(input, position)}; + if (quote == '"' || quote == '\'') { + const auto closing{input.find(quote, position + 1)}; + if (closing == std::string_view::npos) { + return 0; + } + + return closing + 1 - offset; + } + + const auto value_start{position}; + while (position < input.size()) { + const auto character{input[position]}; + if (character == ' ' || character == '\t' || character == '\r' || + character == '\n' || character == '\v' || character == '\f' || + character == '"' || character == '\'' || character == '=' || + character == '<' || character == '>' || character == '`') { + break; + } + + ++position; + } + + if (position == value_start) { + return 0; + } + + return position - offset; +} + +// An open tag or a closing tag of GFM section 6.6, right after the opening +// angle bracket +inline auto scan_html_tag(const std::string_view input, + const std::size_t offset) noexcept -> std::size_t { + auto position{offset}; + if (character_at(input, position) == '/') { + ++position; + const auto name_length{scan_tag_name(input, position)}; + if (name_length == 0) { + return 0; + } + + position += name_length; + position += scan_spacechars(input, position); + if (character_at(input, position) != '>') { + return 0; + } + + return position + 1 - offset; + } + + const auto name_length{scan_tag_name(input, position)}; + if (name_length == 0) { + return 0; + } + + position += name_length; + while (true) { + const auto spaces{scan_spacechars(input, position)}; + if (spaces == 0 || + !is_attribute_name_start(character_at(input, position + spaces))) { + break; + } + + auto name_end{position + spaces + 1}; + while (name_end < input.size() && + is_attribute_name_character(input[name_end])) { + ++name_end; + } + + position = name_end + scan_attribute_value_specification(input, name_end); + } + + position += scan_spacechars(input, position); + if (character_at(input, position) == '/') { + ++position; + } + + if (character_at(input, position) != '>') { + return 0; + } + + return position + 1 - offset; +} + +// An HTML comment of GFM section 6.10, at the two dashes that follow the +// exclamation mark: "An HTML comment consists of , where text +// does not start with > or ->, does not end with -, and does not contain --" +inline auto scan_html_comment(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + if (character_at(input, offset) != '-' || + character_at(input, offset + 1) != '-') { + return 0; + } + + const auto text{offset + 2}; + if (character_at(input, text) == '>' || + (character_at(input, text) == '-' && + character_at(input, text + 1) == '>')) { + return 0; + } + + // As the text can neither contain two dashes nor end with one, the first two + // dashes after the opening have to be the start of the closing + const auto closing{input.find("--", text)}; + if (closing == std::string_view::npos || + character_at(input, closing + 2) != '>') { + return 0; + } + + return closing + 3 - offset; +} + +// The content of a processing instruction, right after its question mark, +// without the closing question mark and angle bracket +inline auto scan_html_processing_instruction(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + auto position{offset}; + while (position < input.size()) { + if (input[position] == '?') { + if (position + 1 < input.size() && input[position + 1] != '>') { + ++position; + continue; + } + + break; + } + + ++position; + } + + return position - offset; +} + +// A declaration, right after its exclamation mark, without the closing angle +// bracket +inline auto scan_html_declaration(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + auto position{offset}; + while (position < input.size() && input[position] >= 'A' && + input[position] <= 'Z') { + ++position; + } + + if (position == offset) { + return 0; + } + + const auto spaces{scan_spacechars(input, position)}; + if (spaces == 0) { + return 0; + } + + const auto closing{input.find('>', position + spaces)}; + return (closing == std::string_view::npos ? input.size() : closing) - offset; +} + +// A CDATA section, right after its opening bracket, without the closing +// brackets and angle bracket +inline auto scan_html_cdata(const std::string_view input, + const std::size_t offset) noexcept -> std::size_t { + if (offset > input.size() || + input.substr(offset, 6) != std::string_view{"CDATA["}) { + return 0; + } + + auto boundary{offset + 6}; + std::size_t brackets{0}; + for (auto position{offset + 6}; position < input.size(); ++position) { + const auto character{input[position]}; + if (brackets == 2) { + if (character == '>') { + break; + } + + brackets = 0; + boundary = position + 1; + } else if (character == ']') { + ++brackets; + } else { + brackets = 0; + boundary = position + 1; + } + } + + return boundary - offset; +} + +// The lowercase names of the HTML block condition 6 of GFM section 4.6 +constexpr std::array BLOCK_TAG_NAMES{ + {"address", "article", "aside", "base", "basefont", "blockquote", + "body", "caption", "center", "col", "colgroup", "dd", + "details", "dialog", "dir", "div", "dl", "dt", + "fieldset", "figcaption", "figure", "footer", "form", "frame", + "frameset", "h1", "h2", "h3", "h4", "h5", + "h6", "head", "header", "hr", "html", "iframe", + "legend", "li", "link", "main", "menu", "menuitem", + "nav", "noframes", "ol", "optgroup", "option", "p", + "param", "section", "source", "summary", "table", "tbody", + "td", "tfoot", "th", "thead", "title", "tr", + "track", "ul"}}; + +// Returns the lowercase alphanumeric run at the given offset, if it is short +// enough to be a tag name that the HTML block conditions care about +inline auto lowercase_tag_name(const std::string_view input, + const std::size_t offset, + std::array &buffer) noexcept + -> std::string_view { + std::size_t length{0}; + while (offset + length < input.size() && + sourcemeta::core::is_alphanum(input[offset + length])) { + if (length == buffer.size()) { + return {}; + } + + buffer[length] = sourcemeta::core::to_lowercase(input[offset + length]); + ++length; + } + + return {buffer.data(), length}; +} + +// The start condition of an HTML block of GFM section 4.6, returning the +// number of the condition from one to six or zero +inline auto scan_html_block_start(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + if (character_at(input, offset) != '<') { + return 0; + } + + const auto next{character_at(input, offset + 1)}; + if (next == '!') { + const auto after{character_at(input, offset + 2)}; + if (after == '-' && character_at(input, offset + 3) == '-') { + return 2; + } + + if (after == '[' && sourcemeta::core::starts_with_ignore_case( + input.substr(offset + 3), "cdata[")) { + return 5; + } + + return after >= 'A' && after <= 'Z' ? 4 : 0; + } + + if (next == '?') { + return 3; + } + + std::array buffer{}; + const auto name{lowercase_tag_name(input, offset + 1, buffer)}; + if (name == "script" || name == "pre" || name == "textarea" || + name == "style") { + const auto after{character_at(input, offset + 1 + name.size())}; + return is_html_space(after) || after == '>' ? 1 : 0; + } + + auto position{offset + 1}; + if (next == '/') { + ++position; + } + + const auto block_name{lowercase_tag_name(input, position, buffer)}; + if (block_name.empty() || + !std::binary_search(BLOCK_TAG_NAMES.cbegin(), BLOCK_TAG_NAMES.cend(), + block_name)) { + return 0; + } + + position += block_name.size(); + const auto after{character_at(input, position)}; + if (is_html_space(after) || after == '>') { + return 6; + } + + return after == '/' && character_at(input, position + 1) == '>' ? 6 : 0; +} + +// The start condition 7 of an HTML block of GFM section 4.6 +inline auto scan_html_block_start_7(const std::string_view input, + const std::size_t offset) noexcept -> bool { + if (character_at(input, offset) != '<') { + return false; + } + + const auto length{scan_html_tag(input, offset + 1)}; + if (length == 0) { + return false; + } + + auto position{offset + 1 + length}; + while (position < input.size() && + (input[position] == '\t' || input[position] == '\f' || + input[position] == ' ')) { + ++position; + } + + const auto character{character_at(input, position)}; + return character == '\n' || character == '\r'; +} + +// The end conditions of the HTML blocks of GFM section 4.6 +inline auto scan_html_block_end(const std::string_view input, + const std::size_t offset, + const std::size_t condition) noexcept -> bool { + if (offset > input.size()) { + return false; + } + + const auto line{input.substr(offset)}; + switch (condition) { + case 1: { + auto position{line.find(" buffer{}; + const auto name{lowercase_tag_name(line, position + 2, buffer)}; + if ((name == "script" || name == "pre" || name == "textarea" || + name == "style") && + character_at(line, position + 2 + name.size()) == '>') { + return true; + } + + position = line.find("") != std::string_view::npos; + case 3: + return line.find("?>") != std::string_view::npos; + case 4: + return line.find('>') != std::string_view::npos; + case 5: + return line.find("]]>") != std::string_view::npos; + default: + return false; + } +} + +// A link title of GFM section 6.3, which "consists of either a sequence of zero +// or more characters between straight double-quote characters ("), including a +// " character only if it is backslash-escaped, or a sequence of zero or more +// characters between straight single-quote characters ('), including a ' +// character only if it is backslash-escaped, or a sequence of zero or more +// characters between matching parentheses ((...)), including a ( or ) +// character only if it is backslash-escaped" +inline auto scan_link_title(const std::string_view input, + const std::size_t offset) noexcept -> std::size_t { + const auto opening{character_at(input, offset)}; + if (opening != '"' && opening != '\'' && opening != '(') { + return 0; + } + + const auto closing{opening == '(' ? ')' : opening}; + for (auto position{offset + 1}; position < input.size(); ++position) { + const auto character{input[position]}; + // GFM section 2.4: "Any ASCII punctuation character may be + // backslash-escaped" + if (character == '\\' && position + 1 < input.size() && + sourcemeta::core::is_punctuation(input[position + 1])) { + ++position; + continue; + } + + if (character == closing) { + return position + 1 - offset; + } + + if (opening == '(' && character == '(') { + return 0; + } + } + + return 0; +} + +// The start of an ATX heading of GFM section 4.2, including the whitespace +// after its opening sequence +inline auto scan_atx_heading_start(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + auto position{offset}; + while (position < input.size() && input[position] == '#') { + ++position; + } + + const auto hashes{position - offset}; + if (hashes == 0 || hashes > 6) { + return 0; + } + + const auto character{character_at(input, position)}; + if (character == ' ' || character == '\t') { + while (position < input.size() && + (input[position] == ' ' || input[position] == '\t')) { + ++position; + } + + return position - offset; + } + + return character == '\n' || character == '\r' ? position + 1 - offset : 0; +} + +// The underline of a setext heading of GFM section 4.3, returning the level +// of the heading or zero +inline auto scan_setext_heading_line(const std::string_view input, + const std::size_t offset) noexcept + -> std::uint8_t { + const auto marker{character_at(input, offset)}; + if (marker != '=' && marker != '-') { + return 0; + } + + auto position{offset}; + while (position < input.size() && input[position] == marker) { + ++position; + } + + while (position < input.size() && + (input[position] == ' ' || input[position] == '\t')) { + ++position; + } + + const auto character{character_at(input, position)}; + if (character != '\n' && character != '\r') { + return 0; + } + + return marker == '=' ? 1 : 2; +} + +// The opening fence of a fenced code block of GFM section 4.5, returning the +// length of the fence +inline auto scan_open_code_fence(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + const auto marker{character_at(input, offset)}; + if (marker != '`' && marker != '~') { + return 0; + } + + auto position{offset}; + while (position < input.size() && input[position] == marker) { + ++position; + } + + const auto length{position - offset}; + if (length < 3) { + return 0; + } + + while (position < input.size()) { + const auto character{input[position]}; + if (character == '\n' || character == '\r') { + return length; + } + + if (marker == '`' && character == '`') { + return 0; + } + + ++position; + } + + return 0; +} + +// The closing fence of a fenced code block of GFM section 4.5, returning the +// length of the fence +inline auto scan_close_code_fence(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + const auto marker{character_at(input, offset)}; + if (marker != '`' && marker != '~') { + return 0; + } + + auto position{offset}; + while (position < input.size() && input[position] == marker) { + ++position; + } + + const auto length{position - offset}; + if (length < 3) { + return 0; + } + + while (position < input.size() && + (input[position] == ' ' || input[position] == '\t')) { + ++position; + } + + const auto character{character_at(input, position)}; + return character == '\n' || character == '\r' ? length : 0; +} + +// The image media types whose data URLs safe mode keeps +constexpr std::array SAFE_DATA_URL_PREFIXES{ + {"data:image/png", "data:image/gif", "data:image/jpeg", "data:image/webp"}}; + +// Whether a link destination starts with a scheme that can run code or read +// local files, where only a few image data URLs are safe. RFC 2397 Section 3 +// writes a data URL as `dataurl := "data:" [ mediatype ] [ ";base64" ] "," +// data` with `mediatype := [ type "/" subtype ] *( ";" parameter )`, so the +// subtype of an allowed image ends at a semicolon or a comma +inline auto is_dangerous_url(const std::string_view url) noexcept -> bool { + for (const auto prefix : SAFE_DATA_URL_PREFIXES) { + if (sourcemeta::core::starts_with_ignore_case(url, prefix) && + url.size() > prefix.size() && + (url[prefix.size()] == ';' || url[prefix.size()] == ',')) { + return false; + } + } + + return sourcemeta::core::starts_with_ignore_case(url, "javascript:") || + sourcemeta::core::starts_with_ignore_case(url, "vbscript:") || + sourcemeta::core::starts_with_ignore_case(url, "file:") || + sourcemeta::core::starts_with_ignore_case(url, "data:"); +} + +// The start of a footnote definition, including the whitespace after its +// colon +inline auto scan_footnote_definition(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + if (character_at(input, offset) != '[' || + character_at(input, offset + 1) != '^') { + return 0; + } + + auto position{offset + 2}; + while (position < input.size()) { + const auto character{input[position]}; + if (character == ']' || character == ' ' || character == '\r' || + character == '\n' || character == '\t') { + break; + } + + ++position; + } + + if (position == offset + 2 || character_at(input, position) != ']' || + character_at(input, position + 1) != ':') { + return 0; + } + + position += 2; + while (position < input.size() && + (input[position] == ' ' || input[position] == '\t')) { + ++position; + } + + return position - offset; +} + +inline auto scan_table_marker(const std::string_view input, + std::size_t position) noexcept -> std::size_t { + const auto start{position}; + while (position < input.size() && is_line_space(input[position])) { + ++position; + } + + if (character_at(input, position) == ':') { + ++position; + } + + const auto dashes_start{position}; + while (position < input.size() && input[position] == '-') { + ++position; + } + + if (position == dashes_start) { + return 0; + } + + if (character_at(input, position) == ':') { + ++position; + } + + while (position < input.size() && is_line_space(input[position])) { + ++position; + } + + return position - start; +} + +// The end of a table row, which is any whitespace and a line ending +inline auto scan_table_row_end(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + if (offset >= input.size()) { + return 0; + } + + auto position{offset}; + while (position < input.size() && is_line_space(input[position])) { + ++position; + } + + if (character_at(input, position) == '\r') { + ++position; + } + + return character_at(input, position) == '\n' ? position + 1 - offset : 0; +} + +// The delimiter row of a table of GFM section 4.10 +inline auto scan_table_start(const std::string_view input, + const std::size_t offset) noexcept -> std::size_t { + if (offset >= input.size()) { + return 0; + } + + auto position{offset}; + if (input[position] == '|') { + ++position; + } + + const auto first{scan_table_marker(input, position)}; + if (first == 0) { + return 0; + } + + position += first; + while (character_at(input, position) == '|') { + const auto marker{scan_table_marker(input, position + 1)}; + if (marker == 0) { + ++position; + break; + } + + position += 1 + marker; + } + + const auto end{scan_table_row_end(input, position)}; + return end == 0 ? 0 : position + end - offset; +} + +// The content of a table cell, which ends at a line ending or at a pipe that +// is not preceded by a backslash +inline auto scan_table_cell(const std::string_view input, + const std::size_t offset) noexcept -> std::size_t { + auto position{offset}; + while (position < input.size()) { + const auto character{input[position]}; + if (character == '\r' || character == '\n') { + break; + } + + if (character == '|' && + (position == offset || input[position - 1] != '\\')) { + break; + } + + ++position; + } + + return position - offset; +} + +// A pipe that ends a table cell, including the whitespace after it +inline auto scan_table_cell_end(const std::string_view input, + const std::size_t offset) noexcept + -> std::size_t { + if (character_at(input, offset) != '|') { + return 0; + } + + auto position{offset + 1}; + while (position < input.size() && is_line_space(input[position])) { + ++position; + } + + return position - offset; +} + +// A task list item marker of GFM section 5.3 at the start of the content of a +// list item, which "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 (])", where the list item already took +// the spaces, and which needs "at least one whitespace character before any +// other content". A line ending cannot come between the brackets, so the +// whitespace there is one of the other whitespace characters of GFM section 2.1 +inline auto scan_task_list_marker(const std::string_view input, + const std::size_t position) noexcept -> bool { + if (character_at(input, position) != '[' || + character_at(input, position + 2) != ']') { + return false; + } + + const auto state{character_at(input, position + 1)}; + return (is_line_space(state) || state == 'x' || state == 'X') && + is_line_space(character_at(input, position + 3)); +} + +} // namespace sourcemeta::core::markdown + +#endif diff --git a/vendor/core/src/core/unicode/include/sourcemeta/core/unicode.h b/vendor/core/src/core/unicode/include/sourcemeta/core/unicode.h index 70ec8ed06..f3d6e9d60 100644 --- a/vendor/core/src/core/unicode/include/sourcemeta/core/unicode.h +++ b/vendor/core/src/core/unicode/include/sourcemeta/core/unicode.h @@ -8,7 +8,8 @@ #include #include // std::size_t -#include // std::uint8_t +#include // std::uint8_t, std::uint64_t +#include // std::memcpy #include // std::istream #include // std::optional #include // std::ostream @@ -289,6 +290,50 @@ constexpr auto utf8_sequence_size(const std::string_view input) -> std::size_t { return size; } +/// @ingroup unicode +/// Check whether the given input consists entirely of well-formed UTF-8 +/// sequences per RFC 3629 Section 4, without allocating. ASCII runs are +/// skipped eight bytes at a time. For example: +/// +/// ```cpp +/// #include +/// #include +/// +/// assert(sourcemeta::core::is_valid_utf8("caf\xC3\xA9")); +/// assert(!sourcemeta::core::is_valid_utf8("a\xFF")); +/// ``` +inline auto is_valid_utf8(const std::string_view input) noexcept -> bool { + constexpr std::uint64_t HIGH_BITS{0x8080808080808080ULL}; + const auto size{input.size()}; + std::size_t position{0}; + while (position < size) { + // Comparing what is left rather than the position past the word keeps the + // sum of a position and a word from wrapping around + if (size - position >= 8) { + std::uint64_t word{0}; + std::memcpy(&word, input.data() + position, 8); + if ((word & HIGH_BITS) == 0) { + position += 8; + continue; + } + } + + if (static_cast(input[position]) < 0x80) { + position += 1; + continue; + } + + const auto length{utf8_sequence_size(input.substr(position))}; + if (length == 0) { + return false; + } + + position += length; + } + + return true; +} + /// @ingroup unicode /// Check whether the given byte is a UTF-8 continuation byte (%x80-BF per /// RFC 3629 Section 4). For example: diff --git a/vendor/core/src/core/uri/include/sourcemeta/core/uri.h b/vendor/core/src/core/uri/include/sourcemeta/core/uri.h index d65156e16..0e60a95bf 100644 --- a/vendor/core/src/core/uri/include/sourcemeta/core/uri.h +++ b/vendor/core/src/core/uri/include/sourcemeta/core/uri.h @@ -11,9 +11,10 @@ #include // NOLINTEND(misc-include-cleaner) +#include // std::array #include // std::convertible_to, std::same_as #include // std::size_t, std::ptrdiff_t -#include // std::uint32_t +#include // std::uint8_t, std::uint32_t #include // std::filesystem #include // std::istream #include // std::forward_iterator_tag @@ -937,6 +938,102 @@ class SOURCEMETA_CORE_URI_EXPORT URI { } } + /// Percent-encode the octets of a string that cannot appear where they are + /// in a URI reference, appending the result to a string like output sink. + /// Unlike `escape`, the unreserved characters, the sub-delimiters, the colon, + /// the at sign, the slash, the question mark, and every valid percent-encoded + /// triplet pass through, so the delimiters of a URI reference survive and an + /// already encoded string is not encoded twice. Following RFC 3986, the + /// number sign only passes through once, as it introduces the fragment, and + /// the square brackets only pass through around the IP literal host of an + /// authority, the only place they may appear. The output must not alias the + /// input. + /// For example: + /// + /// ```cpp + /// #include + /// #include + /// #include + /// + /// std::string output; + /// sourcemeta::core::URI::escape_reference("http://[::1]/a b?c#d#e", output); + /// assert(output == "http://[::1]/a%20b?c#d%23e"); + /// ``` + template + static auto escape_reference(const std::string_view input, Output &output) + -> void { + // RFC 3986 Section 2.2 and Section 2.3: the unreserved characters, the + // sub-delims, and the gen-delims other than the square brackets and the + // number sign + static constexpr std::array PASS_THROUGH{{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 + 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 0x50 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, // 0x70 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x80 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xA0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xB0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xC0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xD0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xE0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 0xF0 + }}; + + bool in_fragment{false}; + // The square brackets are rare, so the IP literal is only located once + // one of them shows up + bool literal_located{false}; + std::pair literal{std::string_view::npos, + std::string_view::npos}; + std::size_t run_start{0}; + for (std::size_t position = 0; position < input.size(); position += 1) { + const auto byte{static_cast(input[position])}; + // RFC 3986 Section 2.1: pct-encoded = "%" HEXDIG HEXDIG + if (PASS_THROUGH[byte] != 0 || + (byte == '%' && is_percent_triplet(input, position))) { + continue; + } + + // RFC 3986 Section 3.5: "A fragment identifier component is indicated + // by the presence of a number sign ("#") character and terminated by + // the end of the URI", where fragment = *( pchar / "/" / "?" ) leaves no + // room for another number sign + if (byte == '#' && !in_fragment) { + in_fragment = true; + continue; + } + + if (byte == '[' || byte == ']') [[unlikely]] { + if (!literal_located) { + literal = ip_literal_brackets(input); + literal_located = true; + } + + if (position == literal.first || position == literal.second) { + continue; + } + } + + // The characters that pass through are appended in runs + output.append(input.substr(run_start, position - run_start)); + // RFC 3986 Section 2.1: percent-encode with uppercase hexadecimal + const auto high{static_cast((byte >> 4U) & 0x0FU)}; + const auto low{static_cast(byte & 0x0FU)}; + const std::array encoded{ + {'%', static_cast(high < 10 ? '0' + high : 'A' + high - 10), + static_cast(low < 10 ? '0' + low : 'A' + low - 10)}}; + output.append(std::string_view{encoded.data(), encoded.size()}); + run_start = position + 1; + } + + output.append(input.substr(run_start)); + } + /// Append a percent-encoded name and value pair to a query, form body, or /// fragment under construction (RFC 3986 Section 2.1), joining it to any /// preceding pair. The caller writes the opening character of a fresh @@ -1341,6 +1438,11 @@ class SOURCEMETA_CORE_URI_EXPORT URI { private: auto parse(std::string_view input) -> void; + // The positions of the square brackets around the IP literal host of a URI + // reference, if it has one + [[nodiscard]] static auto ip_literal_brackets(std::string_view input) noexcept + -> std::pair; + // WHATWG URL Section 5.1: "Replace any 0x2B (+) in name and value with 0x20 // (SP)" and then percent-decode, which Section 1.3 defines to append a "%" // that is not followed by two hexadecimal digits as it appears rather than diff --git a/vendor/core/src/core/uri/parse.cc b/vendor/core/src/core/uri/parse.cc index 1baa97ce7..454b61ecb 100644 --- a/vendor/core/src/core/uri/parse.cc +++ b/vendor/core/src/core/uri/parse.cc @@ -10,6 +10,7 @@ #include // assert #include // std::isalpha, std::isdigit #include // std::from_chars +#include // std::size_t #include // std::uint64_t #include // std::numeric_limits #include // std::optional @@ -154,6 +155,43 @@ auto parse_port(const std::string_view input, } } +// RFC 3986 Section 3.2.2: IP-literal = "[" ( IPv6address / IPvFuture ) "]", +// with IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) +auto is_ip_literal(const std::string_view content) -> bool { + if (content.empty()) { + return false; + } + + if (content.front() != 'v' && content.front() != 'V') { + return sourcemeta::core::is_ipv6(content); + } + + std::string_view::size_type position{1}; + while (position < content.size() && hex_digit_value(content[position]) >= 0) { + position += 1; + } + + if (position == 1 || position >= content.size() || + content[position] != URI_DOT) { + return false; + } + + position += 1; + if (position >= content.size()) { + return false; + } + + for (; position < content.size(); position += 1) { + const auto character{content[position]}; + if (!uri_is_unreserved(character) && !uri_is_sub_delim(character) && + character != URI_COLON) { + return false; + } + } + + return true; +} + template auto parse_ipv6(const std::string_view input, std::string_view::size_type &position) @@ -655,6 +693,61 @@ auto URI::is_scheme(const std::string_view input) noexcept -> bool { return true; } +auto URI::ip_literal_brackets(const std::string_view input) noexcept + -> std::pair { + const std::pair none{std::string_view::npos, + std::string_view::npos}; + // RFC 3986 Section 3.2: "The authority component is preceded by a double + // slash ("//") and is terminated by the next slash ("/"), question mark + // ("?"), or number sign ("#") character, or by the end of the URI" + std::size_t authority_start{0}; + const auto delimiter{input.find_first_of(":/?#")}; + if (delimiter != std::string_view::npos && input[delimiter] == ':' && + URI::is_scheme(input.substr(0, delimiter)) && + input.substr(delimiter + 1, 2) == "//") { + authority_start = delimiter + 3; + } else if (input.starts_with("//")) { + authority_start = 2; + } else { + return none; + } + + auto authority_end{input.find_first_of("/?#", authority_start)}; + if (authority_end == std::string_view::npos) { + authority_end = input.size(); + } + + // RFC 3986 Section 3.2: authority = [ userinfo "@" ] host [ ":" port ], + // where neither the host nor the port can contain an at sign + const auto userinfo_end{ + input.substr(authority_start, authority_end - authority_start) + .rfind('@')}; + const auto host{userinfo_end == std::string_view::npos + ? authority_start + : authority_start + userinfo_end + 1}; + + // RFC 3986 Section 3.2.2: "A host identified by an Internet Protocol literal + // address, version 6 [RFC3513] or later, is distinguished by enclosing the + // IP literal within square brackets ("[" and "]"). This is the only place + // where square bracket characters are allowed in the URI syntax" + if (host >= authority_end || input[host] != '[') { + return none; + } + + const auto closing{input.find(']', host)}; + if (closing >= authority_end || + (closing + 1 != authority_end && input[closing + 1] != ':')) { + return none; + } + + // Brackets around anything else cannot appear in a URI reference + if (!is_ip_literal(input.substr(host + 1, closing - host - 1))) { + return none; + } + + return {host, closing}; +} + auto URI::is_gen_delim(const char character) noexcept -> bool { return uri_is_gen_delim(character); } diff --git a/vendor/core/src/lang/benchmark/CMakeLists.txt b/vendor/core/src/lang/benchmark/CMakeLists.txt new file mode 100644 index 000000000..e8fcf552f --- /dev/null +++ b/vendor/core/src/lang/benchmark/CMakeLists.txt @@ -0,0 +1,49 @@ +sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME benchmark + SOURCES benchmark.cc) + +if(SOURCEMETA_CORE_INSTALL) + sourcemeta_library_install(NAMESPACE sourcemeta PROJECT core NAME benchmark) +endif() + +target_link_libraries(sourcemeta_core_benchmark + PUBLIC sourcemeta::core::preprocessor) +target_link_libraries(sourcemeta_core_benchmark + PRIVATE sourcemeta::core::io) +target_link_libraries(sourcemeta_core_benchmark + PRIVATE sourcemeta::core::json) +target_link_libraries(sourcemeta_core_benchmark + PRIVATE sourcemeta::core::options) +target_link_libraries(sourcemeta_core_benchmark + PRIVATE sourcemeta::core::process) + +# A dedicated, always-static entry point library. Linking it into every +# benchmark executable provides a default `main()` through static archive +# resolution, while a suite that defines its own `main()` transparently +# overrides it. This mirrors how the test framework ships its own entry point. +add_library(sourcemeta_core_benchmark_main STATIC benchmark_main.cc) +add_library(sourcemeta::core::benchmark_main ALIAS sourcemeta_core_benchmark_main) +sourcemeta_add_default_options(PRIVATE sourcemeta_core_benchmark_main) +# Public so the dependency propagates to consumers and CMake orders this archive +# ahead of the framework, keeping the entry point's reference to the runner +# resolvable at link time +target_link_libraries(sourcemeta_core_benchmark_main + PUBLIC sourcemeta::core::benchmark) +set_target_properties(sourcemeta_core_benchmark_main + PROPERTIES EXPORT_NAME core::benchmark_main) + +# We don't want consumers to be bothered with this +if(PROJECT_IS_TOP_LEVEL) + sourcemeta_clang_tidy_attempt_enable(TARGET sourcemeta_core_benchmark_main) +endif() + +if(SOURCEMETA_CORE_INSTALL) + include(GNUInstallDirs) + install(TARGETS sourcemeta_core_benchmark_main + EXPORT sourcemeta_core_benchmark_main + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + COMPONENT sourcemeta_core_dev) + install(EXPORT sourcemeta_core_benchmark_main + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/core" + NAMESPACE sourcemeta:: + COMPONENT sourcemeta_core_dev) +endif() diff --git a/vendor/core/src/lang/benchmark/benchmark.cc b/vendor/core/src/lang/benchmark/benchmark.cc new file mode 100644 index 000000000..dc0f28f2f --- /dev/null +++ b/vendor/core/src/lang/benchmark/benchmark.cc @@ -0,0 +1,420 @@ +#include +#include +#include +#include +#include + +#include // std::max, std::min +#include // std::array +#include // std::llround +#include // std::size_t +#include // std::uint64_t +#include // EXIT_SUCCESS, EXIT_FAILURE +#include // std::exception +#include // std::filesystem::path +#include // std::less +#include // std::setprecision, std::fixed +#include // std::cout, std::cerr +#include // std::ostream +#include // std::ostringstream +#include // std::string +#include // std::string_view +#include // std::thread::hardware_concurrency +#include // std::move +#include // std::vector + +namespace { +using namespace std::string_view_literals; + +constexpr auto BENCHMARK_HASH_VERSION{ + sourcemeta::core::JSON::Object::hash("version"sv)}; +constexpr auto BENCHMARK_HASH_CONTEXT{ + sourcemeta::core::JSON::Object::hash("context"sv)}; +constexpr auto BENCHMARK_HASH_CORES{ + sourcemeta::core::JSON::Object::hash("cores"sv)}; +constexpr auto BENCHMARK_HASH_BENCHMARKS{ + sourcemeta::core::JSON::Object::hash("benchmarks"sv)}; +constexpr auto BENCHMARK_HASH_NAME{ + sourcemeta::core::JSON::Object::hash("name"sv)}; +constexpr auto BENCHMARK_HASH_ITERATIONS{ + sourcemeta::core::JSON::Object::hash("iterations"sv)}; +constexpr auto BENCHMARK_HASH_REPETITIONS{ + sourcemeta::core::JSON::Object::hash("repetitions"sv)}; +constexpr auto BENCHMARK_HASH_REAL_TIME{ + sourcemeta::core::JSON::Object::hash("realTime"sv)}; +constexpr auto BENCHMARK_HASH_CPU_TIME{ + sourcemeta::core::JSON::Object::hash("cpuTime"sv)}; +constexpr auto BENCHMARK_HASH_COLD_TIME{ + sourcemeta::core::JSON::Object::hash("coldTime"sv)}; + +// What the shape of this document is, so that a reader given one written by +// some other version has something to refuse on rather than a surprise +constexpr std::int64_t FORMAT_VERSION{1}; + +struct RegisteredBenchmark { + std::string name; + std::string_view file; + int line; + std::function body; +}; + +struct Measurement { + std::string name; + std::uint64_t iterations; + double real_time; + std::optional cpu_time; + // What the very first execution cost, before anything the benchmark touches + // had a chance to warm up. A wide gap against the reported time is the sign + // of a cache, a lazy initialisation, or an allocator that settles + double cold_time; +}; + +auto base_name(const std::string_view path) -> std::string { + return std::filesystem::path{path}.filename().string(); +} + +auto registry() -> std::vector & { + static std::vector benchmarks; + return benchmarks; +} + +// How long one measurement is given before the amount of work it covers is +// taken as enough to time reliably +constexpr std::chrono::nanoseconds MINIMUM_RUN_TIME{170'000'000}; + +// How many times that work is then measured. A single window can be lost to +// whatever else the machine decided to do while it was open, and no number of +// iterations inside one window makes up for that. Measuring the same work +// several times over does, and the fastest of those is the one least +// disturbed, as interference only ever makes code slower. Together these cost +// about what a single longer measurement used to +constexpr std::size_t REPETITIONS{3}; + +// A run that cannot reach the target time within this many iterations is +// reported as it stands rather than grown further +constexpr std::uint64_t MAXIMUM_ITERATIONS{1'000'000'000'000}; + +constexpr std::uint64_t INITIAL_ITERATIONS{1}; + +// Aim beyond the target rather than exactly at it, so that a run which lands +// just short does not need another attempt +constexpr double OVERSHOOT{1.4}; + +// A run too short to extrapolate from grows by a flat factor instead, as +// scaling from a measurement dominated by noise overshoots wildly +constexpr double BLIND_GROWTH{10.0}; +constexpr double BLIND_THRESHOLD{0.1}; + +auto next_iterations(const std::uint64_t current, + const std::chrono::nanoseconds elapsed) -> std::uint64_t { + const auto target{static_cast(MINIMUM_RUN_TIME.count())}; + const auto measured{std::max(static_cast(elapsed.count()), 1.0)}; + const auto multiplier{(measured / target) > BLIND_THRESHOLD + ? (target * OVERSHOOT / measured) + : BLIND_GROWTH}; + const auto grown{ + std::llround(std::max(multiplier * static_cast(current), + static_cast(current) + 1.0))}; + return std::min(static_cast(grown), MAXIMUM_ITERATIONS); +} + +auto measure(const RegisteredBenchmark &benchmark) + -> std::optional { + auto iterations{INITIAL_ITERATIONS}; + std::optional cold{std::nullopt}; + std::optional real{std::nullopt}; + std::optional cpu{std::nullopt}; + std::size_t repetitions{0}; + auto settled{false}; + + while (true) { + sourcemeta::core::BenchmarkState state{iterations}; + benchmark.body(state); + + if (!state.measured()) { + return std::nullopt; + } + + const auto elapsed{state.real_time()}; + if (!cold.has_value()) { + cold = static_cast(elapsed.count()) / + static_cast(iterations); + } + + // Growing stops for good once the work is large enough to time, as a + // later repetition that comes in faster is the point of repeating rather + // than a sign that there is too little work to measure + if (!settled) { + settled = elapsed >= MINIMUM_RUN_TIME || iterations >= MAXIMUM_ITERATIONS; + if (!settled) { + iterations = next_iterations(iterations, elapsed); + continue; + } + } + + const auto count{static_cast(iterations)}; + const auto candidate{static_cast(elapsed.count()) / count}; + if (!real.has_value() || candidate < real.value()) { + real = candidate; + cpu = state.cpu_time().has_value() + ? std::optional{static_cast( + state.cpu_time().value().count()) / + count} + : std::nullopt; + } + + repetitions += 1; + if (repetitions >= REPETITIONS) { + return Measurement{.name = benchmark.name, + .iterations = iterations, + .real_time = real.value(), + .cpu_time = cpu, + .cold_time = cold.value()}; + } + } +} + +auto print_usage(const std::string_view program) -> void { + std::cout << "Usage: " << std::filesystem::path{program}.stem().string() + << " [options]\n\n" + << "Run the registered benchmarks.\n\n" + << "Options:\n" + << " -f, --filter Only run benchmarks whose name " + "contains \n" + << " -o, --output Also write the results as JSON to " + "\n" + << " -h, --help Show this message\n"; +} + +auto print_environment() -> void { + const auto cores{std::thread::hardware_concurrency()}; + if (cores > 0) { + std::cout << "Running on " << cores << " processors\n"; + } +} + +// A benchmark that takes seconds per iteration and one that takes nanoseconds +// both have to line up in the same table, so the unit follows the magnitude +auto format_duration(const double nanoseconds) -> std::string { + struct Unit { + double factor; + std::string_view suffix; + }; + + static constexpr std::array UNITS{ + {{.factor = 1.0, .suffix = "ns"}, + {.factor = 1'000.0, .suffix = "us"}, + {.factor = 1'000'000.0, .suffix = "ms"}, + {.factor = 1'000'000'000.0, .suffix = "s"}}}; + + auto chosen{UNITS.front()}; + for (const auto &unit : UNITS) { + if (nanoseconds >= unit.factor) { + chosen = unit; + } + } + + std::ostringstream stream; + stream << std::fixed << std::setprecision(2) << (nanoseconds / chosen.factor) + << " " << chosen.suffix; + return stream.str(); +} + +auto print_measurement(const Measurement &measurement) -> void { + std::cout << measurement.name << "\n" + << " time: " << format_duration(measurement.real_time); + if (measurement.cpu_time.has_value()) { + std::cout << ", cpu: " << format_duration(measurement.cpu_time.value()); + } + + std::cout << ", first: " << format_duration(measurement.cold_time) + << ", iterations: " << measurement.iterations << "\n"; +} + +// Every duration is nanoseconds for one iteration, and the real one is the +// fastest of the repetitions rather than an average over them +auto to_json(const std::vector &measurements) + -> sourcemeta::core::JSON { + auto context{sourcemeta::core::JSON::make_object()}; + const auto cores{std::thread::hardware_concurrency()}; + if (cores > 0) { + context.assign_assume_new( + "cores", sourcemeta::core::JSON{static_cast(cores)}, + BENCHMARK_HASH_CORES); + } + + auto entries{sourcemeta::core::JSON::make_array()}; + for (const auto &measurement : measurements) { + auto entry{sourcemeta::core::JSON::make_object()}; + entry.assign_assume_new("name", sourcemeta::core::JSON{measurement.name}, + BENCHMARK_HASH_NAME); + entry.assign_assume_new("iterations", + sourcemeta::core::JSON{static_cast( + measurement.iterations)}, + BENCHMARK_HASH_ITERATIONS); + entry.assign_assume_new( + "repetitions", + sourcemeta::core::JSON{static_cast(REPETITIONS)}, + BENCHMARK_HASH_REPETITIONS); + entry.assign_assume_new("realTime", + sourcemeta::core::JSON{measurement.real_time}, + BENCHMARK_HASH_REAL_TIME); + + // A platform that cannot account for processor time says so, rather than + // standing the elapsed time in for it, which would read as a benchmark + // that spent every moment of it computing + entry.assign_assume_new( + "cpuTime", + measurement.cpu_time.has_value() + ? sourcemeta::core::JSON{measurement.cpu_time.value()} + : sourcemeta::core::JSON{nullptr}, + BENCHMARK_HASH_CPU_TIME); + + entry.assign_assume_new("coldTime", + sourcemeta::core::JSON{measurement.cold_time}, + BENCHMARK_HASH_COLD_TIME); + entries.push_back(std::move(entry)); + } + + auto document{sourcemeta::core::JSON::make_object()}; + document.assign_assume_new("version", sourcemeta::core::JSON{FORMAT_VERSION}, + BENCHMARK_HASH_VERSION); + document.assign_assume_new("context", std::move(context), + BENCHMARK_HASH_CONTEXT); + document.assign_assume_new("benchmarks", std::move(entries), + BENCHMARK_HASH_BENCHMARKS); + return document; +} + +} // namespace + +namespace sourcemeta::core { + +BenchmarkState::BenchmarkState(const std::uint64_t iterations) + : iterations_{iterations} {} + +auto BenchmarkState::iterations() const -> std::uint64_t { + return this->iterations_; +} + +auto BenchmarkState::measured() const -> bool { return this->finished_; } + +auto BenchmarkState::real_time() const -> std::chrono::nanoseconds { + return this->real_elapsed_; +} + +auto BenchmarkState::cpu_time() const + -> std::optional { + return this->cpu_elapsed_; +} + +auto BenchmarkState::start() -> void { + this->started_ = true; + this->cpu_start_ = process_usage().cpu_time; + this->real_start_ = std::chrono::steady_clock::now(); +} + +auto BenchmarkState::finish() -> void { + if (this->finished_) { + return; + } + + const auto real_end{std::chrono::steady_clock::now()}; + const auto cpu_end{process_usage().cpu_time}; + this->real_elapsed_ = real_end - this->real_start_; + if (this->cpu_start_.has_value() && cpu_end.has_value()) { + this->cpu_elapsed_ = cpu_end.value() - this->cpu_start_.value(); + } + + this->finished_ = true; +} + +#if !defined(__clang__) && !defined(__GNUC__) +auto benchmark_use_char_pointer(const volatile char *) -> void {} +#endif + +auto benchmark_register(std::string_view name, std::string_view file, int line, + std::function body) -> int { + registry().push_back({.name = std::string{name}, + .file = file, + .line = line, + .body = std::move(body)}); + return 0; +} + +auto benchmark_run(int argc, char **argv) -> int { + Options options; + options.option("filter", {"f"}); + options.option("output", {"o"}); + options.flag("help", {"h"}); + + try { + options.parse(argc, argv); + } catch (const OptionsError &) { + print_usage(argv[0]); + return EXIT_FAILURE; + } + + if (options.contains("help")) { + print_usage(argv[0]); + return EXIT_SUCCESS; + } + + std::string_view needle; + if (options.contains("filter") && !options.at("filter").empty()) { + needle = options.at("filter").front(); + } + + std::vector selected; + for (const auto &entry : registry()) { + if (needle.empty() || entry.name.contains(needle)) { + selected.push_back(&entry); + } + } + + // An unfiltered run that selects nothing means registration is broken, which + // must not pass as a successful run. A filter that matches nothing is instead + // an ordinary thing to ask for interactively + if (selected.empty() && needle.empty()) { + std::cerr << "error: No benchmarks were registered\n"; + return EXIT_FAILURE; + } + + print_environment(); + + std::vector measurements; + measurements.reserve(selected.size()); + for (const auto *entry : selected) { + auto measurement{measure(*entry)}; + if (!measurement.has_value()) { + std::cerr << "error: The benchmark did not iterate over its state\n" + << " at benchmark " << entry->name << "\n" + << " at source location " << base_name(entry->file) << ":" + << entry->line << "\n"; + return EXIT_FAILURE; + } + + print_measurement(measurement.value()); + measurements.push_back(std::move(measurement).value()); + } + + if (options.contains("output") && !options.at("output").empty()) { + const std::filesystem::path destination{options.at("output").front()}; + const auto document{to_json(measurements)}; + + try { + write_file(destination, [&document](std::ostream &stream) { + prettify(document, stream); + stream << "\n"; + }); + } catch (const std::exception &error) { + std::cerr << "error: " << error.what() << "\n" + << " at file path " << destination.string() << "\n"; + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} + +} // namespace sourcemeta::core diff --git a/vendor/core/src/lang/benchmark/benchmark_main.cc b/vendor/core/src/lang/benchmark/benchmark_main.cc new file mode 100644 index 000000000..07b59d764 --- /dev/null +++ b/vendor/core/src/lang/benchmark/benchmark_main.cc @@ -0,0 +1,5 @@ +#include + +auto main(int argc, char **argv) -> int { + return sourcemeta::core::benchmark_run(argc, argv); +} diff --git a/vendor/core/src/lang/benchmark/include/sourcemeta/core/benchmark.h b/vendor/core/src/lang/benchmark/include/sourcemeta/core/benchmark.h new file mode 100644 index 000000000..0b50f1337 --- /dev/null +++ b/vendor/core/src/lang/benchmark/include/sourcemeta/core/benchmark.h @@ -0,0 +1,281 @@ +#ifndef SOURCEMETA_CORE_BENCHMARK_H_ +#define SOURCEMETA_CORE_BENCHMARK_H_ + +#ifndef SOURCEMETA_CORE_BENCHMARK_EXPORT +#include +#endif + +#include + +#include // std::chrono::nanoseconds, std::chrono::steady_clock +#include // std::uint64_t +#include // std::function +#include // std::optional +#include // std::string_view +#include // std::is_trivially_copyable_v + +#if defined(_MSC_VER) +#include // _ReadWriteBarrier +#endif + +/// @defgroup benchmark Benchmark +/// @brief A minimal microbenchmarking framework +/// +/// This functionality is included as follows: +/// +/// ```cpp +/// #include +/// ``` + +namespace sourcemeta::core { + +// Exporting symbols that depends on the standard C++ library is considered +// safe. +// https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-2-c4275?view=msvc-170&redirectedfrom=MSDN +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4251 4275) +#endif + +/// @ingroup benchmark +/// +/// The state of one benchmark run, i.e. how many iterations to perform and the +/// time they took. A benchmark body obtains it from the registration macro and +/// consumes it by iterating over it. +class SOURCEMETA_CORE_BENCHMARK_EXPORT BenchmarkState { +public: + /// Prepare a run of the given number of iterations. + explicit BenchmarkState(const std::uint64_t iterations); + + /// The value a loop iteration yields. It carries nothing, as the loop exists + /// only to repeat its body a known number of times. + struct [[maybe_unused]] Value {}; + + /// Walks the remaining iterations of a run. Every member is defined here on + /// purpose, i.e. the loop must cost a decrement and a compare, not a call + /// into another translation unit, and a nested class of an exported class is + /// not itself exported on Windows. + class Iterator { + public: + /// Construct the sentinel that the loop compares against. + Iterator() : remaining_{0}, parent_{nullptr} {} + + /// Construct the position that walks the given run. + explicit Iterator(BenchmarkState *const parent) + : remaining_{parent->iterations_}, parent_{parent} {} + + /// Yield the current iteration. + SOURCEMETA_FORCEINLINE auto operator*() const -> Value { return {}; } + + /// Advance to the next iteration. + SOURCEMETA_FORCEINLINE auto operator++() -> Iterator & { + this->remaining_ -= 1; + return *this; + } + + /// Report whether the run has iterations left, stopping the clock when it + /// does not. + SOURCEMETA_FORCEINLINE auto operator!=(const Iterator &other) const + -> bool { + if (this->remaining_ != other.remaining_) [[likely]] { + return true; + } + + // The sentinel carries no run to stop, and a comparison repeated after + // the loop has already ended must not restate the elapsed time + if (this->parent_ != nullptr) { + this->parent_->finish(); + } + + return false; + } + + private: + std::uint64_t remaining_; + BenchmarkState *parent_; + }; + + /// The position the loop starts from. + SOURCEMETA_FORCEINLINE auto begin() -> Iterator { return Iterator{this}; } + + /// The sentinel the loop stops at. Obtaining it starts the clock, so that as + /// little as possible of the caller's setup falls inside the measurement. + SOURCEMETA_FORCEINLINE auto end() -> Iterator { + this->start(); + return {}; + } + + /// How many iterations this run was asked to perform. + [[nodiscard]] auto iterations() const -> std::uint64_t; + /// Whether the body actually iterated. + [[nodiscard]] auto measured() const -> bool; + /// How long the iterations took on the clock. + [[nodiscard]] auto real_time() const -> std::chrono::nanoseconds; + /// How much processor time the iterations consumed, where the platform can + /// answer. + [[nodiscard]] auto cpu_time() const + -> std::optional; + +private: + auto start() -> void; + auto finish() -> void; + + std::uint64_t iterations_; + bool started_{false}; + bool finished_{false}; + std::chrono::steady_clock::time_point real_start_{}; + std::chrono::nanoseconds real_elapsed_{0}; + std::optional cpu_start_{std::nullopt}; + std::optional cpu_elapsed_{std::nullopt}; +}; + +// Only a platform without inline assembly needs an opaque sink to make a value +// escape, so it is not declared anywhere else. Defining it unconditionally +// would leave a function that no build using assembly can ever reach +#if !defined(__clang__) && !defined(__GNUC__) + +/// @ingroup benchmark +/// +/// Consume a pointer without looking at it. Only the platforms that offer no +/// inline assembly rely on this. +SOURCEMETA_CORE_BENCHMARK_EXPORT +auto benchmark_use_char_pointer(const volatile char *pointer) -> void; + +#endif + +// Inline assembly is the only portable way to tell a compiler that a value has +// escaped, and an empty instruction sequence is what makes the barrier free. +// Without it the optimiser deletes the very work under measurement, silently, +// and the benchmark reports a result that was never computed. +// +// The constraint strings below are those of Google Benchmark, which is licensed +// under Apache-2.0, at +// https://github.com/google/benchmark/blob/v1.8.5/include/benchmark/benchmark.h +// They are reproduced rather than reinvented because they are the most +// exercised form of this barrier in the wild, and because the details are not +// guessable. Clang wants the register alternative first while GCC wants memory +// first, and GCC additionally copies the whole argument unless a value that is +// neither trivially copyable nor register sized is constrained to memory alone, +// per https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105519 +// +// A second library arrived at the same code independently, i.e. nanobench +// records that it moved off Facebook's folly after hitting compilation problems +// and settled on these exact constraints +// +// NOLINTBEGIN(hicpp-no-assembler) + +/// @ingroup benchmark +/// +/// Keep a value the compiler would otherwise discard. For example: +/// +/// ```cpp +/// #include +/// +/// BENCHMARK(Addition) { +/// for (auto iteration : state) { +/// auto result{1 + 1}; +/// sourcemeta::core::benchmark_do_not_optimize(result); +/// } +/// } +/// ``` +template +SOURCEMETA_FORCEINLINE inline auto benchmark_do_not_optimize(Type &value) + -> void { +#if defined(__clang__) + asm volatile("" : "+r,m"(value) : : "memory"); +#elif defined(__GNUC__) + if constexpr (std::is_trivially_copyable_v && + sizeof(Type) <= sizeof(void *)) { + asm volatile("" : "+m,r"(value) : : "memory"); + } else { + asm volatile("" : "+m"(value) : : "memory"); + } +#elif defined(_MSC_VER) + benchmark_use_char_pointer(&reinterpret_cast(value)); + _ReadWriteBarrier(); +#else + benchmark_use_char_pointer(&reinterpret_cast(value)); +#endif +} + +/// @ingroup benchmark +/// +/// Keep a value the compiler would otherwise discard, where the caller holds it +/// by constant reference or produced it as a temporary. For example: +/// +/// ```cpp +/// #include +/// +/// BENCHMARK(Addition) { +/// const auto left{1}; +/// for (auto iteration : state) { +/// sourcemeta::core::benchmark_do_not_optimize(left + 1); +/// } +/// } +/// ``` +template +SOURCEMETA_FORCEINLINE inline auto benchmark_do_not_optimize(const Type &value) + -> void { +#if defined(__clang__) + asm volatile("" : : "r,m"(value) : "memory"); +#elif defined(__GNUC__) + if constexpr (std::is_trivially_copyable_v && + sizeof(Type) <= sizeof(void *)) { + asm volatile("" : : "r,m"(value) : "memory"); + } else { + asm volatile("" : : "m"(value) : "memory"); + } +#elif defined(_MSC_VER) + benchmark_use_char_pointer(&reinterpret_cast(value)); + _ReadWriteBarrier(); +#else + benchmark_use_char_pointer(&reinterpret_cast(value)); +#endif +} + +// NOLINTEND(hicpp-no-assembler) + +/// @ingroup benchmark +/// +/// Register a benchmark by name with a callable body. Returns a dummy value so +/// it can be used to initialise a namespace-scope variable. +SOURCEMETA_CORE_BENCHMARK_EXPORT +auto benchmark_register(std::string_view name, std::string_view file, int line, + std::function body) -> int; + +/// @ingroup benchmark +/// +/// Run every registered benchmark, optionally filtered, and return a process +/// exit code. +SOURCEMETA_CORE_BENCHMARK_EXPORT +auto benchmark_run(int argc, char **argv) -> int; + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +} // namespace sourcemeta::core + +// The registration symbol is a namespace-scope object whose initializer runs +// the registry call, which no static initialization check can prove +// non-throwing +// NOLINTBEGIN(cert-err58-cpp,bugprone-throwing-static-initialization) + +// The body takes its state as a parameter that the caller never spells, which +// is what keeps the reported label out of the identifier namespace and off +// every naming rule that would otherwise apply to it +#define SOURCEMETA_CORE_BENCHMARK_REGISTER(name) \ + static auto sourcemeta_benchmark_body_##name( \ + ::sourcemeta::core::BenchmarkState &) \ + ->void; \ + [[maybe_unused]] static const int sourcemeta_benchmark_registration_##name = \ + ::sourcemeta::core::benchmark_register( \ + #name, __FILE__, __LINE__, &sourcemeta_benchmark_body_##name); \ + static auto sourcemeta_benchmark_body_##name( \ + ::sourcemeta::core::BenchmarkState &state) \ + ->void + +#define BENCHMARK(name) SOURCEMETA_CORE_BENCHMARK_REGISTER(name) +// NOLINTEND(cert-err58-cpp,bugprone-throwing-static-initialization) + +#endif diff --git a/vendor/core/src/lang/numeric/decimal.cc b/vendor/core/src/lang/numeric/decimal.cc index 198078aa2..e488d9a86 100644 --- a/vendor/core/src/lang/numeric/decimal.cc +++ b/vendor/core/src/lang/numeric/decimal.cc @@ -773,9 +773,6 @@ auto Decimal::to_string() const -> std::string { } else if (this->coefficient_ == 0 && ((this->flags_ & FLAG_BIG) == 0)) { decimal_place = -1 + ((((this->exponent_ + 2) % 3) + 3) % 3); } else { - decimal_place = integer_digit_count + - ((((integer_digit_count - 1) % 3) + 3) % 3) - - ((((integer_digit_count - 1) % 3) + 3) % 3); auto adjusted = integer_digit_count - 1; auto remainder = ((adjusted % 3) + 3) % 3; decimal_place = 1 + remainder; diff --git a/vendor/core/src/lang/text/include/sourcemeta/core/text.h b/vendor/core/src/lang/text/include/sourcemeta/core/text.h index 4018d6b05..b66210b6a 100644 --- a/vendor/core/src/lang/text/include/sourcemeta/core/text.h +++ b/vendor/core/src/lang/text/include/sourcemeta/core/text.h @@ -18,7 +18,7 @@ #include // std::ostream #include // std::string #include // std::string_view -#include // std::remove_cv_t +#include // std::is_nothrow_copy_constructible_v, std::is_nothrow_invocable_r_v, std::remove_cv_t #include // std::pair #include // std::vector @@ -314,6 +314,33 @@ constexpr auto is_alphanum(const std::string_view value) noexcept -> bool { return true; } +/// @ingroup text +/// +/// Return whether a character is an ASCII punctuation character, which is any +/// printable ASCII character other than the space, a letter, or a digit. For +/// example: +/// +/// ```cpp +/// #include +/// #include +/// +/// assert(sourcemeta::core::is_punctuation('!')); +/// assert(sourcemeta::core::is_punctuation('~')); +/// assert(!sourcemeta::core::is_punctuation('a')); +/// assert(!sourcemeta::core::is_punctuation(' ')); +/// ``` +template + requires std::same_as || + std::same_as || + std::same_as || + std::same_as +constexpr auto is_punctuation(const Character character) noexcept -> bool { + return (character >= '!' && character <= '/') || + (character >= ':' && character <= '@') || + (character >= '[' && character <= '`') || + (character >= '{' && character <= '~'); +} + /// @ingroup text /// /// Truncate a string in place to at most `maximum_length` bytes, appending @@ -396,6 +423,79 @@ SOURCEMETA_CORE_TEXT_EXPORT auto strip_right(const std::string_view input, const char character) noexcept -> std::string_view; +/// @ingroup text +/// +/// Return `input` with its leading characters that satisfy `predicate` +/// removed. For example: +/// +/// ```cpp +/// #include +/// #include +/// +/// const auto is_zero{[](const char character) { return character == '0'; }}; +/// assert(sourcemeta::core::strip_left("000123", is_zero) == "123"); +/// ``` +template + requires std::predicate +constexpr auto +strip_left(const std::string_view input, Predicate predicate) noexcept( + std::is_nothrow_invocable_r_v && + std::is_nothrow_copy_constructible_v) -> std::string_view { + std::string_view result{input}; + while (!result.empty() && predicate(result.front())) { + result.remove_prefix(1); + } + + return result; +} + +/// @ingroup text +/// +/// Return `input` with its trailing characters that satisfy `predicate` +/// removed. For example: +/// +/// ```cpp +/// #include +/// #include +/// +/// const auto is_zero{[](const char character) { return character == '0'; }}; +/// assert(sourcemeta::core::strip_right("123000", is_zero) == "123"); +/// ``` +template + requires std::predicate +constexpr auto +strip_right(const std::string_view input, Predicate predicate) noexcept( + std::is_nothrow_invocable_r_v && + std::is_nothrow_copy_constructible_v) -> std::string_view { + std::string_view result{input}; + while (!result.empty() && predicate(result.back())) { + result.remove_suffix(1); + } + + return result; +} + +/// @ingroup text +/// +/// Return `input` with its leading and trailing characters that satisfy +/// `predicate` removed, for when the characters to trim are not the ASCII +/// whitespace. For example: +/// +/// ```cpp +/// #include +/// #include +/// +/// const auto is_dash{[](const char character) { return character == '-'; }}; +/// assert(sourcemeta::core::trim("--hello--", is_dash) == "hello"); +/// ``` +template + requires std::predicate +constexpr auto trim(const std::string_view input, Predicate predicate) noexcept( + std::is_nothrow_invocable_r_v && + std::is_nothrow_copy_constructible_v) -> std::string_view { + return strip_right(strip_left(input, predicate), predicate); +} + /// @ingroup text /// /// Return the content of `input` with a single matched pair of surrounding diff --git a/vendor/core/vendor/cmark-gfm/COPYING b/vendor/core/vendor/cmark-gfm/COPYING deleted file mode 100644 index db88a81b3..000000000 --- a/vendor/core/vendor/cmark-gfm/COPYING +++ /dev/null @@ -1,170 +0,0 @@ -Copyright (c) 2014, John MacFarlane - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ------ - -houdini.h, houdini_href_e.c, houdini_html_e.c, houdini_html_u.c - -derive from https://github.com/vmg/houdini (with some modifications) - -Copyright (C) 2012 Vicent Martí - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ------ - -buffer.h, buffer.c, chunk.h - -are derived from code (C) 2012 Github, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ------ - -utf8.c and utf8.c - -are derived from utf8proc -(), -(C) 2009 Public Software Group e. V., Berlin, Germany. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - ------ - -The normalization code in normalize.py was derived from the -markdowntest project, Copyright 2013 Karl Dubost: - -The MIT License (MIT) - -Copyright (c) 2013 Karl Dubost - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------ - -The CommonMark spec (test/spec.txt) is - -Copyright (C) 2014-15 John MacFarlane - -Released under the Creative Commons CC-BY-SA 4.0 license: -. - ------ - -The test software in test/ is - -Copyright (c) 2014, John MacFarlane - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/core/vendor/cmark-gfm/extensions/autolink.c b/vendor/core/vendor/cmark-gfm/extensions/autolink.c deleted file mode 100644 index d898cd2d4..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/autolink.c +++ /dev/null @@ -1,508 +0,0 @@ -#include "autolink.h" -#include -#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) { - size_t i; - size_t closing = 0; - size_t opening = 0; - - for (i = 0; i < link_end; ++i) { - const uint8_t c = data[i]; - if (c == '<') { - link_end = i; - break; - } else if (c == '(') { - opening++; - } else if (c == ')') { - closing++; - } - } - - while (link_end > 0) { - switch (data[link_end - 1]) { - case ')': - /* 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)) - */ - if (closing <= opening) { - return link_end; - } - closing--; - link_end--; - break; - case '?': - case '!': - case '.': - case ',': - case ':': - case '*': - case '_': - case '~': - case '\'': - case '"': - link_end--; - break; - case ';': { - 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--; - break; - } - - default: - return link_end; - } - } - - 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; - - /* The purpose of this code is to reject urls that contain an underscore - * in one of the last two segments. Examples: - * - * www.xxx.yyy.zzz autolinked - * www.xxx.yyy._zzz not autolinked - * www.xxx._yyy.zzz not autolinked - * www._xxx.yyy.zzz autolinked - * - * The reason is that domain names are allowed to include underscores, - * but host names are not. See: https://stackoverflow.com/a/2183140 - */ - for (i = 1; i < size - 1; i++) { - if (data[i] == '\\' && i < size - 2) - 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) { - /* If the url is very long then accept it despite the underscores, - * to avoid quadratic behavior causing a denial of service. See: - * https://github.com/github/cmark-gfm/security/advisories/GHSA-29g3-96g3-jg6c - * Reasonable urls are unlikely to have more than 10 segments, so - * this extra condition shouldn't have any impact on normal usage. - */ - if (np <= 10) { - 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]) && 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]) && 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); - - 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 = max_rewind - rewind; - node->end_column = text->end_column = cmark_inline_parser_get_column(inline_parser) - 1; - - 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 bool validate_protocol(const char protocol[], uint8_t *data, size_t rewind, size_t max_rewind) { - size_t len = strlen(protocol); - - if (len > (max_rewind - rewind)) { - return false; - } - - // Check that the protocol matches - if (memcmp(data - rewind - len, protocol, len) != 0) { - return false; - } - - if (len == (max_rewind - rewind)) { - return true; - } - - char prev_char = data[-((ptrdiff_t)rewind) - len - 1]; - - // Make sure the character before the protocol is non-alphanumeric - return !cmark_isalnum(prev_char); -} - -static void postprocess_text(cmark_parser *parser, cmark_node *text) { - size_t start = 0; - size_t offset = 0; - // `text` is going to be split into a list of nodes containing shorter segments - // of text, so we detach the memory buffer from text and use `cmark_chunk_dup` to - // create references to it. Later, `cmark_chunk_to_cstr` is used to convert - // the references into allocated buffers. The detached buffer is freed before we - // return. - cmark_chunk detached_chunk = text->as.literal; - text->as.literal = cmark_chunk_dup(&detached_chunk, 0, detached_chunk.len); - - uint8_t *data = text->as.literal.data; - size_t remaining = text->as.literal.len; - - while (true) { - size_t link_end; - uint8_t *at; - bool auto_mailto = true; - bool is_xmpp = false; - size_t rewind; - size_t max_rewind; - size_t np = 0; - - if (offset >= remaining) - break; - - at = (uint8_t *)memchr(data + start + offset, '@', remaining - offset); - if (!at) - break; - - max_rewind = at - (data + start + offset); - -found_at: - for (rewind = 0; rewind < max_rewind; ++rewind) { - uint8_t c = data[start + offset + max_rewind - rewind - 1]; - - if (cmark_isalnum(c)) - continue; - - if (strchr(".+-_", c) != NULL) - continue; - - if (strchr(":", c) != NULL) { - if (validate_protocol("mailto:", data + start + offset + max_rewind, rewind, max_rewind)) { - auto_mailto = false; - continue; - } - - if (validate_protocol("xmpp:", data + start + offset + max_rewind, rewind, max_rewind)) { - auto_mailto = false; - is_xmpp = true; - continue; - } - } - - break; - } - - if (rewind == 0) { - offset += max_rewind + 1; - continue; - } - - assert(data[start + offset + max_rewind] == '@'); - for (link_end = 1; link_end < remaining - offset - max_rewind; ++link_end) { - uint8_t c = data[start + offset + max_rewind + link_end]; - - if (cmark_isalnum(c)) - continue; - - if (c == '@') { - // Found another '@', so go back and try again with an updated offset and max_rewind. - offset += max_rewind + 1; - max_rewind = link_end - 1; - goto found_at; - } else if (c == '.' && link_end < remaining - offset - max_rewind - 1 && - cmark_isalnum(data[start + offset + max_rewind + link_end + 1])) - np++; - else if (c == '/' && is_xmpp) - continue; - else if (c != '-' && c != '_') - break; - } - - if (link_end < 2 || np == 0 || - (!cmark_isalpha(data[start + offset + max_rewind + link_end - 1]) && - data[start + offset + max_rewind + link_end - 1] != '.')) { - offset += max_rewind + link_end; - continue; - } - - link_end = autolink_delim(data + start + offset + max_rewind, link_end); - - if (link_end == 0) { - offset += max_rewind + 1; - continue; - } - - cmark_node *link_node = cmark_node_new_with_mem(CMARK_NODE_LINK, parser->mem); - cmark_strbuf buf; - cmark_strbuf_init(parser->mem, &buf, 10); - if (auto_mailto) - cmark_strbuf_puts(&buf, "mailto:"); - cmark_strbuf_put(&buf, data + start + offset + max_rewind - 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( - &detached_chunk, - (bufsize_t)(start + 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(&detached_chunk, - (bufsize_t)(start + offset + max_rewind + link_end), - (bufsize_t)(remaining - offset - max_rewind - link_end)); - - cmark_node_insert_after(link_node, post); - - text->as.literal = cmark_chunk_dup(&detached_chunk, (bufsize_t)start, (bufsize_t)(offset + max_rewind - rewind)); - cmark_chunk_to_cstr(parser->mem, &text->as.literal); - - text = post; - start += offset + max_rewind + link_end; - remaining -= offset + max_rewind + link_end; - offset = 0; - } - - // Convert the reference to allocated memory. - assert(!text->as.literal.alloc); - cmark_chunk_to_cstr(parser->mem, &text->as.literal); - - // Free the detached buffer. - cmark_chunk_free(parser->mem, &detached_chunk); -} - -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); - } - } - - 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/vendor/core/vendor/cmark-gfm/extensions/autolink.h b/vendor/core/vendor/cmark-gfm/extensions/autolink.h deleted file mode 100644 index 4e179379d..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/autolink.h +++ /dev/null @@ -1,8 +0,0 @@ -#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/vendor/core/vendor/cmark-gfm/extensions/cmark-gfm-core-extensions.h b/vendor/core/vendor/cmark-gfm/extensions/cmark-gfm-core-extensions.h deleted file mode 100644 index bc29ffd41..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/cmark-gfm-core-extensions.h +++ /dev/null @@ -1,54 +0,0 @@ -#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_export.h" -#include -#include - -CMARK_GFM_EXPORT -void cmark_gfm_core_extensions_ensure_registered(void); - -CMARK_GFM_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_EXPORT -int cmark_gfm_extensions_set_table_columns(cmark_node *node, uint16_t n_columns); - -CMARK_GFM_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_EXPORT -int cmark_gfm_extensions_set_table_alignments(cmark_node *node, uint16_t ncols, uint8_t *alignments); - -CMARK_GFM_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_EXPORT -int cmark_gfm_extensions_set_table_row_is_header(cmark_node *node, int is_header); - -CMARK_GFM_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_EXPORT -int cmark_gfm_extensions_set_tasklist_item_checked(cmark_node *node, bool is_checked); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/core/vendor/cmark-gfm/extensions/core-extensions.c b/vendor/core/vendor/cmark-gfm/extensions/core-extensions.c deleted file mode 100644 index 846e2bc2b..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/core-extensions.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "cmark-gfm-core-extensions.h" -#include "autolink.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; -} - -void cmark_gfm_core_extensions_ensure_registered(void) { - static int registered = 0; - - if (!registered) { - cmark_register_plugin(core_extensions_registration); - registered = 1; - } -} diff --git a/vendor/core/vendor/cmark-gfm/extensions/ext_scanners.c b/vendor/core/vendor/cmark-gfm/extensions/ext_scanners.c deleted file mode 100644 index 0d3ba2881..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/ext_scanners.c +++ /dev/null @@ -1,879 +0,0 @@ -/* 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/vendor/core/vendor/cmark-gfm/extensions/ext_scanners.h b/vendor/core/vendor/cmark-gfm/extensions/ext_scanners.h deleted file mode 100644 index 6dd4a725d..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/ext_scanners.h +++ /dev/null @@ -1,24 +0,0 @@ -#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/vendor/core/vendor/cmark-gfm/extensions/ext_scanners.re b/vendor/core/vendor/cmark-gfm/extensions/ext_scanners.re deleted file mode 100644 index 9144e5b48..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/ext_scanners.re +++ /dev/null @@ -1,92 +0,0 @@ -/*!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/vendor/core/vendor/cmark-gfm/extensions/strikethrough.c b/vendor/core/vendor/cmark-gfm/extensions/strikethrough.c deleted file mode 100644 index e08842242..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/strikethrough.c +++ /dev/null @@ -1,167 +0,0 @@ -#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); - -done: - 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); - - 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/vendor/core/vendor/cmark-gfm/extensions/strikethrough.h b/vendor/core/vendor/cmark-gfm/extensions/strikethrough.h deleted file mode 100644 index a52a2b4ac..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/strikethrough.h +++ /dev/null @@ -1,9 +0,0 @@ -#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/vendor/core/vendor/cmark-gfm/extensions/table.c b/vendor/core/vendor/cmark-gfm/extensions/table.c deleted file mode 100644 index e8359f259..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/table.c +++ /dev/null @@ -1,917 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "ext_scanners.h" -#include "strikethrough.h" -#include "table.h" -#include "cmark-gfm-core-extensions.h" - -// Limit to prevent a malicious input from causing a denial of service. -#define MAX_AUTOCOMPLETED_CELLS 0x80000 - -// Custom node flag, initialized in `create_table_extension`. -static cmark_node_internal_flags CMARK_NODE__TABLE_VISITED; - -cmark_node_type CMARK_NODE_TABLE, CMARK_NODE_TABLE_ROW, - CMARK_NODE_TABLE_CELL; - -typedef struct { - cmark_strbuf *buf; - int start_offset, end_offset, internal_offset; -} node_cell; - -typedef struct { - uint16_t n_columns; - int paragraph_offset; - node_cell *cells; -} table_row; - -typedef struct { - uint16_t n_columns; - uint8_t *alignments; - int n_rows; - int n_nonempty_cells; -} node_table; - -typedef struct { - bool is_header; -} node_table_row; - -static void free_table_cell(cmark_mem *mem, node_cell *cell) { - cmark_strbuf_free((cmark_strbuf *)cell->buf); - mem->free(cell->buf); -} - -static void free_row_cells(cmark_mem *mem, table_row *row) { - while (row->n_columns > 0) { - free_table_cell(mem, &row->cells[--row->n_columns]); - } - mem->free(row->cells); - row->cells = NULL; -} - -static void free_table_row(cmark_mem *mem, table_row *row) { - if (!row) - return; - - free_row_cells(mem, row); - 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; -} - -// Increment the number of rows in the table. Also update n_nonempty_cells, -// which keeps track of the number of cells which were parsed from the -// input file. (If one of the rows is too short, then the trailing cells -// are autocompleted. Autocompleted cells are not counted in n_nonempty_cells.) -// The purpose of this is to prevent a malicious input from generating a very -// large number of autocompleted cells, which could cause a denial of service -// vulnerability. -static int incr_table_row_count(cmark_node *node, int i) { - if (!node || node->type != CMARK_NODE_TABLE) { - return 0; - } - - ((node_table *)node->as.opaque)->n_rows++; - ((node_table *)node->as.opaque)->n_nonempty_cells += i; - return 1; -} - -// Calculate the number of autocompleted cells. -static int get_n_autocompleted_cells(cmark_node *node) { - if (!node || node->type != CMARK_NODE_TABLE) { - return 0; - } - - const node_table *nt = (node_table *)node->as.opaque; - return (nt->n_columns * nt->n_rows) - nt->n_nonempty_cells; -} - -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 uint8_t get_cell_alignment(cmark_node *node) { - if (!node || node->type != CMARK_NODE_TABLE_CELL) - return 0; - - const uint8_t *alignments = get_table_alignments(node->parent->parent); - int i = node->as.cell_index; - return alignments[i]; -} - -static int set_cell_index(cmark_node *node, int i) { - if (!node || node->type != CMARK_NODE_TABLE_CELL) - return 0; - - node->as.cell_index = i; - 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; -} - -// Adds a new cell to the end of the row. A pointer to the new cell is returned -// for the caller to initialize. -static node_cell* append_row_cell(cmark_mem *mem, table_row *row) { - const uint32_t n_columns = row->n_columns + 1; - // realloc when n_columns is a power of 2 - if ((n_columns & (n_columns-1)) == 0) { - // make sure we never wrap row->n_columns - // offset will != len and our exit will clean up as intended - if (n_columns > UINT16_MAX) { - return NULL; - } - // Use realloc to double the size of the buffer. - row->cells = (node_cell *)mem->realloc(row->cells, (2 * n_columns - 1) * sizeof(node_cell)); - } - row->n_columns = (uint16_t)n_columns; - return &row->cells[n_columns-1]; -} - -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; - int int_overflow_abort = 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 = append_row_cell(parser->mem, row); - if (!cell) { - int_overflow_abort = 1; - cmark_strbuf_free(cell_buf); - parser->mem->free(cell_buf); - break; - } - cell->buf = cell_buf; - cell->start_offset = offset; - cell->end_offset = offset + cell_matched - 1; - cell->internal_offset = 0; - - while (cell->start_offset > row->paragraph_offset && string[cell->start_offset - 1] != '|') { - --cell->start_offset; - ++cell->internal_offset; - } - } - - 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; - - free_row_cells(parser->mem, row); - - // 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 || int_overflow_abort) { - 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 *delimiter_row = NULL; - node_table_row *ntr; - const char *parent_string; - uint16_t i; - - if (parent_container->flags & CMARK_NODE__TABLE_VISITED) { - return parent_container; - } - - 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 delimiter row. - delimiter_row = row_from_string( - self, parser, input + cmark_parser_get_first_nonspace(parser), - len - cmark_parser_get_first_nonspace(parser)); - // assert may be optimized out, don't rely on it for security boundaries - if (!delimiter_row) { - return parent_container; - } - - assert(delimiter_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 != delimiter_row->n_columns) { - free_table_row(parser->mem, delimiter_row); - free_table_row(parser->mem, header_row); - cmark_arena_pop(); - parent_container->flags |= CMARK_NODE__TABLE_VISITED; - return parent_container; - } - - if (cmark_arena_pop()) { - delimiter_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)); - // row_from_string can return NULL, add additional check to ensure n_columns match - if (!delimiter_row || !header_row || header_row->n_columns != delimiter_row->n_columns) { - free_table_row(parser->mem, delimiter_row); - free_table_row(parser->mem, header_row); - return parent_container; - } - } - - if (!cmark_node_set_type(parent_container, CMARK_NODE_TABLE)) { - free_table_row(parser->mem, header_row); - free_table_row(parser->mem, delimiter_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); - - // allocate alignments based on delimiter_row->n_columns - // since we populate the alignments array based on delimiter_row->cells - uint8_t *alignments = - (uint8_t *)parser->mem->calloc(delimiter_row->n_columns, sizeof(uint8_t)); - for (i = 0; i < delimiter_row->n_columns; ++i) { - node_cell *node = &delimiter_row->cells[i]; - 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; - - for (i = 0; i < header_row->n_columns; ++i) { - node_cell *cell = &header_row->cells[i]; - 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); - set_cell_index(header_cell, i); - } - - incr_table_row_count(parent_container, i); - - 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, delimiter_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; - - if (get_n_autocompleted_cells(parent_container) > MAX_AUTOCOMPLETED_CELLS) { - 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)); - - if (!row) { - // clean up the dangling node - cmark_node_free(table_row_block); - return NULL; - } - - { - int i, table_columns = get_n_table_columns(parent_container); - - for (i = 0; i < row->n_columns && i < table_columns; ++i) { - node_cell *cell = &row->cells[i]; - 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); - set_cell_index(node, i); - } - - incr_table_row_count(parent_container, i); - - 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); - set_cell_index(node, i); - } - } - - 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_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)) { - switch (get_cell_alignment(node)) { - 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; - - // 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) { - if (entering) { - cmark_html_render_cr(html); - if (table_state->in_table_header) { - cmark_strbuf_puts(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_register_node_flag(&CMARK_NODE__TABLE_VISITED); - 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/vendor/core/vendor/cmark-gfm/extensions/table.h b/vendor/core/vendor/cmark-gfm/extensions/table.h deleted file mode 100644 index f6a0634f0..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/table.h +++ /dev/null @@ -1,12 +0,0 @@ -#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/vendor/core/vendor/cmark-gfm/extensions/tagfilter.c b/vendor/core/vendor/cmark-gfm/extensions/tagfilter.c deleted file mode 100644 index 262352e0c..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/tagfilter.c +++ /dev/null @@ -1,60 +0,0 @@ -#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/vendor/core/vendor/cmark-gfm/extensions/tagfilter.h b/vendor/core/vendor/cmark-gfm/extensions/tagfilter.h deleted file mode 100644 index 9a5f388d4..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/tagfilter.h +++ /dev/null @@ -1,8 +0,0 @@ -#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/vendor/core/vendor/cmark-gfm/extensions/tasklist.c b/vendor/core/vendor/cmark-gfm/extensions/tasklist.c deleted file mode 100644 index 7bef45499..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/tasklist.c +++ /dev/null @@ -1,156 +0,0 @@ -#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/vendor/core/vendor/cmark-gfm/extensions/tasklist.h b/vendor/core/vendor/cmark-gfm/extensions/tasklist.h deleted file mode 100644 index 26e9d96d2..000000000 --- a/vendor/core/vendor/cmark-gfm/extensions/tasklist.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef TASKLIST_H -#define TASKLIST_H - -#include "cmark-gfm-core-extensions.h" - -cmark_syntax_extension *create_tasklist_extension(void); - -#endif diff --git a/vendor/core/vendor/cmark-gfm/src/arena.c b/vendor/core/vendor/cmark-gfm/src/arena.c deleted file mode 100644 index da1a70e92..000000000 --- a/vendor/core/vendor/cmark-gfm/src/arena.c +++ /dev/null @@ -1,104 +0,0 @@ -#include -#include -#include -#include "cmark-gfm.h" -#include "cmark-gfm-extension_api.h" - -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) { - if (!A) - return; - A->push_point = 1; - A = alloc_arena_chunk(10240, A); -} - -int cmark_arena_pop(void) { - if (!A) - return 0; - while (A && !A->push_point) { - free(A->ptr); - struct arena_chunk *n = A->prev; - free(A); - A = n; - } - if (A) - A->push_point = 0; - return 1; -} - -static void init_arena(void) { - A = alloc_arena_chunk(4 * 1048576, NULL); -} - -void cmark_arena_reset(void) { - while (A) { - free(A->ptr); - struct arena_chunk *n = A->prev; - free(A); - A = n; - } -} - -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; - - struct arena_chunk *chunk; - if (sz > A->sz) { - A->prev = chunk = alloc_arena_chunk(sz, A->prev); - } else if (sz > A->sz - A->used) { - A = chunk = alloc_arena_chunk(A->sz + A->sz / 2, A); - } else { - chunk = A; - } - void *ptr = (uint8_t *) chunk->ptr + chunk->used; - chunk->used += sz; - *((size_t *) ptr) = sz - sizeof(size_t); - 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(void) { - return &CMARK_ARENA_MEM_ALLOCATOR; -} diff --git a/vendor/core/vendor/cmark-gfm/src/blocks.c b/vendor/core/vendor/cmark-gfm/src/blocks.c deleted file mode 100644 index 3b5da56bf..000000000 --- a/vendor/core/vendor/cmark-gfm/src/blocks.c +++ /dev/null @@ -1,1622 +0,0 @@ -/** - * Block parsing implementation. - * - * For a high-level overview of the block parsing process, - * see http://spec.commonmark.org/0.24/#phase-1-block-structure - */ - -#include -#include -#include -#include - -#include "cmark_ctype.h" -#include "syntax_extension.h" -#include "config.h" -#include "parser.h" -#include "cmark-gfm.h" -#include "node.h" -#include "references.h" -#include "utf8.h" -#include "scanners.h" -#include "inlines.h" -#include "houdini.h" -#include "buffer.h" -#include "footnotes.h" - -#define CODE_INDENT 4 -#define TAB_STOP 4 - -/** - * Very deeply nested lists can cause quadratic performance issues. - * This constant is used in open_new_blocks() to limit the nesting - * depth. It is unlikely that a non-contrived markdown document will - * be nested this deeply. - */ -#define MAX_LIST_DEPTH 100 - -#ifndef MIN -#define MIN(x, y) ((x < y) ? x : y) -#endif - -#define peek_at(i, n) (i)->data[n] - -static bool S_last_line_blank(const cmark_node *node) { - return (node->flags & CMARK_NODE__LAST_LINE_BLANK) != 0; -} - -static bool S_last_line_checked(const cmark_node *node) { - return (node->flags & CMARK_NODE__LAST_LINE_CHECKED) != 0; -} - -static CMARK_INLINE cmark_node_type S_type(const cmark_node *node) { - return (cmark_node_type)node->type; -} - -static void S_set_last_line_blank(cmark_node *node, bool is_blank) { - if (is_blank) - node->flags |= CMARK_NODE__LAST_LINE_BLANK; - else - node->flags &= ~CMARK_NODE__LAST_LINE_BLANK; -} - -static void S_set_last_line_checked(cmark_node *node) { - node->flags |= CMARK_NODE__LAST_LINE_CHECKED; -} - -static CMARK_INLINE bool S_is_line_end_char(char c) { - return (c == '\n' || c == '\r'); -} - -static CMARK_INLINE bool S_is_space_or_tab(char c) { - return (c == ' ' || c == '\t'); -} - -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); - -static cmark_node *make_block(cmark_mem *mem, cmark_node_type tag, - int start_line, int start_column) { - cmark_node *e; - - e = (cmark_node *)mem->calloc(1, sizeof(*e)); - cmark_strbuf_init(mem, &e->content, 32); - e->type = (uint16_t)tag; - e->flags = CMARK_NODE__OPEN; - e->start_line = start_line; - e->start_column = start_column; - e->end_line = start_line; - - return e; -} - -// Create a root document node. -static cmark_node *make_document(cmark_mem *mem) { - cmark_node *e = make_block(mem, CMARK_NODE_DOCUMENT, 1, 1); - return e; -} - -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) { - 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; - - cmark_parser_dispose(parser); - - memset(parser, 0, sizeof(cmark_parser)); - parser->mem = saved_mem; - - cmark_strbuf_init(parser->mem, &parser->curline, 256); - cmark_strbuf_init(parser->mem, &parser->linebuf, 0); - - cmark_node *document = make_document(parser->mem); - - parser->refmap = cmark_reference_map_new(parser->mem); - parser->root = document; - parser->current = document; - - parser->syntax_extensions = saved_exts; - parser->inline_syntax_extensions = saved_inline_exts; - parser->options = saved_options; -} - -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_parser_reset(parser); - return parser; -} - -cmark_parser *cmark_parser_new(int options) { - 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; - cmark_parser_dispose(parser); - cmark_strbuf_free(&parser->curline); - cmark_strbuf_free(&parser->linebuf); - cmark_llist_free(parser->mem, parser->syntax_extensions); - cmark_llist_free(parser->mem, parser->inline_syntax_extensions); - mem->free(parser); -} - -static cmark_node *finalize(cmark_parser *parser, cmark_node *b); - -// Returns true if line has only space characters, else false. -static bool is_blank(cmark_strbuf *s, bufsize_t offset) { - while (offset < s->size) { - switch (s->ptr[offset]) { - case '\r': - case '\n': - return true; - case ' ': - offset++; - break; - case '\t': - offset++; - break; - default: - return false; - } - } - - return true; -} - -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 *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) { - int chars_to_tab; - int i; - assert(node->flags & CMARK_NODE__OPEN); - if (parser->partially_consumed_tab) { - parser->offset += 1; // skip over tab - // add space characters: - chars_to_tab = TAB_STOP - (parser->column % TAB_STOP); - for (i = 0; i < chars_to_tab; i++) { - cmark_strbuf_putc(&node->content, ' '); - } - } - cmark_strbuf_put(&node->content, ch->data + parser->offset, - ch->len - parser->offset); -} - -static void remove_trailing_blank_lines(cmark_strbuf *ln) { - bufsize_t i; - unsigned char c; - - for (i = ln->size - 1; i >= 0; --i) { - c = ln->ptr[i]; - - if (c != ' ' && c != '\t' && !S_is_line_end_char(c)) - break; - } - - if (i < 0) { - cmark_strbuf_clear(ln); - return; - } - - for (; i < ln->size; ++i) { - c = ln->ptr[i]; - - if (!S_is_line_end_char(c)) - continue; - - cmark_strbuf_truncate(ln, i); - break; - } -} - -// Check to see if a node ends with a blank line, descending -// if needed into lists and sublists. -static bool S_ends_with_blank_line(cmark_node *node) { - if (S_last_line_checked(node)) { - return(S_last_line_blank(node)); - } else if ((S_type(node) == CMARK_NODE_LIST || - S_type(node) == CMARK_NODE_ITEM) && node->last_child) { - S_set_last_line_checked(node); - return(S_ends_with_blank_line(node->last_child)); - } else { - S_set_last_line_checked(node); - return (S_last_line_blank(node)); - } -} - -// returns true if content remains after link defs are resolved. -static bool resolve_reference_link_definitions( - cmark_parser *parser, - cmark_node *b) { - 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))) { - - chunk.data += pos; - chunk.len -= pos; - } - cmark_strbuf_drop(node_content, (node_content->size - chunk.len)); - return !is_blank(&b->content, 0); -} - -static cmark_node *finalize(cmark_parser *parser, cmark_node *b) { - bufsize_t pos; - cmark_node *item; - cmark_node *subitem; - cmark_node *parent; - bool has_content; - - parent = b->parent; - assert(b->flags & - CMARK_NODE__OPEN); // shouldn't call finalize on closed blocks - b->flags &= ~CMARK_NODE__OPEN; - - if (parser->curline.size == 0) { - // end of input - line number has not been incremented - b->end_line = parser->line_number; - 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)) { - b->end_line = parser->line_number; - b->end_column = parser->curline.size; - if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\n') - b->end_column -= 1; - if (b->end_column && parser->curline.ptr[b->end_column - 1] == '\r') - b->end_column -= 1; - } else { - b->end_line = parser->line_number - 1; - b->end_column = parser->last_line_length; - } - - cmark_strbuf *node_content = &b->content; - - switch (S_type(b)) { - case CMARK_NODE_PARAGRAPH: - { - has_content = resolve_reference_link_definitions(parser, b); - if (!has_content) { - // remove blank node (former reference def) - cmark_node_free(b); - } - break; - } - - case CMARK_NODE_CODE_BLOCK: - if (!b->as.code.fenced) { // indented code - remove_trailing_blank_lines(node_content); - cmark_strbuf_putc(node_content, '\n'); - } else { - // first line of contents becomes info - for (pos = 0; pos < node_content->size; ++pos) { - if (S_is_line_end_char(node_content->ptr[pos])) - break; - } - assert(pos < node_content->size); - - cmark_strbuf tmp = CMARK_BUF_INIT(parser->mem); - houdini_unescape_html_f(&tmp, node_content->ptr, pos); - cmark_strbuf_trim(&tmp); - cmark_strbuf_unescape(&tmp); - b->as.code.info = cmark_chunk_buf_detach(&tmp); - - if (node_content->ptr[pos] == '\r') - pos += 1; - if (node_content->ptr[pos] == '\n') - pos += 1; - cmark_strbuf_drop(node_content, pos); - } - b->as.code.literal = cmark_chunk_buf_detach(node_content); - break; - - case CMARK_NODE_HTML_BLOCK: - b->as.literal = cmark_chunk_buf_detach(node_content); - break; - - case CMARK_NODE_LIST: // determine tight/loose status - b->as.list.tight = true; // tight by default - item = b->first_child; - - while (item) { - // check for non-final non-empty list item ending with blank line: - if (S_last_line_blank(item) && item->next) { - b->as.list.tight = false; - break; - } - // recurse into children of list item, to see if there are - // spaces between them: - subitem = item->first_child; - while (subitem) { - if ((item->next || subitem->next) && - S_ends_with_blank_line(subitem)) { - b->as.list.tight = false; - break; - } - subitem = subitem->next; - } - if (!(b->as.list.tight)) { - break; - } - item = item->next; - } - - break; - - default: - break; - } - - return parent; -} - -// Add a node as child of another. Return pointer to child. -static cmark_node *add_child(cmark_parser *parser, cmark_node *parent, - cmark_node_type block_type, int start_column) { - assert(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 (!cmark_node_can_contain_type(parent, block_type)) { - parent = finalize(parser, parent); - } - - cmark_node *child = - make_block(parser->mem, block_type, parser->line_number, start_column); - child->parent = parent; - - if (parent->last_child) { - parent->last_child->next = child; - child->prev = parent->last_child; - } else { - parent->first_child = child; - child->prev = NULL; - } - parent->last_child = child; - 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(c, ext->emphasis); - else - cmark_inlines_remove_special_character(c, ext->emphasis); - } - } -} - -// Walk through node and all children, recursively, parsing -// string content into inline content where appropriate. -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(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_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; - - // store a reference to this footnote reference's footnote definition - // this is used by renderers when generating label ids - cur->parent_footnote_def = footnote->node; - - // keep track of a) count of how many times this footnote def has been - // referenced, and b) which reference index this footnote ref is at. - // this is used by renderers when generating links and backreferences. - cur->footnote.ref_ix = ++footnote->node->footnote.def_count; - - 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) { - cmark_node_unlink(footnote->node); - continue; - } - cmark_node_append_child(parser->root, footnote->node); - footnote->node = NULL; - } - } - - cmark_unlink_footnotes_map(map); - 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. -static bufsize_t parse_list_marker(cmark_mem *mem, cmark_chunk *input, - bufsize_t pos, bool interrupts_paragraph, - cmark_list **dataptr) { - unsigned char c; - bufsize_t startpos; - cmark_list *data; - bufsize_t i; - - startpos = pos; - c = peek_at(input, pos); - - if (c == '*' || c == '-' || c == '+') { - pos++; - if (!cmark_isspace(peek_at(input, pos))) { - return 0; - } - - if (interrupts_paragraph) { - i = pos; - // require non-blank content after list marker: - while (S_is_space_or_tab(peek_at(input, i))) { - i++; - } - if (peek_at(input, i) == '\n') { - return 0; - } - } - - data = (cmark_list *)mem->calloc(1, sizeof(*data)); - data->marker_offset = 0; // will be adjusted later - data->list_type = CMARK_BULLET_LIST; - data->bullet_char = c; - data->start = 0; - data->delimiter = CMARK_NO_DELIM; - data->tight = false; - } else if (cmark_isdigit(c)) { - int start = 0; - int digits = 0; - - do { - start = (10 * start) + (peek_at(input, pos) - '0'); - pos++; - digits++; - // We limit to 9 digits to avoid overflow, - // assuming max int is 2^31 - 1 - // This also seems to be the limit for 'start' in some browsers. - } while (digits < 9 && cmark_isdigit(peek_at(input, pos))); - - if (interrupts_paragraph && start != 1) { - return 0; - } - c = peek_at(input, pos); - if (c == '.' || c == ')') { - pos++; - if (!cmark_isspace(peek_at(input, pos))) { - return 0; - } - if (interrupts_paragraph) { - // require non-blank content after list marker: - i = pos; - while (S_is_space_or_tab(peek_at(input, i))) { - i++; - } - if (S_is_line_end_char(peek_at(input, i))) { - return 0; - } - } - - data = (cmark_list *)mem->calloc(1, sizeof(*data)); - data->marker_offset = 0; // will be adjusted later - data->list_type = CMARK_ORDERED_LIST; - data->bullet_char = 0; - data->start = start; - data->delimiter = (c == '.' ? CMARK_PERIOD_DELIM : CMARK_PAREN_DELIM); - data->tight = false; - } else { - return 0; - } - } else { - return 0; - } - - *dataptr = data; - return (pos - startpos); -} - -// Return 1 if list item belongs in list, else 0. -static int lists_match(cmark_list *list_data, cmark_list *item_data) { - return (list_data->list_type == item_data->list_type && - list_data->delimiter == item_data->delimiter && - // list_data->marker_offset == item_data.marker_offset && - list_data->bullet_char == item_data->bullet_char); -} - -static cmark_node *finalize_document(cmark_parser *parser) { - while (parser->current != parser->root) { - parser->current = finalize(parser, parser->current); - } - - finalize(parser, parser->root); - - // Limit total size of extra content created from reference links to - // document size to avoid superlinear growth. Always allow 100KB. - if (parser->total_size > 100000) - parser->refmap->max_ref_size = parser->total_size; - else - parser->refmap->max_ref_size = 100000; - - process_inlines(parser, parser->refmap, parser->options); - if (parser->options & CMARK_OPT_FOOTNOTES) - process_footnotes(parser); - - return parser->root; -} - -cmark_node *cmark_parse_file(FILE *f, int options) { - unsigned char buffer[4096]; - cmark_parser *parser = cmark_parser_new(options); - size_t bytes; - cmark_node *document; - - while ((bytes = fread(buffer, 1, sizeof(buffer), f)) > 0) { - bool eof = bytes < sizeof(buffer); - S_parser_feed(parser, buffer, bytes, eof); - if (eof) { - break; - } - } - - document = cmark_parser_finish(parser); - cmark_parser_free(parser); - return document; -} - -cmark_node *cmark_parse_document(const char *buffer, size_t len, int options) { - cmark_parser *parser = cmark_parser_new(options); - cmark_node *document; - - S_parser_feed(parser, (const unsigned char *)buffer, len, true); - - document = cmark_parser_finish(parser); - cmark_parser_free(parser); - return document; -} - -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}; - - if (len > UINT_MAX - parser->total_size) - parser->total_size = UINT_MAX; - else - parser->total_size += len; - - if (parser->last_buffer_ended_with_cr && *buffer == '\n') { - // skip NL if last buffer ended with CR ; see #117 - buffer++; - } - parser->last_buffer_ended_with_cr = false; - while (buffer < end) { - const unsigned char *eol; - bufsize_t chunk_len; - bool process = false; - for (eol = buffer; eol < end; ++eol) { - if (S_is_line_end_char(*eol)) { - process = true; - break; - } - if (*eol == '\0' && eol < end) { - break; - } - } - if (eol >= end && eof) { - process = true; - } - - 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); - cmark_strbuf_clear(&parser->linebuf); - } else { - S_process_line(parser, buffer, chunk_len); - } - } else { - if (eol < end && *eol == '\0') { - // omit NULL byte - cmark_strbuf_put(&parser->linebuf, buffer, chunk_len); - // add replacement character - cmark_strbuf_put(&parser->linebuf, repl, 3); - } else { - cmark_strbuf_put(&parser->linebuf, buffer, chunk_len); - } - } - - buffer += chunk_len; - if (buffer < end) { - if (*buffer == '\0') { - // skip over NULL - buffer++; - } else { - // skip over line ending characters - if (*buffer == '\r') { - buffer++; - if (buffer == end) - parser->last_buffer_ended_with_cr = true; - } - if (buffer < end && *buffer == '\n') - buffer++; - } - } - } -} - -static void chop_trailing_hashtags(cmark_chunk *ch) { - bufsize_t n, orig_n; - - cmark_chunk_rtrim(ch); - orig_n = n = ch->len - 1; - - // if string ends in space followed by #s, remove these: - while (n >= 0 && peek_at(ch, n) == '#') - n--; - - // Check for a space before the final #s: - if (n != orig_n && n >= 0 && S_is_space_or_tab(peek_at(ch, n))) { - ch->len = n; - cmark_chunk_rtrim(ch); - } -} - -// Check for thematic break. On failure, return 0 and update -// thematic_break_kill_pos with the index at which the -// parse fails. On success, return length of match. -// "...three or more hyphens, asterisks, -// or underscores on a line by themselves. If you wish, you may use -// spaces between the hyphens or asterisks." -static int S_scan_thematic_break(cmark_parser *parser, cmark_chunk *input, - bufsize_t offset) { - bufsize_t i; - char c; - char nextc = '\0'; - int count; - i = offset; - c = peek_at(input, i); - if (!(c == '*' || c == '_' || c == '-')) { - parser->thematic_break_kill_pos = i; - return 0; - } - count = 1; - while ((nextc = peek_at(input, ++i))) { - if (nextc == c) { - count++; - } else if (nextc != ' ' && nextc != '\t') { - break; - } - } - if (count >= 3 && (nextc == '\r' || nextc == '\n')) { - return (i - offset) + 1; - } else { - parser->thematic_break_kill_pos = i; - return 0; - } -} - -// Find first nonspace character from current offset, setting -// parser->first_nonspace, parser->first_nonspace_column, -// parser->indent, and parser->blank. Does not advance parser->offset. -static void S_find_first_nonspace(cmark_parser *parser, cmark_chunk *input) { - char c; - int chars_to_tab = TAB_STOP - (parser->column % TAB_STOP); - - if (parser->first_nonspace <= parser->offset) { - parser->first_nonspace = parser->offset; - parser->first_nonspace_column = parser->column; - while ((c = peek_at(input, parser->first_nonspace))) { - if (c == ' ') { - parser->first_nonspace += 1; - parser->first_nonspace_column += 1; - chars_to_tab = chars_to_tab - 1; - if (chars_to_tab == 0) { - chars_to_tab = TAB_STOP; - } - } else if (c == '\t') { - parser->first_nonspace += 1; - parser->first_nonspace_column += chars_to_tab; - chars_to_tab = TAB_STOP; - } else { - break; - } - } - } - - parser->indent = parser->first_nonspace_column - parser->column; - parser->blank = S_is_line_end_char(peek_at(input, parser->first_nonspace)); -} - -// Advance parser->offset and parser->column. parser->offset is the -// byte position in input; parser->column is a virtual column number -// that takes into account tabs. (Multibyte characters are not taken -// into account, because the Markdown line prefixes we are interested in -// analyzing are entirely ASCII.) The count parameter indicates -// how far to advance the offset. If columns is true, then count -// indicates a number of columns; otherwise, a number of bytes. -// If advancing a certain number of columns partially consumes -// a tab character, parser->partially_consumed_tab is set to true. -static void S_advance_offset(cmark_parser *parser, cmark_chunk *input, - bufsize_t count, bool columns) { - char c; - int chars_to_tab; - int chars_to_advance; - while (count > 0 && (c = peek_at(input, parser->offset))) { - if (c == '\t') { - chars_to_tab = TAB_STOP - (parser->column % TAB_STOP); - if (columns) { - parser->partially_consumed_tab = chars_to_tab > count; - chars_to_advance = MIN(count, chars_to_tab); - parser->column += chars_to_advance; - parser->offset += (parser->partially_consumed_tab ? 0 : 1); - count -= chars_to_advance; - } else { - parser->partially_consumed_tab = false; - parser->column += chars_to_tab; - parser->offset += 1; - count -= 1; - } - } else { - parser->partially_consumed_tab = false; - parser->offset += 1; - parser->column += 1; // assume ascii; block starts are ascii - count -= 1; - } - } -} - -static bool S_last_child_is_open(cmark_node *container) { - return container->last_child && - (container->last_child->flags & CMARK_NODE__OPEN); -} - -static bool parse_block_quote_prefix(cmark_parser *parser, cmark_chunk *input) { - bool res = false; - bufsize_t matched = 0; - - matched = - parser->indent <= 3 && peek_at(input, parser->first_nonspace) == '>'; - if (matched) { - - S_advance_offset(parser, input, parser->indent + 1, true); - - if (S_is_space_or_tab(peek_at(input, parser->offset))) { - S_advance_offset(parser, input, 1, true); - } - - res = true; - } - 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; - - if (parser->indent >= - container->as.list.marker_offset + container->as.list.padding) { - S_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. - S_advance_offset(parser, input, parser->first_nonspace - parser->offset, - false); - res = true; - } - return res; -} - -static bool parse_code_block_prefix(cmark_parser *parser, cmark_chunk *input, - cmark_node *container, - bool *should_continue) { - bool res = false; - - if (!container->as.code.fenced) { // indented - if (parser->indent >= CODE_INDENT) { - S_advance_offset(parser, input, CODE_INDENT, true); - res = true; - } else if (parser->blank) { - S_advance_offset(parser, input, parser->first_nonspace - parser->offset, - false); - res = true; - } - } else { // fenced - bufsize_t matched = 0; - - if (parser->indent <= 3 && (peek_at(input, parser->first_nonspace) == - container->as.code.fence_char)) { - matched = scan_close_code_fence(input, parser->first_nonspace); - } - - if (matched >= container->as.code.fence_length) { - // closing fence - and since we're at - // the end of a line, we can stop processing it: - *should_continue = false; - S_advance_offset(parser, input, matched, false); - parser->current = finalize(parser, container); - } else { - // skip opt. spaces of fence parser->offset - int i = container->as.code.fence_offset; - - while (i > 0 && S_is_space_or_tab(peek_at(input, parser->offset))) { - S_advance_offset(parser, input, 1, true); - i--; - } - res = true; - } - } - - return res; -} - -static bool parse_html_block_prefix(cmark_parser *parser, - cmark_node *container) { - bool res = false; - int html_block_type = container->as.html_block_type; - - assert(html_block_type >= 1 && html_block_type <= 7); - switch (html_block_type) { - case 1: - case 2: - case 3: - case 4: - case 5: - // these types of blocks can accept blanks - res = true; - break; - case 6: - case 7: - res = !parser->blank; - break; - } - - 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. - * - * Will not close unmatched blocks, as we may have a lazy continuation - * line -> http://spec.commonmark.org/0.24/#lazy-continuation-line - * - * Returns: The last matching node, or NULL - */ -static cmark_node *check_open_blocks(cmark_parser *parser, cmark_chunk *input, - bool *all_matched) { - bool should_continue = true; - *all_matched = false; - cmark_node *container = parser->root; - cmark_node_type cont_type; - - while (S_last_child_is_open(container)) { - container = container->last_child; - cont_type = S_type(container); - - 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)) - goto done; - break; - case CMARK_NODE_ITEM: - if (!parse_node_item_prefix(parser, input, container)) - goto done; - break; - case CMARK_NODE_CODE_BLOCK: - if (!parse_code_block_prefix(parser, input, container, &should_continue)) - goto done; - break; - case CMARK_NODE_HEADING: - // a heading can never contain more than one line - goto done; - case CMARK_NODE_HTML_BLOCK: - if (!parse_html_block_prefix(parser, container)) - goto done; - break; - case CMARK_NODE_PARAGRAPH: - 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; - } - } - - *all_matched = true; - -done: - if (!*all_matched) { - container = container->parent; // back up to last matching node - } - - if (!should_continue) { - container = NULL; - } - - return container; -} - -static void open_new_blocks(cmark_parser *parser, cmark_node **container, - cmark_chunk *input, bool all_matched) { - bool indented; - cmark_list *data = NULL; - bool maybe_lazy = S_type(parser->current) == CMARK_NODE_PARAGRAPH; - cmark_node_type cont_type = S_type(*container); - bufsize_t matched = 0; - int lev = 0; - bool save_partially_consumed_tab; - bool has_content; - int save_offset; - int save_column; - size_t depth = 0; - - while (cont_type != CMARK_NODE_CODE_BLOCK && - cont_type != CMARK_NODE_HTML_BLOCK) { - depth++; - S_find_first_nonspace(parser, input); - indented = parser->indent >= CODE_INDENT; - - if (!indented && peek_at(input, parser->first_nonspace) == '>') { - - bufsize_t blockquote_startpos = parser->first_nonspace; - - S_advance_offset(parser, input, - parser->first_nonspace + 1 - parser->offset, false); - // optional following character - if (S_is_space_or_tab(peek_at(input, parser->offset))) { - S_advance_offset(parser, input, 1, true); - } - *container = add_child(parser, *container, CMARK_NODE_BLOCK_QUOTE, - blockquote_startpos + 1); - - } else if (!indented && (matched = scan_atx_heading_start( - input, parser->first_nonspace))) { - bufsize_t hashpos; - int level = 0; - bufsize_t heading_startpos = parser->first_nonspace; - - S_advance_offset(parser, input, - parser->first_nonspace + matched - parser->offset, - false); - *container = add_child(parser, *container, CMARK_NODE_HEADING, - heading_startpos + 1); - - hashpos = cmark_chunk_strchr(input, '#', parser->first_nonspace); - - while (peek_at(input, hashpos) == '#') { - level++; - hashpos++; - } - - (*container)->as.heading.level = level; - (*container)->as.heading.setext = false; - (*container)->internal_offset = matched; - - } else if (!indented && (matched = scan_open_code_fence( - input, parser->first_nonspace))) { - *container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK, - 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 : (uint8_t)matched; - (*container)->as.code.fence_offset = - (int8_t)(parser->first_nonspace - parser->offset); - (*container)->as.code.info = cmark_chunk_literal(""); - S_advance_offset(parser, input, - parser->first_nonspace + matched - parser->offset, - false); - - } else if (!indented && ((matched = scan_html_block_start( - input, parser->first_nonspace)) || - (cont_type != CMARK_NODE_PARAGRAPH && - (matched = scan_html_block_start_7( - input, parser->first_nonspace))))) { - *container = add_child(parser, *container, CMARK_NODE_HTML_BLOCK, - parser->first_nonspace + 1); - (*container)->as.html_block_type = matched; - // note, we don't adjust parser->offset because the tag is part of the - // text - } else if (!indented && cont_type == CMARK_NODE_PARAGRAPH && - (lev = - scan_setext_heading_line(input, parser->first_nonspace))) { - // finalize paragraph, resolving reference links - has_content = resolve_reference_link_definitions(parser, *container); - - if (has_content) { - - (*container)->type = (uint16_t)CMARK_NODE_HEADING; - (*container)->as.heading.level = lev; - (*container)->as.heading.setext = true; - S_advance_offset(parser, input, input->len - 1 - parser->offset, false); - } - } else if (!indented && - !(cont_type == CMARK_NODE_PARAGRAPH && !all_matched) && - (parser->thematic_break_kill_pos <= parser->first_nonspace) && - (matched = S_scan_thematic_break(parser, input, parser->first_nonspace))) { - // it's only now that we know the line is not part of a setext heading: - *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) && - depth < MAX_LIST_DEPTH && - (matched = scan_footnote_definition(input, parser->first_nonspace))) { - cmark_chunk c = cmark_chunk_dup(input, parser->first_nonspace + 2, matched - 2); - - while (c.data[c.len - 1] != ']') - --c.len; - --c.len; - - cmark_chunk_to_cstr(parser->mem, &c); - - 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 && - depth < MAX_LIST_DEPTH && - (matched = parse_list_marker( - parser->mem, input, parser->first_nonspace, - (*container)->type == CMARK_NODE_PARAGRAPH, &data))) { - - // Note that we can have new list items starting with >= 4 - // spaces indent, as long as the list container is still open. - int i = 0; - - // compute padding: - S_advance_offset(parser, input, - parser->first_nonspace + matched - parser->offset, - false); - - save_partially_consumed_tab = parser->partially_consumed_tab; - save_offset = parser->offset; - save_column = parser->column; - - while (parser->column - save_column <= 5 && - S_is_space_or_tab(peek_at(input, parser->offset))) { - S_advance_offset(parser, input, 1, true); - } - - i = parser->column - save_column; - if (i >= 5 || i < 1 || - // only spaces after list marker: - S_is_line_end_char(peek_at(input, parser->offset))) { - data->padding = matched + 1; - parser->offset = save_offset; - parser->column = save_column; - parser->partially_consumed_tab = save_partially_consumed_tab; - if (i > 0) { - S_advance_offset(parser, input, 1, true); - } - } else { - data->padding = matched + i; - } - - // check container; if it's a list, see if this list item - // can continue the list; otherwise, create a list container. - - data->marker_offset = parser->indent; - - if (cont_type != CMARK_NODE_LIST || - !lists_match(&((*container)->as.list), data)) { - *container = add_child(parser, *container, CMARK_NODE_LIST, - parser->first_nonspace + 1); - - memcpy(&((*container)->as.list), data, sizeof(*data)); - } - - // add the list item - *container = add_child(parser, *container, CMARK_NODE_ITEM, - parser->first_nonspace + 1); - /* TODO: static */ - memcpy(&((*container)->as.list), data, sizeof(*data)); - parser->mem->free(data); - } else if (indented && !maybe_lazy && !parser->blank) { - S_advance_offset(parser, input, CODE_INDENT, true); - *container = add_child(parser, *container, CMARK_NODE_CODE_BLOCK, - parser->offset + 1); - (*container)->as.code.fenced = false; - (*container)->as.code.fence_char = 0; - (*container)->as.code.fence_length = 0; - (*container)->as.code.fence_offset = 0; - (*container)->as.code.info = cmark_chunk_literal(""); - } else { - 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))) { - // if it's a line container, it can't contain other containers - break; - } - - cont_type = S_type(*container); - maybe_lazy = false; - } -} - -static void add_text_to_container(cmark_parser *parser, cmark_node *container, - cmark_node *last_matched_container, - cmark_chunk *input) { - cmark_node *tmp; - // what remains at parser->offset is a text line. add the text to the - // appropriate container. - - S_find_first_nonspace(parser, input); - - if (parser->blank && container->last_child) - S_set_last_line_blank(container->last_child, true); - - // block quote lines are never blank as they start with > - // and we don't count blanks in fenced code for purposes of tight/loose - // lists or breaking out of lists. we also don't set last_line_blank - // on an empty list item. - const cmark_node_type ctype = S_type(container); - const bool last_line_blank = - (parser->blank && ctype != CMARK_NODE_BLOCK_QUOTE && - ctype != CMARK_NODE_HEADING && ctype != CMARK_NODE_THEMATIC_BREAK && - !(ctype == CMARK_NODE_CODE_BLOCK && container->as.code.fenced) && - !(ctype == CMARK_NODE_ITEM && container->first_child == NULL && - container->start_line == parser->line_number)); - - S_set_last_line_blank(container, last_line_blank); - - tmp = container; - while (tmp->parent) { - S_set_last_line_blank(tmp->parent, false); - tmp = tmp->parent; - } - - // If the last line processed belonged to a paragraph node, - // and we didn't match all of the line prefixes for the open containers, - // and we didn't start any new containers, - // and the line isn't blank, - // 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 && - S_type(parser->current) == CMARK_NODE_PARAGRAPH) { - add_line(parser->current, input, parser); - } else { // not a lazy continuation - // Finalize any blocks that were not matched and set cur to container: - while (parser->current != last_matched_container) { - parser->current = finalize(parser, parser->current); - assert(parser->current != NULL); - } - - if (S_type(container) == CMARK_NODE_CODE_BLOCK) { - add_line(container, input, parser); - } else if (S_type(container) == CMARK_NODE_HTML_BLOCK) { - add_line(container, input, parser); - - int matches_end_condition; - switch (container->as.html_block_type) { - case 1: - // , , - matches_end_condition = - scan_html_block_end_1(input, parser->first_nonspace); - break; - case 2: - // --> - matches_end_condition = - scan_html_block_end_2(input, parser->first_nonspace); - break; - case 3: - // ?> - matches_end_condition = - scan_html_block_end_3(input, parser->first_nonspace); - break; - case 4: - // > - matches_end_condition = - scan_html_block_end_4(input, parser->first_nonspace); - break; - case 5: - // ]]> - matches_end_condition = - scan_html_block_end_5(input, parser->first_nonspace); - break; - default: - matches_end_condition = 0; - break; - } - - if (matches_end_condition) { - container = finalize(parser, container); - assert(parser->current != NULL); - } - } else if (parser->blank) { - // ??? 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, - 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); - add_line(container, input, parser); - } - - parser->current = 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) { - 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); - else - cmark_strbuf_put(&parser->curline, buffer, bytes); - - bytes = parser->curline.size; - - // ensure line ends with a newline: - if (bytes == 0 || !S_is_line_end_char(parser->curline.ptr[bytes - 1])) - cmark_strbuf_putc(&parser->curline, '\n'); - - 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; - - input.data = parser->curline.ptr; - 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); - - if (!last_matched_container) - goto finished; - - container = last_matched_container; - - current = parser->current; - - 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: - parser->last_line_length = input.len; - if (parser->last_line_length && - input.data[parser->last_line_length - 1] == '\n') - parser->last_line_length -= 1; - if (parser->last_line_length && - input.data[parser->last_line_length - 1] == '\r') - parser->last_line_length -= 1; - - cmark_strbuf_clear(&parser->curline); -} - -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); - cmark_strbuf_clear(&parser->linebuf); - } - - finalize_document(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 - - 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/vendor/core/vendor/cmark-gfm/src/buffer.c b/vendor/core/vendor/cmark-gfm/src/buffer.c deleted file mode 100644 index c7934e57d..000000000 --- a/vendor/core/vendor/cmark-gfm/src/buffer.c +++ /dev/null @@ -1,278 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "cmark_ctype.h" -#include "buffer.h" - -/* Used as default value for cmark_strbuf->ptr so that people can always - * assume ptr is non-NULL and zero terminated even for new cmark_strbufs. - */ -unsigned char cmark_strbuf__initbuf[1]; - -#ifndef MIN -#define MIN(x, y) ((x < y) ? x : y) -#endif - -void cmark_strbuf_init(cmark_mem *mem, cmark_strbuf *buf, - bufsize_t initial_size) { - buf->mem = mem; - buf->asize = 0; - buf->size = 0; - buf->ptr = cmark_strbuf__initbuf; - - if (initial_size > 0) - cmark_strbuf_grow(buf, initial_size); -} - -static CMARK_INLINE void S_strbuf_grow_by(cmark_strbuf *buf, bufsize_t add) { - cmark_strbuf_grow(buf, buf->size + add); -} - -void cmark_strbuf_grow(cmark_strbuf *buf, bufsize_t target_size) { - assert(target_size > 0); - - if (target_size < buf->asize) - return; - - if (target_size > (bufsize_t)(INT32_MAX / 2)) { - fprintf(stderr, - "[cmark] cmark_strbuf_grow requests buffer with size > %d, aborting\n", - (INT32_MAX / 2)); - abort(); - } - - /* Oversize the buffer by 50% to guarantee amortized linear time - * complexity on append operations. */ - bufsize_t new_size = target_size + target_size / 2; - new_size += 1; - new_size = (new_size + 7) & ~7; - - buf->ptr = (unsigned char *)buf->mem->realloc(buf->asize ? buf->ptr : NULL, - new_size); - buf->asize = new_size; -} - -bufsize_t cmark_strbuf_len(const cmark_strbuf *buf) { return buf->size; } - -void cmark_strbuf_free(cmark_strbuf *buf) { - if (!buf) - return; - - if (buf->ptr != cmark_strbuf__initbuf) - buf->mem->free(buf->ptr); - - cmark_strbuf_init(buf->mem, buf, 0); -} - -void cmark_strbuf_clear(cmark_strbuf *buf) { - buf->size = 0; - - if (buf->asize > 0) - buf->ptr[0] = '\0'; -} - -void cmark_strbuf_set(cmark_strbuf *buf, const unsigned char *data, - bufsize_t len) { - if (len <= 0 || data == NULL) { - cmark_strbuf_clear(buf); - } else { - if (data != buf->ptr) { - if (len >= buf->asize) - cmark_strbuf_grow(buf, len); - memmove(buf->ptr, data, len); - } - buf->size = len; - buf->ptr[buf->size] = '\0'; - } -} - -void cmark_strbuf_sets(cmark_strbuf *buf, const char *string) { - cmark_strbuf_set(buf, (const unsigned char *)string, - string ? (bufsize_t)strlen(string) : 0); -} - -void cmark_strbuf_putc(cmark_strbuf *buf, int c) { - S_strbuf_grow_by(buf, 1); - buf->ptr[buf->size++] = (unsigned char)(c & 0xFF); - buf->ptr[buf->size] = '\0'; -} - -void cmark_strbuf_put(cmark_strbuf *buf, const unsigned char *data, - bufsize_t len) { - if (len <= 0) - return; - - S_strbuf_grow_by(buf, len); - memmove(buf->ptr + buf->size, data, len); - buf->size += len; - buf->ptr[buf->size] = '\0'; -} - -void cmark_strbuf_puts(cmark_strbuf *buf, const char *string) { - cmark_strbuf_put(buf, (const unsigned char *)string, (bufsize_t)strlen(string)); -} - -void cmark_strbuf_copy_cstr(char *data, bufsize_t datasize, - const cmark_strbuf *buf) { - bufsize_t copylen; - - assert(buf); - if (!data || datasize <= 0) - return; - - data[0] = '\0'; - - if (buf->size == 0 || buf->asize <= 0) - return; - - copylen = buf->size; - if (copylen > datasize - 1) - copylen = datasize - 1; - memmove(data, buf->ptr, copylen); - data[copylen] = '\0'; -} - -void cmark_strbuf_swap(cmark_strbuf *buf_a, cmark_strbuf *buf_b) { - cmark_strbuf t = *buf_a; - *buf_a = *buf_b; - *buf_b = t; -} - -unsigned char *cmark_strbuf_detach(cmark_strbuf *buf) { - unsigned char *data = buf->ptr; - - if (buf->asize == 0) { - /* return an empty string */ - return (unsigned char *)buf->mem->calloc(1, 1); - } - - cmark_strbuf_init(buf->mem, buf, 0); - return data; -} - -int cmark_strbuf_cmp(const cmark_strbuf *a, const cmark_strbuf *b) { - int result = memcmp(a->ptr, b->ptr, MIN(a->size, b->size)); - return (result != 0) ? result - : (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0; -} - -bufsize_t cmark_strbuf_strchr(const cmark_strbuf *buf, int c, bufsize_t pos) { - if (pos >= buf->size) - return -1; - if (pos < 0) - pos = 0; - - const unsigned char *p = - (unsigned char *)memchr(buf->ptr + pos, c, buf->size - pos); - if (!p) - return -1; - - return (bufsize_t)(p - (const unsigned char *)buf->ptr); -} - -bufsize_t cmark_strbuf_strrchr(const cmark_strbuf *buf, int c, bufsize_t pos) { - if (pos < 0 || buf->size == 0) - return -1; - if (pos >= buf->size) - pos = buf->size - 1; - - bufsize_t i; - for (i = pos; i >= 0; i--) { - if (buf->ptr[i] == (unsigned char)c) - return i; - } - - return -1; -} - -void cmark_strbuf_truncate(cmark_strbuf *buf, bufsize_t len) { - if (len < 0) - len = 0; - - if (len < buf->size) { - buf->size = len; - buf->ptr[buf->size] = '\0'; - } -} - -void cmark_strbuf_drop(cmark_strbuf *buf, bufsize_t n) { - if (n > 0) { - if (n > buf->size) - n = buf->size; - buf->size = buf->size - n; - if (buf->size) - memmove(buf->ptr, buf->ptr + n, buf->size); - - buf->ptr[buf->size] = '\0'; - } -} - -void cmark_strbuf_rtrim(cmark_strbuf *buf) { - if (!buf->size) - return; - - while (buf->size > 0) { - if (!cmark_isspace(buf->ptr[buf->size - 1])) - break; - - buf->size--; - } - - buf->ptr[buf->size] = '\0'; -} - -void cmark_strbuf_trim(cmark_strbuf *buf) { - bufsize_t i = 0; - - if (!buf->size) - return; - - while (i < buf->size && cmark_isspace(buf->ptr[i])) - i++; - - cmark_strbuf_drop(buf, i); - - cmark_strbuf_rtrim(buf); -} - -// Destructively modify string, collapsing consecutive -// space and newline characters into a single space. -void cmark_strbuf_normalize_whitespace(cmark_strbuf *s) { - bool last_char_was_space = false; - bufsize_t r, w; - - for (r = 0, w = 0; r < s->size; ++r) { - if (cmark_isspace(s->ptr[r])) { - if (!last_char_was_space) { - s->ptr[w++] = ' '; - last_char_was_space = true; - } - } else { - s->ptr[w++] = s->ptr[r]; - last_char_was_space = false; - } - } - - cmark_strbuf_truncate(s, w); -} - -// Destructively unescape a string: remove backslashes before punctuation chars. -extern void cmark_strbuf_unescape(cmark_strbuf *buf) { - bufsize_t r, w; - - for (r = 0, w = 0; r < buf->size; ++r) { - if (buf->ptr[r] == '\\' && cmark_ispunct(buf->ptr[r + 1])) - r++; - - buf->ptr[w++] = buf->ptr[r]; - } - - cmark_strbuf_truncate(buf, w); -} diff --git a/vendor/core/vendor/cmark-gfm/src/buffer.h b/vendor/core/vendor/cmark-gfm/src/buffer.h deleted file mode 100644 index b85bb4406..000000000 --- a/vendor/core/vendor/cmark-gfm/src/buffer.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef CMARK_BUFFER_H -#define CMARK_BUFFER_H - -#include -#include -#include -#include -#include -#include "config.h" -#include "cmark-gfm.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - cmark_mem *mem; - unsigned char *ptr; - bufsize_t asize, size; -} cmark_strbuf; - -extern unsigned char cmark_strbuf__initbuf[]; - -#define CMARK_BUF_INIT(mem) \ - { mem, cmark_strbuf__initbuf, 0, 0 } - -/** - * Initialize a cmark_strbuf structure. - * - * 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); - -static CMARK_INLINE const char *cmark_strbuf_cstr(const cmark_strbuf *buf) { - return (char *)buf->ptr; -} - -#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 -} -#endif - -#endif diff --git a/vendor/core/vendor/cmark-gfm/src/case_fold_switch.inc b/vendor/core/vendor/cmark-gfm/src/case_fold_switch.inc deleted file mode 100644 index 28e223e14..000000000 --- a/vendor/core/vendor/cmark-gfm/src/case_fold_switch.inc +++ /dev/null @@ -1,4327 +0,0 @@ - switch (c) { - case 0x0041: - bufpush(0x0061); - break; - case 0x0042: - bufpush(0x0062); - break; - case 0x0043: - bufpush(0x0063); - break; - case 0x0044: - bufpush(0x0064); - break; - case 0x0045: - bufpush(0x0065); - break; - case 0x0046: - bufpush(0x0066); - break; - case 0x0047: - bufpush(0x0067); - break; - case 0x0048: - bufpush(0x0068); - break; - case 0x0049: - bufpush(0x0069); - break; - case 0x004A: - bufpush(0x006A); - break; - case 0x004B: - bufpush(0x006B); - break; - case 0x004C: - bufpush(0x006C); - break; - case 0x004D: - bufpush(0x006D); - break; - case 0x004E: - bufpush(0x006E); - break; - case 0x004F: - bufpush(0x006F); - break; - case 0x0050: - bufpush(0x0070); - break; - case 0x0051: - bufpush(0x0071); - break; - case 0x0052: - bufpush(0x0072); - break; - case 0x0053: - bufpush(0x0073); - break; - case 0x0054: - bufpush(0x0074); - break; - case 0x0055: - bufpush(0x0075); - break; - case 0x0056: - bufpush(0x0076); - break; - case 0x0057: - bufpush(0x0077); - break; - case 0x0058: - bufpush(0x0078); - break; - case 0x0059: - bufpush(0x0079); - break; - case 0x005A: - bufpush(0x007A); - break; - case 0x00B5: - bufpush(0x03BC); - break; - case 0x00C0: - bufpush(0x00E0); - break; - case 0x00C1: - bufpush(0x00E1); - break; - case 0x00C2: - bufpush(0x00E2); - break; - case 0x00C3: - bufpush(0x00E3); - break; - case 0x00C4: - bufpush(0x00E4); - break; - case 0x00C5: - bufpush(0x00E5); - break; - case 0x00C6: - bufpush(0x00E6); - break; - case 0x00C7: - bufpush(0x00E7); - break; - case 0x00C8: - bufpush(0x00E8); - break; - case 0x00C9: - bufpush(0x00E9); - break; - case 0x00CA: - bufpush(0x00EA); - break; - case 0x00CB: - bufpush(0x00EB); - break; - case 0x00CC: - bufpush(0x00EC); - break; - case 0x00CD: - bufpush(0x00ED); - break; - case 0x00CE: - bufpush(0x00EE); - break; - case 0x00CF: - bufpush(0x00EF); - break; - case 0x00D0: - bufpush(0x00F0); - break; - case 0x00D1: - bufpush(0x00F1); - break; - case 0x00D2: - bufpush(0x00F2); - break; - case 0x00D3: - bufpush(0x00F3); - break; - case 0x00D4: - bufpush(0x00F4); - break; - case 0x00D5: - bufpush(0x00F5); - break; - case 0x00D6: - bufpush(0x00F6); - break; - case 0x00D8: - bufpush(0x00F8); - break; - case 0x00D9: - bufpush(0x00F9); - break; - case 0x00DA: - bufpush(0x00FA); - break; - case 0x00DB: - bufpush(0x00FB); - break; - case 0x00DC: - bufpush(0x00FC); - break; - case 0x00DD: - bufpush(0x00FD); - break; - case 0x00DE: - bufpush(0x00FE); - break; - case 0x00DF: - bufpush(0x0073); - bufpush(0x0073); - break; - case 0x0100: - bufpush(0x0101); - break; - case 0x0102: - bufpush(0x0103); - break; - case 0x0104: - bufpush(0x0105); - break; - case 0x0106: - bufpush(0x0107); - break; - case 0x0108: - bufpush(0x0109); - break; - case 0x010A: - bufpush(0x010B); - break; - case 0x010C: - bufpush(0x010D); - break; - case 0x010E: - bufpush(0x010F); - break; - case 0x0110: - bufpush(0x0111); - break; - case 0x0112: - bufpush(0x0113); - break; - case 0x0114: - bufpush(0x0115); - break; - case 0x0116: - bufpush(0x0117); - break; - case 0x0118: - bufpush(0x0119); - break; - case 0x011A: - bufpush(0x011B); - break; - case 0x011C: - bufpush(0x011D); - break; - case 0x011E: - bufpush(0x011F); - break; - case 0x0120: - bufpush(0x0121); - break; - case 0x0122: - bufpush(0x0123); - break; - case 0x0124: - bufpush(0x0125); - break; - case 0x0126: - bufpush(0x0127); - break; - case 0x0128: - bufpush(0x0129); - break; - case 0x012A: - bufpush(0x012B); - break; - case 0x012C: - bufpush(0x012D); - break; - case 0x012E: - bufpush(0x012F); - break; - case 0x0130: - bufpush(0x0069); - bufpush(0x0307); - break; - case 0x0132: - bufpush(0x0133); - break; - case 0x0134: - bufpush(0x0135); - break; - case 0x0136: - bufpush(0x0137); - break; - case 0x0139: - bufpush(0x013A); - break; - case 0x013B: - bufpush(0x013C); - break; - case 0x013D: - bufpush(0x013E); - break; - case 0x013F: - bufpush(0x0140); - break; - case 0x0141: - bufpush(0x0142); - break; - case 0x0143: - bufpush(0x0144); - break; - case 0x0145: - bufpush(0x0146); - break; - case 0x0147: - bufpush(0x0148); - break; - case 0x0149: - bufpush(0x02BC); - bufpush(0x006E); - break; - case 0x014A: - bufpush(0x014B); - break; - case 0x014C: - bufpush(0x014D); - break; - case 0x014E: - bufpush(0x014F); - break; - case 0x0150: - bufpush(0x0151); - break; - case 0x0152: - bufpush(0x0153); - break; - case 0x0154: - bufpush(0x0155); - break; - case 0x0156: - bufpush(0x0157); - break; - case 0x0158: - bufpush(0x0159); - break; - case 0x015A: - bufpush(0x015B); - break; - case 0x015C: - bufpush(0x015D); - break; - case 0x015E: - bufpush(0x015F); - break; - case 0x0160: - bufpush(0x0161); - break; - case 0x0162: - bufpush(0x0163); - break; - case 0x0164: - bufpush(0x0165); - break; - case 0x0166: - bufpush(0x0167); - break; - case 0x0168: - bufpush(0x0169); - break; - case 0x016A: - bufpush(0x016B); - break; - case 0x016C: - bufpush(0x016D); - break; - case 0x016E: - bufpush(0x016F); - break; - case 0x0170: - bufpush(0x0171); - break; - case 0x0172: - bufpush(0x0173); - break; - case 0x0174: - bufpush(0x0175); - break; - case 0x0176: - bufpush(0x0177); - break; - case 0x0178: - bufpush(0x00FF); - break; - case 0x0179: - bufpush(0x017A); - break; - case 0x017B: - bufpush(0x017C); - break; - case 0x017D: - bufpush(0x017E); - break; - case 0x017F: - bufpush(0x0073); - break; - case 0x0181: - bufpush(0x0253); - break; - case 0x0182: - bufpush(0x0183); - break; - case 0x0184: - bufpush(0x0185); - break; - case 0x0186: - bufpush(0x0254); - break; - case 0x0187: - bufpush(0x0188); - break; - case 0x0189: - bufpush(0x0256); - break; - case 0x018A: - bufpush(0x0257); - break; - case 0x018B: - bufpush(0x018C); - break; - case 0x018E: - bufpush(0x01DD); - break; - case 0x018F: - bufpush(0x0259); - break; - case 0x0190: - bufpush(0x025B); - break; - case 0x0191: - bufpush(0x0192); - break; - case 0x0193: - bufpush(0x0260); - break; - case 0x0194: - bufpush(0x0263); - break; - case 0x0196: - bufpush(0x0269); - break; - case 0x0197: - bufpush(0x0268); - break; - case 0x0198: - bufpush(0x0199); - break; - case 0x019C: - bufpush(0x026F); - break; - case 0x019D: - bufpush(0x0272); - break; - case 0x019F: - bufpush(0x0275); - break; - case 0x01A0: - bufpush(0x01A1); - break; - case 0x01A2: - bufpush(0x01A3); - break; - case 0x01A4: - bufpush(0x01A5); - break; - case 0x01A6: - bufpush(0x0280); - break; - case 0x01A7: - bufpush(0x01A8); - break; - case 0x01A9: - bufpush(0x0283); - break; - case 0x01AC: - bufpush(0x01AD); - break; - case 0x01AE: - bufpush(0x0288); - break; - case 0x01AF: - bufpush(0x01B0); - break; - case 0x01B1: - bufpush(0x028A); - break; - case 0x01B2: - bufpush(0x028B); - break; - case 0x01B3: - bufpush(0x01B4); - break; - case 0x01B5: - bufpush(0x01B6); - break; - case 0x01B7: - bufpush(0x0292); - break; - case 0x01B8: - bufpush(0x01B9); - break; - case 0x01BC: - bufpush(0x01BD); - break; - case 0x01C4: - bufpush(0x01C6); - break; - case 0x01C5: - bufpush(0x01C6); - break; - case 0x01C7: - bufpush(0x01C9); - break; - case 0x01C8: - bufpush(0x01C9); - break; - case 0x01CA: - bufpush(0x01CC); - break; - case 0x01CB: - bufpush(0x01CC); - break; - case 0x01CD: - bufpush(0x01CE); - break; - case 0x01CF: - bufpush(0x01D0); - break; - case 0x01D1: - bufpush(0x01D2); - break; - case 0x01D3: - bufpush(0x01D4); - break; - case 0x01D5: - bufpush(0x01D6); - break; - case 0x01D7: - bufpush(0x01D8); - break; - case 0x01D9: - bufpush(0x01DA); - break; - case 0x01DB: - bufpush(0x01DC); - break; - case 0x01DE: - bufpush(0x01DF); - break; - case 0x01E0: - bufpush(0x01E1); - break; - case 0x01E2: - bufpush(0x01E3); - break; - case 0x01E4: - bufpush(0x01E5); - break; - case 0x01E6: - bufpush(0x01E7); - break; - case 0x01E8: - bufpush(0x01E9); - break; - case 0x01EA: - bufpush(0x01EB); - break; - case 0x01EC: - bufpush(0x01ED); - break; - case 0x01EE: - bufpush(0x01EF); - break; - case 0x01F0: - bufpush(0x006A); - bufpush(0x030C); - break; - case 0x01F1: - bufpush(0x01F3); - break; - case 0x01F2: - bufpush(0x01F3); - break; - case 0x01F4: - bufpush(0x01F5); - break; - case 0x01F6: - bufpush(0x0195); - break; - case 0x01F7: - bufpush(0x01BF); - break; - case 0x01F8: - bufpush(0x01F9); - break; - case 0x01FA: - bufpush(0x01FB); - break; - case 0x01FC: - bufpush(0x01FD); - break; - case 0x01FE: - bufpush(0x01FF); - break; - case 0x0200: - bufpush(0x0201); - break; - case 0x0202: - bufpush(0x0203); - break; - case 0x0204: - bufpush(0x0205); - break; - case 0x0206: - bufpush(0x0207); - break; - case 0x0208: - bufpush(0x0209); - break; - case 0x020A: - bufpush(0x020B); - break; - case 0x020C: - bufpush(0x020D); - break; - case 0x020E: - bufpush(0x020F); - break; - case 0x0210: - bufpush(0x0211); - break; - case 0x0212: - bufpush(0x0213); - break; - case 0x0214: - bufpush(0x0215); - break; - case 0x0216: - bufpush(0x0217); - break; - case 0x0218: - bufpush(0x0219); - break; - case 0x021A: - bufpush(0x021B); - break; - case 0x021C: - bufpush(0x021D); - break; - case 0x021E: - bufpush(0x021F); - break; - case 0x0220: - bufpush(0x019E); - break; - case 0x0222: - bufpush(0x0223); - break; - case 0x0224: - bufpush(0x0225); - break; - case 0x0226: - bufpush(0x0227); - break; - case 0x0228: - bufpush(0x0229); - break; - case 0x022A: - bufpush(0x022B); - break; - case 0x022C: - bufpush(0x022D); - break; - case 0x022E: - bufpush(0x022F); - break; - case 0x0230: - bufpush(0x0231); - break; - case 0x0232: - bufpush(0x0233); - break; - case 0x023A: - bufpush(0x2C65); - break; - case 0x023B: - bufpush(0x023C); - break; - case 0x023D: - bufpush(0x019A); - break; - case 0x023E: - bufpush(0x2C66); - break; - case 0x0241: - bufpush(0x0242); - break; - case 0x0243: - bufpush(0x0180); - break; - case 0x0244: - bufpush(0x0289); - break; - case 0x0245: - bufpush(0x028C); - break; - case 0x0246: - bufpush(0x0247); - break; - case 0x0248: - bufpush(0x0249); - break; - case 0x024A: - bufpush(0x024B); - break; - case 0x024C: - bufpush(0x024D); - break; - case 0x024E: - bufpush(0x024F); - break; - case 0x0345: - bufpush(0x03B9); - break; - case 0x0370: - bufpush(0x0371); - break; - case 0x0372: - bufpush(0x0373); - break; - case 0x0376: - bufpush(0x0377); - break; - case 0x037F: - bufpush(0x03F3); - break; - case 0x0386: - bufpush(0x03AC); - break; - case 0x0388: - bufpush(0x03AD); - break; - case 0x0389: - bufpush(0x03AE); - break; - case 0x038A: - bufpush(0x03AF); - break; - case 0x038C: - bufpush(0x03CC); - break; - case 0x038E: - bufpush(0x03CD); - break; - case 0x038F: - bufpush(0x03CE); - break; - case 0x0390: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x0391: - bufpush(0x03B1); - break; - case 0x0392: - bufpush(0x03B2); - break; - case 0x0393: - bufpush(0x03B3); - break; - case 0x0394: - bufpush(0x03B4); - break; - case 0x0395: - bufpush(0x03B5); - break; - case 0x0396: - bufpush(0x03B6); - break; - case 0x0397: - bufpush(0x03B7); - break; - case 0x0398: - bufpush(0x03B8); - break; - case 0x0399: - bufpush(0x03B9); - break; - case 0x039A: - bufpush(0x03BA); - break; - case 0x039B: - bufpush(0x03BB); - break; - case 0x039C: - bufpush(0x03BC); - break; - case 0x039D: - bufpush(0x03BD); - break; - case 0x039E: - bufpush(0x03BE); - break; - case 0x039F: - bufpush(0x03BF); - break; - case 0x03A0: - bufpush(0x03C0); - break; - case 0x03A1: - bufpush(0x03C1); - break; - case 0x03A3: - bufpush(0x03C3); - break; - case 0x03A4: - bufpush(0x03C4); - break; - case 0x03A5: - bufpush(0x03C5); - break; - case 0x03A6: - bufpush(0x03C6); - break; - case 0x03A7: - bufpush(0x03C7); - break; - case 0x03A8: - bufpush(0x03C8); - break; - case 0x03A9: - bufpush(0x03C9); - break; - case 0x03AA: - bufpush(0x03CA); - break; - case 0x03AB: - bufpush(0x03CB); - break; - case 0x03B0: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x03C2: - bufpush(0x03C3); - break; - case 0x03CF: - bufpush(0x03D7); - break; - case 0x03D0: - bufpush(0x03B2); - break; - case 0x03D1: - bufpush(0x03B8); - break; - case 0x03D5: - bufpush(0x03C6); - break; - case 0x03D6: - bufpush(0x03C0); - break; - case 0x03D8: - bufpush(0x03D9); - break; - case 0x03DA: - bufpush(0x03DB); - break; - case 0x03DC: - bufpush(0x03DD); - break; - case 0x03DE: - bufpush(0x03DF); - break; - case 0x03E0: - bufpush(0x03E1); - break; - case 0x03E2: - bufpush(0x03E3); - break; - case 0x03E4: - bufpush(0x03E5); - break; - case 0x03E6: - bufpush(0x03E7); - break; - case 0x03E8: - bufpush(0x03E9); - break; - case 0x03EA: - bufpush(0x03EB); - break; - case 0x03EC: - bufpush(0x03ED); - break; - case 0x03EE: - bufpush(0x03EF); - break; - case 0x03F0: - bufpush(0x03BA); - break; - case 0x03F1: - bufpush(0x03C1); - break; - case 0x03F4: - bufpush(0x03B8); - break; - case 0x03F5: - bufpush(0x03B5); - break; - case 0x03F7: - bufpush(0x03F8); - break; - case 0x03F9: - bufpush(0x03F2); - break; - case 0x03FA: - bufpush(0x03FB); - break; - case 0x03FD: - bufpush(0x037B); - break; - case 0x03FE: - bufpush(0x037C); - break; - case 0x03FF: - bufpush(0x037D); - break; - case 0x0400: - bufpush(0x0450); - break; - case 0x0401: - bufpush(0x0451); - break; - case 0x0402: - bufpush(0x0452); - break; - case 0x0403: - bufpush(0x0453); - break; - case 0x0404: - bufpush(0x0454); - break; - case 0x0405: - bufpush(0x0455); - break; - case 0x0406: - bufpush(0x0456); - break; - case 0x0407: - bufpush(0x0457); - break; - case 0x0408: - bufpush(0x0458); - break; - case 0x0409: - bufpush(0x0459); - break; - case 0x040A: - bufpush(0x045A); - break; - case 0x040B: - bufpush(0x045B); - break; - case 0x040C: - bufpush(0x045C); - break; - case 0x040D: - bufpush(0x045D); - break; - case 0x040E: - bufpush(0x045E); - break; - case 0x040F: - bufpush(0x045F); - break; - case 0x0410: - bufpush(0x0430); - break; - case 0x0411: - bufpush(0x0431); - break; - case 0x0412: - bufpush(0x0432); - break; - case 0x0413: - bufpush(0x0433); - break; - case 0x0414: - bufpush(0x0434); - break; - case 0x0415: - bufpush(0x0435); - break; - case 0x0416: - bufpush(0x0436); - break; - case 0x0417: - bufpush(0x0437); - break; - case 0x0418: - bufpush(0x0438); - break; - case 0x0419: - bufpush(0x0439); - break; - case 0x041A: - bufpush(0x043A); - break; - case 0x041B: - bufpush(0x043B); - break; - case 0x041C: - bufpush(0x043C); - break; - case 0x041D: - bufpush(0x043D); - break; - case 0x041E: - bufpush(0x043E); - break; - case 0x041F: - bufpush(0x043F); - break; - case 0x0420: - bufpush(0x0440); - break; - case 0x0421: - bufpush(0x0441); - break; - case 0x0422: - bufpush(0x0442); - break; - case 0x0423: - bufpush(0x0443); - break; - case 0x0424: - bufpush(0x0444); - break; - case 0x0425: - bufpush(0x0445); - break; - case 0x0426: - bufpush(0x0446); - break; - case 0x0427: - bufpush(0x0447); - break; - case 0x0428: - bufpush(0x0448); - break; - case 0x0429: - bufpush(0x0449); - break; - case 0x042A: - bufpush(0x044A); - break; - case 0x042B: - bufpush(0x044B); - break; - case 0x042C: - bufpush(0x044C); - break; - case 0x042D: - bufpush(0x044D); - break; - case 0x042E: - bufpush(0x044E); - break; - case 0x042F: - bufpush(0x044F); - break; - case 0x0460: - bufpush(0x0461); - break; - case 0x0462: - bufpush(0x0463); - break; - case 0x0464: - bufpush(0x0465); - break; - case 0x0466: - bufpush(0x0467); - break; - case 0x0468: - bufpush(0x0469); - break; - case 0x046A: - bufpush(0x046B); - break; - case 0x046C: - bufpush(0x046D); - break; - case 0x046E: - bufpush(0x046F); - break; - case 0x0470: - bufpush(0x0471); - break; - case 0x0472: - bufpush(0x0473); - break; - case 0x0474: - bufpush(0x0475); - break; - case 0x0476: - bufpush(0x0477); - break; - case 0x0478: - bufpush(0x0479); - break; - case 0x047A: - bufpush(0x047B); - break; - case 0x047C: - bufpush(0x047D); - break; - case 0x047E: - bufpush(0x047F); - break; - case 0x0480: - bufpush(0x0481); - break; - case 0x048A: - bufpush(0x048B); - break; - case 0x048C: - bufpush(0x048D); - break; - case 0x048E: - bufpush(0x048F); - break; - case 0x0490: - bufpush(0x0491); - break; - case 0x0492: - bufpush(0x0493); - break; - case 0x0494: - bufpush(0x0495); - break; - case 0x0496: - bufpush(0x0497); - break; - case 0x0498: - bufpush(0x0499); - break; - case 0x049A: - bufpush(0x049B); - break; - case 0x049C: - bufpush(0x049D); - break; - case 0x049E: - bufpush(0x049F); - break; - case 0x04A0: - bufpush(0x04A1); - break; - case 0x04A2: - bufpush(0x04A3); - break; - case 0x04A4: - bufpush(0x04A5); - break; - case 0x04A6: - bufpush(0x04A7); - break; - case 0x04A8: - bufpush(0x04A9); - break; - case 0x04AA: - bufpush(0x04AB); - break; - case 0x04AC: - bufpush(0x04AD); - break; - case 0x04AE: - bufpush(0x04AF); - break; - case 0x04B0: - bufpush(0x04B1); - break; - case 0x04B2: - bufpush(0x04B3); - break; - case 0x04B4: - bufpush(0x04B5); - break; - case 0x04B6: - bufpush(0x04B7); - break; - case 0x04B8: - bufpush(0x04B9); - break; - case 0x04BA: - bufpush(0x04BB); - break; - case 0x04BC: - bufpush(0x04BD); - break; - case 0x04BE: - bufpush(0x04BF); - break; - case 0x04C0: - bufpush(0x04CF); - break; - case 0x04C1: - bufpush(0x04C2); - break; - case 0x04C3: - bufpush(0x04C4); - break; - case 0x04C5: - bufpush(0x04C6); - break; - case 0x04C7: - bufpush(0x04C8); - break; - case 0x04C9: - bufpush(0x04CA); - break; - case 0x04CB: - bufpush(0x04CC); - break; - case 0x04CD: - bufpush(0x04CE); - break; - case 0x04D0: - bufpush(0x04D1); - break; - case 0x04D2: - bufpush(0x04D3); - break; - case 0x04D4: - bufpush(0x04D5); - break; - case 0x04D6: - bufpush(0x04D7); - break; - case 0x04D8: - bufpush(0x04D9); - break; - case 0x04DA: - bufpush(0x04DB); - break; - case 0x04DC: - bufpush(0x04DD); - break; - case 0x04DE: - bufpush(0x04DF); - break; - case 0x04E0: - bufpush(0x04E1); - break; - case 0x04E2: - bufpush(0x04E3); - break; - case 0x04E4: - bufpush(0x04E5); - break; - case 0x04E6: - bufpush(0x04E7); - break; - case 0x04E8: - bufpush(0x04E9); - break; - case 0x04EA: - bufpush(0x04EB); - break; - case 0x04EC: - bufpush(0x04ED); - break; - case 0x04EE: - bufpush(0x04EF); - break; - case 0x04F0: - bufpush(0x04F1); - break; - case 0x04F2: - bufpush(0x04F3); - break; - case 0x04F4: - bufpush(0x04F5); - break; - case 0x04F6: - bufpush(0x04F7); - break; - case 0x04F8: - bufpush(0x04F9); - break; - case 0x04FA: - bufpush(0x04FB); - break; - case 0x04FC: - bufpush(0x04FD); - break; - case 0x04FE: - bufpush(0x04FF); - break; - case 0x0500: - bufpush(0x0501); - break; - case 0x0502: - bufpush(0x0503); - break; - case 0x0504: - bufpush(0x0505); - break; - case 0x0506: - bufpush(0x0507); - break; - case 0x0508: - bufpush(0x0509); - break; - case 0x050A: - bufpush(0x050B); - break; - case 0x050C: - bufpush(0x050D); - break; - case 0x050E: - bufpush(0x050F); - break; - case 0x0510: - bufpush(0x0511); - break; - case 0x0512: - bufpush(0x0513); - break; - case 0x0514: - bufpush(0x0515); - break; - case 0x0516: - bufpush(0x0517); - break; - case 0x0518: - bufpush(0x0519); - break; - case 0x051A: - bufpush(0x051B); - break; - case 0x051C: - bufpush(0x051D); - break; - case 0x051E: - bufpush(0x051F); - break; - case 0x0520: - bufpush(0x0521); - break; - case 0x0522: - bufpush(0x0523); - break; - case 0x0524: - bufpush(0x0525); - break; - case 0x0526: - bufpush(0x0527); - break; - case 0x0528: - bufpush(0x0529); - break; - case 0x052A: - bufpush(0x052B); - break; - case 0x052C: - bufpush(0x052D); - break; - case 0x052E: - bufpush(0x052F); - break; - case 0x0531: - bufpush(0x0561); - break; - case 0x0532: - bufpush(0x0562); - break; - case 0x0533: - bufpush(0x0563); - break; - case 0x0534: - bufpush(0x0564); - break; - case 0x0535: - bufpush(0x0565); - break; - case 0x0536: - bufpush(0x0566); - break; - case 0x0537: - bufpush(0x0567); - break; - case 0x0538: - bufpush(0x0568); - break; - case 0x0539: - bufpush(0x0569); - break; - case 0x053A: - bufpush(0x056A); - break; - case 0x053B: - bufpush(0x056B); - break; - case 0x053C: - bufpush(0x056C); - break; - case 0x053D: - bufpush(0x056D); - break; - case 0x053E: - bufpush(0x056E); - break; - case 0x053F: - bufpush(0x056F); - break; - case 0x0540: - bufpush(0x0570); - break; - case 0x0541: - bufpush(0x0571); - break; - case 0x0542: - bufpush(0x0572); - break; - case 0x0543: - bufpush(0x0573); - break; - case 0x0544: - bufpush(0x0574); - break; - case 0x0545: - bufpush(0x0575); - break; - case 0x0546: - bufpush(0x0576); - break; - case 0x0547: - bufpush(0x0577); - break; - case 0x0548: - bufpush(0x0578); - break; - case 0x0549: - bufpush(0x0579); - break; - case 0x054A: - bufpush(0x057A); - break; - case 0x054B: - bufpush(0x057B); - break; - case 0x054C: - bufpush(0x057C); - break; - case 0x054D: - bufpush(0x057D); - break; - case 0x054E: - bufpush(0x057E); - break; - case 0x054F: - bufpush(0x057F); - break; - case 0x0550: - bufpush(0x0580); - break; - case 0x0551: - bufpush(0x0581); - break; - case 0x0552: - bufpush(0x0582); - break; - case 0x0553: - bufpush(0x0583); - break; - case 0x0554: - bufpush(0x0584); - break; - case 0x0555: - bufpush(0x0585); - break; - case 0x0556: - bufpush(0x0586); - break; - case 0x0587: - bufpush(0x0565); - bufpush(0x0582); - break; - case 0x10A0: - bufpush(0x2D00); - break; - case 0x10A1: - bufpush(0x2D01); - break; - case 0x10A2: - bufpush(0x2D02); - break; - case 0x10A3: - bufpush(0x2D03); - break; - case 0x10A4: - bufpush(0x2D04); - break; - case 0x10A5: - bufpush(0x2D05); - break; - case 0x10A6: - bufpush(0x2D06); - break; - case 0x10A7: - bufpush(0x2D07); - break; - case 0x10A8: - bufpush(0x2D08); - break; - case 0x10A9: - bufpush(0x2D09); - break; - case 0x10AA: - bufpush(0x2D0A); - break; - case 0x10AB: - bufpush(0x2D0B); - break; - case 0x10AC: - bufpush(0x2D0C); - break; - case 0x10AD: - bufpush(0x2D0D); - break; - case 0x10AE: - bufpush(0x2D0E); - break; - case 0x10AF: - bufpush(0x2D0F); - break; - case 0x10B0: - bufpush(0x2D10); - break; - case 0x10B1: - bufpush(0x2D11); - break; - case 0x10B2: - bufpush(0x2D12); - break; - case 0x10B3: - bufpush(0x2D13); - break; - case 0x10B4: - bufpush(0x2D14); - break; - case 0x10B5: - bufpush(0x2D15); - break; - case 0x10B6: - bufpush(0x2D16); - break; - case 0x10B7: - bufpush(0x2D17); - break; - case 0x10B8: - bufpush(0x2D18); - break; - case 0x10B9: - bufpush(0x2D19); - break; - case 0x10BA: - bufpush(0x2D1A); - break; - case 0x10BB: - bufpush(0x2D1B); - break; - case 0x10BC: - bufpush(0x2D1C); - break; - case 0x10BD: - bufpush(0x2D1D); - break; - case 0x10BE: - bufpush(0x2D1E); - break; - case 0x10BF: - bufpush(0x2D1F); - break; - case 0x10C0: - bufpush(0x2D20); - break; - case 0x10C1: - bufpush(0x2D21); - break; - case 0x10C2: - bufpush(0x2D22); - break; - case 0x10C3: - bufpush(0x2D23); - break; - case 0x10C4: - bufpush(0x2D24); - break; - case 0x10C5: - bufpush(0x2D25); - break; - case 0x10C7: - bufpush(0x2D27); - break; - case 0x10CD: - bufpush(0x2D2D); - break; - case 0x13F8: - bufpush(0x13F0); - break; - case 0x13F9: - bufpush(0x13F1); - break; - case 0x13FA: - bufpush(0x13F2); - break; - case 0x13FB: - bufpush(0x13F3); - break; - case 0x13FC: - bufpush(0x13F4); - break; - case 0x13FD: - bufpush(0x13F5); - break; - case 0x1C80: - bufpush(0x0432); - break; - case 0x1C81: - bufpush(0x0434); - break; - case 0x1C82: - bufpush(0x043E); - break; - case 0x1C83: - bufpush(0x0441); - break; - case 0x1C84: - bufpush(0x0442); - break; - case 0x1C85: - bufpush(0x0442); - break; - case 0x1C86: - bufpush(0x044A); - break; - case 0x1C87: - bufpush(0x0463); - break; - case 0x1C88: - bufpush(0xA64B); - break; - case 0x1E00: - bufpush(0x1E01); - break; - case 0x1E02: - bufpush(0x1E03); - break; - case 0x1E04: - bufpush(0x1E05); - break; - case 0x1E06: - bufpush(0x1E07); - break; - case 0x1E08: - bufpush(0x1E09); - break; - case 0x1E0A: - bufpush(0x1E0B); - break; - case 0x1E0C: - bufpush(0x1E0D); - break; - case 0x1E0E: - bufpush(0x1E0F); - break; - case 0x1E10: - bufpush(0x1E11); - break; - case 0x1E12: - bufpush(0x1E13); - break; - case 0x1E14: - bufpush(0x1E15); - break; - case 0x1E16: - bufpush(0x1E17); - break; - case 0x1E18: - bufpush(0x1E19); - break; - case 0x1E1A: - bufpush(0x1E1B); - break; - case 0x1E1C: - bufpush(0x1E1D); - break; - case 0x1E1E: - bufpush(0x1E1F); - break; - case 0x1E20: - bufpush(0x1E21); - break; - case 0x1E22: - bufpush(0x1E23); - break; - case 0x1E24: - bufpush(0x1E25); - break; - case 0x1E26: - bufpush(0x1E27); - break; - case 0x1E28: - bufpush(0x1E29); - break; - case 0x1E2A: - bufpush(0x1E2B); - break; - case 0x1E2C: - bufpush(0x1E2D); - break; - case 0x1E2E: - bufpush(0x1E2F); - break; - case 0x1E30: - bufpush(0x1E31); - break; - case 0x1E32: - bufpush(0x1E33); - break; - case 0x1E34: - bufpush(0x1E35); - break; - case 0x1E36: - bufpush(0x1E37); - break; - case 0x1E38: - bufpush(0x1E39); - break; - case 0x1E3A: - bufpush(0x1E3B); - break; - case 0x1E3C: - bufpush(0x1E3D); - break; - case 0x1E3E: - bufpush(0x1E3F); - break; - case 0x1E40: - bufpush(0x1E41); - break; - case 0x1E42: - bufpush(0x1E43); - break; - case 0x1E44: - bufpush(0x1E45); - break; - case 0x1E46: - bufpush(0x1E47); - break; - case 0x1E48: - bufpush(0x1E49); - break; - case 0x1E4A: - bufpush(0x1E4B); - break; - case 0x1E4C: - bufpush(0x1E4D); - break; - case 0x1E4E: - bufpush(0x1E4F); - break; - case 0x1E50: - bufpush(0x1E51); - break; - case 0x1E52: - bufpush(0x1E53); - break; - case 0x1E54: - bufpush(0x1E55); - break; - case 0x1E56: - bufpush(0x1E57); - break; - case 0x1E58: - bufpush(0x1E59); - break; - case 0x1E5A: - bufpush(0x1E5B); - break; - case 0x1E5C: - bufpush(0x1E5D); - break; - case 0x1E5E: - bufpush(0x1E5F); - break; - case 0x1E60: - bufpush(0x1E61); - break; - case 0x1E62: - bufpush(0x1E63); - break; - case 0x1E64: - bufpush(0x1E65); - break; - case 0x1E66: - bufpush(0x1E67); - break; - case 0x1E68: - bufpush(0x1E69); - break; - case 0x1E6A: - bufpush(0x1E6B); - break; - case 0x1E6C: - bufpush(0x1E6D); - break; - case 0x1E6E: - bufpush(0x1E6F); - break; - case 0x1E70: - bufpush(0x1E71); - break; - case 0x1E72: - bufpush(0x1E73); - break; - case 0x1E74: - bufpush(0x1E75); - break; - case 0x1E76: - bufpush(0x1E77); - break; - case 0x1E78: - bufpush(0x1E79); - break; - case 0x1E7A: - bufpush(0x1E7B); - break; - case 0x1E7C: - bufpush(0x1E7D); - break; - case 0x1E7E: - bufpush(0x1E7F); - break; - case 0x1E80: - bufpush(0x1E81); - break; - case 0x1E82: - bufpush(0x1E83); - break; - case 0x1E84: - bufpush(0x1E85); - break; - case 0x1E86: - bufpush(0x1E87); - break; - case 0x1E88: - bufpush(0x1E89); - break; - case 0x1E8A: - bufpush(0x1E8B); - break; - case 0x1E8C: - bufpush(0x1E8D); - break; - case 0x1E8E: - bufpush(0x1E8F); - break; - case 0x1E90: - bufpush(0x1E91); - break; - case 0x1E92: - bufpush(0x1E93); - break; - case 0x1E94: - bufpush(0x1E95); - break; - case 0x1E96: - bufpush(0x0068); - bufpush(0x0331); - break; - case 0x1E97: - bufpush(0x0074); - bufpush(0x0308); - break; - case 0x1E98: - bufpush(0x0077); - bufpush(0x030A); - break; - case 0x1E99: - bufpush(0x0079); - bufpush(0x030A); - break; - case 0x1E9A: - bufpush(0x0061); - bufpush(0x02BE); - break; - case 0x1E9B: - bufpush(0x1E61); - break; - case 0x1E9E: - bufpush(0x0073); - bufpush(0x0073); - break; - case 0x1EA0: - bufpush(0x1EA1); - break; - case 0x1EA2: - bufpush(0x1EA3); - break; - case 0x1EA4: - bufpush(0x1EA5); - break; - case 0x1EA6: - bufpush(0x1EA7); - break; - case 0x1EA8: - bufpush(0x1EA9); - break; - case 0x1EAA: - bufpush(0x1EAB); - break; - case 0x1EAC: - bufpush(0x1EAD); - break; - case 0x1EAE: - bufpush(0x1EAF); - break; - case 0x1EB0: - bufpush(0x1EB1); - break; - case 0x1EB2: - bufpush(0x1EB3); - break; - case 0x1EB4: - bufpush(0x1EB5); - break; - case 0x1EB6: - bufpush(0x1EB7); - break; - case 0x1EB8: - bufpush(0x1EB9); - break; - case 0x1EBA: - bufpush(0x1EBB); - break; - case 0x1EBC: - bufpush(0x1EBD); - break; - case 0x1EBE: - bufpush(0x1EBF); - break; - case 0x1EC0: - bufpush(0x1EC1); - break; - case 0x1EC2: - bufpush(0x1EC3); - break; - case 0x1EC4: - bufpush(0x1EC5); - break; - case 0x1EC6: - bufpush(0x1EC7); - break; - case 0x1EC8: - bufpush(0x1EC9); - break; - case 0x1ECA: - bufpush(0x1ECB); - break; - case 0x1ECC: - bufpush(0x1ECD); - break; - case 0x1ECE: - bufpush(0x1ECF); - break; - case 0x1ED0: - bufpush(0x1ED1); - break; - case 0x1ED2: - bufpush(0x1ED3); - break; - case 0x1ED4: - bufpush(0x1ED5); - break; - case 0x1ED6: - bufpush(0x1ED7); - break; - case 0x1ED8: - bufpush(0x1ED9); - break; - case 0x1EDA: - bufpush(0x1EDB); - break; - case 0x1EDC: - bufpush(0x1EDD); - break; - case 0x1EDE: - bufpush(0x1EDF); - break; - case 0x1EE0: - bufpush(0x1EE1); - break; - case 0x1EE2: - bufpush(0x1EE3); - break; - case 0x1EE4: - bufpush(0x1EE5); - break; - case 0x1EE6: - bufpush(0x1EE7); - break; - case 0x1EE8: - bufpush(0x1EE9); - break; - case 0x1EEA: - bufpush(0x1EEB); - break; - case 0x1EEC: - bufpush(0x1EED); - break; - case 0x1EEE: - bufpush(0x1EEF); - break; - case 0x1EF0: - bufpush(0x1EF1); - break; - case 0x1EF2: - bufpush(0x1EF3); - break; - case 0x1EF4: - bufpush(0x1EF5); - break; - case 0x1EF6: - bufpush(0x1EF7); - break; - case 0x1EF8: - bufpush(0x1EF9); - break; - case 0x1EFA: - bufpush(0x1EFB); - break; - case 0x1EFC: - bufpush(0x1EFD); - break; - case 0x1EFE: - bufpush(0x1EFF); - break; - case 0x1F08: - bufpush(0x1F00); - break; - case 0x1F09: - bufpush(0x1F01); - break; - case 0x1F0A: - bufpush(0x1F02); - break; - case 0x1F0B: - bufpush(0x1F03); - break; - case 0x1F0C: - bufpush(0x1F04); - break; - case 0x1F0D: - bufpush(0x1F05); - break; - case 0x1F0E: - bufpush(0x1F06); - break; - case 0x1F0F: - bufpush(0x1F07); - break; - case 0x1F18: - bufpush(0x1F10); - break; - case 0x1F19: - bufpush(0x1F11); - break; - case 0x1F1A: - bufpush(0x1F12); - break; - case 0x1F1B: - bufpush(0x1F13); - break; - case 0x1F1C: - bufpush(0x1F14); - break; - case 0x1F1D: - bufpush(0x1F15); - break; - case 0x1F28: - bufpush(0x1F20); - break; - case 0x1F29: - bufpush(0x1F21); - break; - case 0x1F2A: - bufpush(0x1F22); - break; - case 0x1F2B: - bufpush(0x1F23); - break; - case 0x1F2C: - bufpush(0x1F24); - break; - case 0x1F2D: - bufpush(0x1F25); - break; - case 0x1F2E: - bufpush(0x1F26); - break; - case 0x1F2F: - bufpush(0x1F27); - break; - case 0x1F38: - bufpush(0x1F30); - break; - case 0x1F39: - bufpush(0x1F31); - break; - case 0x1F3A: - bufpush(0x1F32); - break; - case 0x1F3B: - bufpush(0x1F33); - break; - case 0x1F3C: - bufpush(0x1F34); - break; - case 0x1F3D: - bufpush(0x1F35); - break; - case 0x1F3E: - bufpush(0x1F36); - break; - case 0x1F3F: - bufpush(0x1F37); - break; - case 0x1F48: - bufpush(0x1F40); - break; - case 0x1F49: - bufpush(0x1F41); - break; - case 0x1F4A: - bufpush(0x1F42); - break; - case 0x1F4B: - bufpush(0x1F43); - break; - case 0x1F4C: - bufpush(0x1F44); - break; - case 0x1F4D: - bufpush(0x1F45); - break; - case 0x1F50: - bufpush(0x03C5); - bufpush(0x0313); - break; - case 0x1F52: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0300); - break; - case 0x1F54: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0301); - break; - case 0x1F56: - bufpush(0x03C5); - bufpush(0x0313); - bufpush(0x0342); - break; - case 0x1F59: - bufpush(0x1F51); - break; - case 0x1F5B: - bufpush(0x1F53); - break; - case 0x1F5D: - bufpush(0x1F55); - break; - case 0x1F5F: - bufpush(0x1F57); - break; - case 0x1F68: - bufpush(0x1F60); - break; - case 0x1F69: - bufpush(0x1F61); - break; - case 0x1F6A: - bufpush(0x1F62); - break; - case 0x1F6B: - bufpush(0x1F63); - break; - case 0x1F6C: - bufpush(0x1F64); - break; - case 0x1F6D: - bufpush(0x1F65); - break; - case 0x1F6E: - bufpush(0x1F66); - break; - case 0x1F6F: - bufpush(0x1F67); - break; - case 0x1F80: - bufpush(0x1F00); - bufpush(0x03B9); - break; - case 0x1F81: - bufpush(0x1F01); - bufpush(0x03B9); - break; - case 0x1F82: - bufpush(0x1F02); - bufpush(0x03B9); - break; - case 0x1F83: - bufpush(0x1F03); - bufpush(0x03B9); - break; - case 0x1F84: - bufpush(0x1F04); - bufpush(0x03B9); - break; - case 0x1F85: - bufpush(0x1F05); - bufpush(0x03B9); - break; - case 0x1F86: - bufpush(0x1F06); - bufpush(0x03B9); - break; - case 0x1F87: - bufpush(0x1F07); - bufpush(0x03B9); - break; - case 0x1F88: - bufpush(0x1F00); - bufpush(0x03B9); - break; - case 0x1F89: - bufpush(0x1F01); - bufpush(0x03B9); - break; - case 0x1F8A: - bufpush(0x1F02); - bufpush(0x03B9); - break; - case 0x1F8B: - bufpush(0x1F03); - bufpush(0x03B9); - break; - case 0x1F8C: - bufpush(0x1F04); - bufpush(0x03B9); - break; - case 0x1F8D: - bufpush(0x1F05); - bufpush(0x03B9); - break; - case 0x1F8E: - bufpush(0x1F06); - bufpush(0x03B9); - break; - case 0x1F8F: - bufpush(0x1F07); - bufpush(0x03B9); - break; - case 0x1F90: - bufpush(0x1F20); - bufpush(0x03B9); - break; - case 0x1F91: - bufpush(0x1F21); - bufpush(0x03B9); - break; - case 0x1F92: - bufpush(0x1F22); - bufpush(0x03B9); - break; - case 0x1F93: - bufpush(0x1F23); - bufpush(0x03B9); - break; - case 0x1F94: - bufpush(0x1F24); - bufpush(0x03B9); - break; - case 0x1F95: - bufpush(0x1F25); - bufpush(0x03B9); - break; - case 0x1F96: - bufpush(0x1F26); - bufpush(0x03B9); - break; - case 0x1F97: - bufpush(0x1F27); - bufpush(0x03B9); - break; - case 0x1F98: - bufpush(0x1F20); - bufpush(0x03B9); - break; - case 0x1F99: - bufpush(0x1F21); - bufpush(0x03B9); - break; - case 0x1F9A: - bufpush(0x1F22); - bufpush(0x03B9); - break; - case 0x1F9B: - bufpush(0x1F23); - bufpush(0x03B9); - break; - case 0x1F9C: - bufpush(0x1F24); - bufpush(0x03B9); - break; - case 0x1F9D: - bufpush(0x1F25); - bufpush(0x03B9); - break; - case 0x1F9E: - bufpush(0x1F26); - bufpush(0x03B9); - break; - case 0x1F9F: - bufpush(0x1F27); - bufpush(0x03B9); - break; - case 0x1FA0: - bufpush(0x1F60); - bufpush(0x03B9); - break; - case 0x1FA1: - bufpush(0x1F61); - bufpush(0x03B9); - break; - case 0x1FA2: - bufpush(0x1F62); - bufpush(0x03B9); - break; - case 0x1FA3: - bufpush(0x1F63); - bufpush(0x03B9); - break; - case 0x1FA4: - bufpush(0x1F64); - bufpush(0x03B9); - break; - case 0x1FA5: - bufpush(0x1F65); - bufpush(0x03B9); - break; - case 0x1FA6: - bufpush(0x1F66); - bufpush(0x03B9); - break; - case 0x1FA7: - bufpush(0x1F67); - bufpush(0x03B9); - break; - case 0x1FA8: - bufpush(0x1F60); - bufpush(0x03B9); - break; - case 0x1FA9: - bufpush(0x1F61); - bufpush(0x03B9); - break; - case 0x1FAA: - bufpush(0x1F62); - bufpush(0x03B9); - break; - case 0x1FAB: - bufpush(0x1F63); - bufpush(0x03B9); - break; - case 0x1FAC: - bufpush(0x1F64); - bufpush(0x03B9); - break; - case 0x1FAD: - bufpush(0x1F65); - bufpush(0x03B9); - break; - case 0x1FAE: - bufpush(0x1F66); - bufpush(0x03B9); - break; - case 0x1FAF: - bufpush(0x1F67); - bufpush(0x03B9); - break; - case 0x1FB2: - bufpush(0x1F70); - bufpush(0x03B9); - break; - case 0x1FB3: - bufpush(0x03B1); - bufpush(0x03B9); - break; - case 0x1FB4: - bufpush(0x03AC); - bufpush(0x03B9); - break; - case 0x1FB6: - bufpush(0x03B1); - bufpush(0x0342); - break; - case 0x1FB7: - bufpush(0x03B1); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FB8: - bufpush(0x1FB0); - break; - case 0x1FB9: - bufpush(0x1FB1); - break; - case 0x1FBA: - bufpush(0x1F70); - break; - case 0x1FBB: - bufpush(0x1F71); - break; - case 0x1FBC: - bufpush(0x03B1); - bufpush(0x03B9); - break; - case 0x1FBE: - bufpush(0x03B9); - break; - case 0x1FC2: - bufpush(0x1F74); - bufpush(0x03B9); - break; - case 0x1FC3: - bufpush(0x03B7); - bufpush(0x03B9); - break; - case 0x1FC4: - bufpush(0x03AE); - bufpush(0x03B9); - break; - case 0x1FC6: - bufpush(0x03B7); - bufpush(0x0342); - break; - case 0x1FC7: - bufpush(0x03B7); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FC8: - bufpush(0x1F72); - break; - case 0x1FC9: - bufpush(0x1F73); - break; - case 0x1FCA: - bufpush(0x1F74); - break; - case 0x1FCB: - bufpush(0x1F75); - break; - case 0x1FCC: - bufpush(0x03B7); - bufpush(0x03B9); - break; - case 0x1FD2: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0300); - break; - case 0x1FD3: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x1FD6: - bufpush(0x03B9); - bufpush(0x0342); - break; - case 0x1FD7: - bufpush(0x03B9); - bufpush(0x0308); - bufpush(0x0342); - break; - case 0x1FD8: - bufpush(0x1FD0); - break; - case 0x1FD9: - bufpush(0x1FD1); - break; - case 0x1FDA: - bufpush(0x1F76); - break; - case 0x1FDB: - bufpush(0x1F77); - break; - case 0x1FE2: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0300); - break; - case 0x1FE3: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0301); - break; - case 0x1FE4: - bufpush(0x03C1); - bufpush(0x0313); - break; - case 0x1FE6: - bufpush(0x03C5); - bufpush(0x0342); - break; - case 0x1FE7: - bufpush(0x03C5); - bufpush(0x0308); - bufpush(0x0342); - break; - case 0x1FE8: - bufpush(0x1FE0); - break; - case 0x1FE9: - bufpush(0x1FE1); - break; - case 0x1FEA: - bufpush(0x1F7A); - break; - case 0x1FEB: - bufpush(0x1F7B); - break; - case 0x1FEC: - bufpush(0x1FE5); - break; - case 0x1FF2: - bufpush(0x1F7C); - bufpush(0x03B9); - break; - case 0x1FF3: - bufpush(0x03C9); - bufpush(0x03B9); - break; - case 0x1FF4: - bufpush(0x03CE); - bufpush(0x03B9); - break; - case 0x1FF6: - bufpush(0x03C9); - bufpush(0x0342); - break; - case 0x1FF7: - bufpush(0x03C9); - bufpush(0x0342); - bufpush(0x03B9); - break; - case 0x1FF8: - bufpush(0x1F78); - break; - case 0x1FF9: - bufpush(0x1F79); - break; - case 0x1FFA: - bufpush(0x1F7C); - break; - case 0x1FFB: - bufpush(0x1F7D); - break; - case 0x1FFC: - bufpush(0x03C9); - bufpush(0x03B9); - break; - case 0x2126: - bufpush(0x03C9); - break; - case 0x212A: - bufpush(0x006B); - break; - case 0x212B: - bufpush(0x00E5); - break; - case 0x2132: - bufpush(0x214E); - break; - case 0x2160: - bufpush(0x2170); - break; - case 0x2161: - bufpush(0x2171); - break; - case 0x2162: - bufpush(0x2172); - break; - case 0x2163: - bufpush(0x2173); - break; - case 0x2164: - bufpush(0x2174); - break; - case 0x2165: - bufpush(0x2175); - break; - case 0x2166: - bufpush(0x2176); - break; - case 0x2167: - bufpush(0x2177); - break; - case 0x2168: - bufpush(0x2178); - break; - case 0x2169: - bufpush(0x2179); - break; - case 0x216A: - bufpush(0x217A); - break; - case 0x216B: - bufpush(0x217B); - break; - case 0x216C: - bufpush(0x217C); - break; - case 0x216D: - bufpush(0x217D); - break; - case 0x216E: - bufpush(0x217E); - break; - case 0x216F: - bufpush(0x217F); - break; - case 0x2183: - bufpush(0x2184); - break; - case 0x24B6: - bufpush(0x24D0); - break; - case 0x24B7: - bufpush(0x24D1); - break; - case 0x24B8: - bufpush(0x24D2); - break; - case 0x24B9: - bufpush(0x24D3); - break; - case 0x24BA: - bufpush(0x24D4); - break; - case 0x24BB: - bufpush(0x24D5); - break; - case 0x24BC: - bufpush(0x24D6); - break; - case 0x24BD: - bufpush(0x24D7); - break; - case 0x24BE: - bufpush(0x24D8); - break; - case 0x24BF: - bufpush(0x24D9); - break; - case 0x24C0: - bufpush(0x24DA); - break; - case 0x24C1: - bufpush(0x24DB); - break; - case 0x24C2: - bufpush(0x24DC); - break; - case 0x24C3: - bufpush(0x24DD); - break; - case 0x24C4: - bufpush(0x24DE); - break; - case 0x24C5: - bufpush(0x24DF); - break; - case 0x24C6: - bufpush(0x24E0); - break; - case 0x24C7: - bufpush(0x24E1); - break; - case 0x24C8: - bufpush(0x24E2); - break; - case 0x24C9: - bufpush(0x24E3); - break; - case 0x24CA: - bufpush(0x24E4); - break; - case 0x24CB: - bufpush(0x24E5); - break; - case 0x24CC: - bufpush(0x24E6); - break; - case 0x24CD: - bufpush(0x24E7); - break; - case 0x24CE: - bufpush(0x24E8); - break; - case 0x24CF: - bufpush(0x24E9); - break; - case 0x2C00: - bufpush(0x2C30); - break; - case 0x2C01: - bufpush(0x2C31); - break; - case 0x2C02: - bufpush(0x2C32); - break; - case 0x2C03: - bufpush(0x2C33); - break; - case 0x2C04: - bufpush(0x2C34); - break; - case 0x2C05: - bufpush(0x2C35); - break; - case 0x2C06: - bufpush(0x2C36); - break; - case 0x2C07: - bufpush(0x2C37); - break; - case 0x2C08: - bufpush(0x2C38); - break; - case 0x2C09: - bufpush(0x2C39); - break; - case 0x2C0A: - bufpush(0x2C3A); - break; - case 0x2C0B: - bufpush(0x2C3B); - break; - case 0x2C0C: - bufpush(0x2C3C); - break; - case 0x2C0D: - bufpush(0x2C3D); - break; - case 0x2C0E: - bufpush(0x2C3E); - break; - case 0x2C0F: - bufpush(0x2C3F); - break; - case 0x2C10: - bufpush(0x2C40); - break; - case 0x2C11: - bufpush(0x2C41); - break; - case 0x2C12: - bufpush(0x2C42); - break; - case 0x2C13: - bufpush(0x2C43); - break; - case 0x2C14: - bufpush(0x2C44); - break; - case 0x2C15: - bufpush(0x2C45); - break; - case 0x2C16: - bufpush(0x2C46); - break; - case 0x2C17: - bufpush(0x2C47); - break; - case 0x2C18: - bufpush(0x2C48); - break; - case 0x2C19: - bufpush(0x2C49); - break; - case 0x2C1A: - bufpush(0x2C4A); - break; - case 0x2C1B: - bufpush(0x2C4B); - break; - case 0x2C1C: - bufpush(0x2C4C); - break; - case 0x2C1D: - bufpush(0x2C4D); - break; - case 0x2C1E: - bufpush(0x2C4E); - break; - case 0x2C1F: - bufpush(0x2C4F); - break; - case 0x2C20: - bufpush(0x2C50); - break; - case 0x2C21: - bufpush(0x2C51); - break; - case 0x2C22: - bufpush(0x2C52); - break; - case 0x2C23: - bufpush(0x2C53); - break; - case 0x2C24: - bufpush(0x2C54); - break; - case 0x2C25: - bufpush(0x2C55); - break; - case 0x2C26: - bufpush(0x2C56); - break; - case 0x2C27: - bufpush(0x2C57); - break; - case 0x2C28: - bufpush(0x2C58); - break; - case 0x2C29: - bufpush(0x2C59); - break; - case 0x2C2A: - bufpush(0x2C5A); - break; - case 0x2C2B: - bufpush(0x2C5B); - break; - case 0x2C2C: - bufpush(0x2C5C); - break; - case 0x2C2D: - bufpush(0x2C5D); - break; - case 0x2C2E: - bufpush(0x2C5E); - break; - case 0x2C60: - bufpush(0x2C61); - break; - case 0x2C62: - bufpush(0x026B); - break; - case 0x2C63: - bufpush(0x1D7D); - break; - case 0x2C64: - bufpush(0x027D); - break; - case 0x2C67: - bufpush(0x2C68); - break; - case 0x2C69: - bufpush(0x2C6A); - break; - case 0x2C6B: - bufpush(0x2C6C); - break; - case 0x2C6D: - bufpush(0x0251); - break; - case 0x2C6E: - bufpush(0x0271); - break; - case 0x2C6F: - bufpush(0x0250); - break; - case 0x2C70: - bufpush(0x0252); - break; - case 0x2C72: - bufpush(0x2C73); - break; - case 0x2C75: - bufpush(0x2C76); - break; - case 0x2C7E: - bufpush(0x023F); - break; - case 0x2C7F: - bufpush(0x0240); - break; - case 0x2C80: - bufpush(0x2C81); - break; - case 0x2C82: - bufpush(0x2C83); - break; - case 0x2C84: - bufpush(0x2C85); - break; - case 0x2C86: - bufpush(0x2C87); - break; - case 0x2C88: - bufpush(0x2C89); - break; - case 0x2C8A: - bufpush(0x2C8B); - break; - case 0x2C8C: - bufpush(0x2C8D); - break; - case 0x2C8E: - bufpush(0x2C8F); - break; - case 0x2C90: - bufpush(0x2C91); - break; - case 0x2C92: - bufpush(0x2C93); - break; - case 0x2C94: - bufpush(0x2C95); - break; - case 0x2C96: - bufpush(0x2C97); - break; - case 0x2C98: - bufpush(0x2C99); - break; - case 0x2C9A: - bufpush(0x2C9B); - break; - case 0x2C9C: - bufpush(0x2C9D); - break; - case 0x2C9E: - bufpush(0x2C9F); - break; - case 0x2CA0: - bufpush(0x2CA1); - break; - case 0x2CA2: - bufpush(0x2CA3); - break; - case 0x2CA4: - bufpush(0x2CA5); - break; - case 0x2CA6: - bufpush(0x2CA7); - break; - case 0x2CA8: - bufpush(0x2CA9); - break; - case 0x2CAA: - bufpush(0x2CAB); - break; - case 0x2CAC: - bufpush(0x2CAD); - break; - case 0x2CAE: - bufpush(0x2CAF); - break; - case 0x2CB0: - bufpush(0x2CB1); - break; - case 0x2CB2: - bufpush(0x2CB3); - break; - case 0x2CB4: - bufpush(0x2CB5); - break; - case 0x2CB6: - bufpush(0x2CB7); - break; - case 0x2CB8: - bufpush(0x2CB9); - break; - case 0x2CBA: - bufpush(0x2CBB); - break; - case 0x2CBC: - bufpush(0x2CBD); - break; - case 0x2CBE: - bufpush(0x2CBF); - break; - case 0x2CC0: - bufpush(0x2CC1); - break; - case 0x2CC2: - bufpush(0x2CC3); - break; - case 0x2CC4: - bufpush(0x2CC5); - break; - case 0x2CC6: - bufpush(0x2CC7); - break; - case 0x2CC8: - bufpush(0x2CC9); - break; - case 0x2CCA: - bufpush(0x2CCB); - break; - case 0x2CCC: - bufpush(0x2CCD); - break; - case 0x2CCE: - bufpush(0x2CCF); - break; - case 0x2CD0: - bufpush(0x2CD1); - break; - case 0x2CD2: - bufpush(0x2CD3); - break; - case 0x2CD4: - bufpush(0x2CD5); - break; - case 0x2CD6: - bufpush(0x2CD7); - break; - case 0x2CD8: - bufpush(0x2CD9); - break; - case 0x2CDA: - bufpush(0x2CDB); - break; - case 0x2CDC: - bufpush(0x2CDD); - break; - case 0x2CDE: - bufpush(0x2CDF); - break; - case 0x2CE0: - bufpush(0x2CE1); - break; - case 0x2CE2: - bufpush(0x2CE3); - break; - case 0x2CEB: - bufpush(0x2CEC); - break; - case 0x2CED: - bufpush(0x2CEE); - break; - case 0x2CF2: - bufpush(0x2CF3); - break; - case 0xA640: - bufpush(0xA641); - break; - case 0xA642: - bufpush(0xA643); - break; - case 0xA644: - bufpush(0xA645); - break; - case 0xA646: - bufpush(0xA647); - break; - case 0xA648: - bufpush(0xA649); - break; - case 0xA64A: - bufpush(0xA64B); - break; - case 0xA64C: - bufpush(0xA64D); - break; - case 0xA64E: - bufpush(0xA64F); - break; - case 0xA650: - bufpush(0xA651); - break; - case 0xA652: - bufpush(0xA653); - break; - case 0xA654: - bufpush(0xA655); - break; - case 0xA656: - bufpush(0xA657); - break; - case 0xA658: - bufpush(0xA659); - break; - case 0xA65A: - bufpush(0xA65B); - break; - case 0xA65C: - bufpush(0xA65D); - break; - case 0xA65E: - bufpush(0xA65F); - break; - case 0xA660: - bufpush(0xA661); - break; - case 0xA662: - bufpush(0xA663); - break; - case 0xA664: - bufpush(0xA665); - break; - case 0xA666: - bufpush(0xA667); - break; - case 0xA668: - bufpush(0xA669); - break; - case 0xA66A: - bufpush(0xA66B); - break; - case 0xA66C: - bufpush(0xA66D); - break; - case 0xA680: - bufpush(0xA681); - break; - case 0xA682: - bufpush(0xA683); - break; - case 0xA684: - bufpush(0xA685); - break; - case 0xA686: - bufpush(0xA687); - break; - case 0xA688: - bufpush(0xA689); - break; - case 0xA68A: - bufpush(0xA68B); - break; - case 0xA68C: - bufpush(0xA68D); - break; - case 0xA68E: - bufpush(0xA68F); - break; - case 0xA690: - bufpush(0xA691); - break; - case 0xA692: - bufpush(0xA693); - break; - case 0xA694: - bufpush(0xA695); - break; - case 0xA696: - bufpush(0xA697); - break; - case 0xA698: - bufpush(0xA699); - break; - case 0xA69A: - bufpush(0xA69B); - break; - case 0xA722: - bufpush(0xA723); - break; - case 0xA724: - bufpush(0xA725); - break; - case 0xA726: - bufpush(0xA727); - break; - case 0xA728: - bufpush(0xA729); - break; - case 0xA72A: - bufpush(0xA72B); - break; - case 0xA72C: - bufpush(0xA72D); - break; - case 0xA72E: - bufpush(0xA72F); - break; - case 0xA732: - bufpush(0xA733); - break; - case 0xA734: - bufpush(0xA735); - break; - case 0xA736: - bufpush(0xA737); - break; - case 0xA738: - bufpush(0xA739); - break; - case 0xA73A: - bufpush(0xA73B); - break; - case 0xA73C: - bufpush(0xA73D); - break; - case 0xA73E: - bufpush(0xA73F); - break; - case 0xA740: - bufpush(0xA741); - break; - case 0xA742: - bufpush(0xA743); - break; - case 0xA744: - bufpush(0xA745); - break; - case 0xA746: - bufpush(0xA747); - break; - case 0xA748: - bufpush(0xA749); - break; - case 0xA74A: - bufpush(0xA74B); - break; - case 0xA74C: - bufpush(0xA74D); - break; - case 0xA74E: - bufpush(0xA74F); - break; - case 0xA750: - bufpush(0xA751); - break; - case 0xA752: - bufpush(0xA753); - break; - case 0xA754: - bufpush(0xA755); - break; - case 0xA756: - bufpush(0xA757); - break; - case 0xA758: - bufpush(0xA759); - break; - case 0xA75A: - bufpush(0xA75B); - break; - case 0xA75C: - bufpush(0xA75D); - break; - case 0xA75E: - bufpush(0xA75F); - break; - case 0xA760: - bufpush(0xA761); - break; - case 0xA762: - bufpush(0xA763); - break; - case 0xA764: - bufpush(0xA765); - break; - case 0xA766: - bufpush(0xA767); - break; - case 0xA768: - bufpush(0xA769); - break; - case 0xA76A: - bufpush(0xA76B); - break; - case 0xA76C: - bufpush(0xA76D); - break; - case 0xA76E: - bufpush(0xA76F); - break; - case 0xA779: - bufpush(0xA77A); - break; - case 0xA77B: - bufpush(0xA77C); - break; - case 0xA77D: - bufpush(0x1D79); - break; - case 0xA77E: - bufpush(0xA77F); - break; - case 0xA780: - bufpush(0xA781); - break; - case 0xA782: - bufpush(0xA783); - break; - case 0xA784: - bufpush(0xA785); - break; - case 0xA786: - bufpush(0xA787); - break; - case 0xA78B: - bufpush(0xA78C); - break; - case 0xA78D: - bufpush(0x0265); - break; - case 0xA790: - bufpush(0xA791); - break; - case 0xA792: - bufpush(0xA793); - break; - case 0xA796: - bufpush(0xA797); - break; - case 0xA798: - bufpush(0xA799); - break; - case 0xA79A: - bufpush(0xA79B); - break; - case 0xA79C: - bufpush(0xA79D); - break; - case 0xA79E: - bufpush(0xA79F); - break; - case 0xA7A0: - bufpush(0xA7A1); - break; - case 0xA7A2: - bufpush(0xA7A3); - break; - case 0xA7A4: - bufpush(0xA7A5); - break; - case 0xA7A6: - bufpush(0xA7A7); - break; - case 0xA7A8: - bufpush(0xA7A9); - break; - case 0xA7AA: - bufpush(0x0266); - break; - case 0xA7AB: - bufpush(0x025C); - break; - case 0xA7AC: - bufpush(0x0261); - break; - case 0xA7AD: - bufpush(0x026C); - break; - case 0xA7AE: - bufpush(0x026A); - break; - case 0xA7B0: - bufpush(0x029E); - break; - case 0xA7B1: - bufpush(0x0287); - break; - case 0xA7B2: - bufpush(0x029D); - break; - case 0xA7B3: - bufpush(0xAB53); - break; - case 0xA7B4: - bufpush(0xA7B5); - break; - case 0xA7B6: - bufpush(0xA7B7); - break; - case 0xAB70: - bufpush(0x13A0); - break; - case 0xAB71: - bufpush(0x13A1); - break; - case 0xAB72: - bufpush(0x13A2); - break; - case 0xAB73: - bufpush(0x13A3); - break; - case 0xAB74: - bufpush(0x13A4); - break; - case 0xAB75: - bufpush(0x13A5); - break; - case 0xAB76: - bufpush(0x13A6); - break; - case 0xAB77: - bufpush(0x13A7); - break; - case 0xAB78: - bufpush(0x13A8); - break; - case 0xAB79: - bufpush(0x13A9); - break; - case 0xAB7A: - bufpush(0x13AA); - break; - case 0xAB7B: - bufpush(0x13AB); - break; - case 0xAB7C: - bufpush(0x13AC); - break; - case 0xAB7D: - bufpush(0x13AD); - break; - case 0xAB7E: - bufpush(0x13AE); - break; - case 0xAB7F: - bufpush(0x13AF); - break; - case 0xAB80: - bufpush(0x13B0); - break; - case 0xAB81: - bufpush(0x13B1); - break; - case 0xAB82: - bufpush(0x13B2); - break; - case 0xAB83: - bufpush(0x13B3); - break; - case 0xAB84: - bufpush(0x13B4); - break; - case 0xAB85: - bufpush(0x13B5); - break; - case 0xAB86: - bufpush(0x13B6); - break; - case 0xAB87: - bufpush(0x13B7); - break; - case 0xAB88: - bufpush(0x13B8); - break; - case 0xAB89: - bufpush(0x13B9); - break; - case 0xAB8A: - bufpush(0x13BA); - break; - case 0xAB8B: - bufpush(0x13BB); - break; - case 0xAB8C: - bufpush(0x13BC); - break; - case 0xAB8D: - bufpush(0x13BD); - break; - case 0xAB8E: - bufpush(0x13BE); - break; - case 0xAB8F: - bufpush(0x13BF); - break; - case 0xAB90: - bufpush(0x13C0); - break; - case 0xAB91: - bufpush(0x13C1); - break; - case 0xAB92: - bufpush(0x13C2); - break; - case 0xAB93: - bufpush(0x13C3); - break; - case 0xAB94: - bufpush(0x13C4); - break; - case 0xAB95: - bufpush(0x13C5); - break; - case 0xAB96: - bufpush(0x13C6); - break; - case 0xAB97: - bufpush(0x13C7); - break; - case 0xAB98: - bufpush(0x13C8); - break; - case 0xAB99: - bufpush(0x13C9); - break; - case 0xAB9A: - bufpush(0x13CA); - break; - case 0xAB9B: - bufpush(0x13CB); - break; - case 0xAB9C: - bufpush(0x13CC); - break; - case 0xAB9D: - bufpush(0x13CD); - break; - case 0xAB9E: - bufpush(0x13CE); - break; - case 0xAB9F: - bufpush(0x13CF); - break; - case 0xABA0: - bufpush(0x13D0); - break; - case 0xABA1: - bufpush(0x13D1); - break; - case 0xABA2: - bufpush(0x13D2); - break; - case 0xABA3: - bufpush(0x13D3); - break; - case 0xABA4: - bufpush(0x13D4); - break; - case 0xABA5: - bufpush(0x13D5); - break; - case 0xABA6: - bufpush(0x13D6); - break; - case 0xABA7: - bufpush(0x13D7); - break; - case 0xABA8: - bufpush(0x13D8); - break; - case 0xABA9: - bufpush(0x13D9); - break; - case 0xABAA: - bufpush(0x13DA); - break; - case 0xABAB: - bufpush(0x13DB); - break; - case 0xABAC: - bufpush(0x13DC); - break; - case 0xABAD: - bufpush(0x13DD); - break; - case 0xABAE: - bufpush(0x13DE); - break; - case 0xABAF: - bufpush(0x13DF); - break; - case 0xABB0: - bufpush(0x13E0); - break; - case 0xABB1: - bufpush(0x13E1); - break; - case 0xABB2: - bufpush(0x13E2); - break; - case 0xABB3: - bufpush(0x13E3); - break; - case 0xABB4: - bufpush(0x13E4); - break; - case 0xABB5: - bufpush(0x13E5); - break; - case 0xABB6: - bufpush(0x13E6); - break; - case 0xABB7: - bufpush(0x13E7); - break; - case 0xABB8: - bufpush(0x13E8); - break; - case 0xABB9: - bufpush(0x13E9); - break; - case 0xABBA: - bufpush(0x13EA); - break; - case 0xABBB: - bufpush(0x13EB); - break; - case 0xABBC: - bufpush(0x13EC); - break; - case 0xABBD: - bufpush(0x13ED); - break; - case 0xABBE: - bufpush(0x13EE); - break; - case 0xABBF: - bufpush(0x13EF); - break; - case 0xFB00: - bufpush(0x0066); - bufpush(0x0066); - break; - case 0xFB01: - bufpush(0x0066); - bufpush(0x0069); - break; - case 0xFB02: - bufpush(0x0066); - bufpush(0x006C); - break; - case 0xFB03: - bufpush(0x0066); - bufpush(0x0066); - bufpush(0x0069); - break; - case 0xFB04: - bufpush(0x0066); - bufpush(0x0066); - bufpush(0x006C); - break; - case 0xFB05: - bufpush(0x0073); - bufpush(0x0074); - break; - case 0xFB06: - bufpush(0x0073); - bufpush(0x0074); - break; - case 0xFB13: - bufpush(0x0574); - bufpush(0x0576); - break; - case 0xFB14: - bufpush(0x0574); - bufpush(0x0565); - break; - case 0xFB15: - bufpush(0x0574); - bufpush(0x056B); - break; - case 0xFB16: - bufpush(0x057E); - bufpush(0x0576); - break; - case 0xFB17: - bufpush(0x0574); - bufpush(0x056D); - break; - case 0xFF21: - bufpush(0xFF41); - break; - case 0xFF22: - bufpush(0xFF42); - break; - case 0xFF23: - bufpush(0xFF43); - break; - case 0xFF24: - bufpush(0xFF44); - break; - case 0xFF25: - bufpush(0xFF45); - break; - case 0xFF26: - bufpush(0xFF46); - break; - case 0xFF27: - bufpush(0xFF47); - break; - case 0xFF28: - bufpush(0xFF48); - break; - case 0xFF29: - bufpush(0xFF49); - break; - case 0xFF2A: - bufpush(0xFF4A); - break; - case 0xFF2B: - bufpush(0xFF4B); - break; - case 0xFF2C: - bufpush(0xFF4C); - break; - case 0xFF2D: - bufpush(0xFF4D); - break; - case 0xFF2E: - bufpush(0xFF4E); - break; - case 0xFF2F: - bufpush(0xFF4F); - break; - case 0xFF30: - bufpush(0xFF50); - break; - case 0xFF31: - bufpush(0xFF51); - break; - case 0xFF32: - bufpush(0xFF52); - break; - case 0xFF33: - bufpush(0xFF53); - break; - case 0xFF34: - bufpush(0xFF54); - break; - case 0xFF35: - bufpush(0xFF55); - break; - case 0xFF36: - bufpush(0xFF56); - break; - case 0xFF37: - bufpush(0xFF57); - break; - case 0xFF38: - bufpush(0xFF58); - break; - case 0xFF39: - bufpush(0xFF59); - break; - case 0xFF3A: - bufpush(0xFF5A); - break; - case 0x10400: - bufpush(0x10428); - break; - case 0x10401: - bufpush(0x10429); - break; - case 0x10402: - bufpush(0x1042A); - break; - case 0x10403: - bufpush(0x1042B); - break; - case 0x10404: - bufpush(0x1042C); - break; - case 0x10405: - bufpush(0x1042D); - break; - case 0x10406: - bufpush(0x1042E); - break; - case 0x10407: - bufpush(0x1042F); - break; - case 0x10408: - bufpush(0x10430); - break; - case 0x10409: - bufpush(0x10431); - break; - case 0x1040A: - bufpush(0x10432); - break; - case 0x1040B: - bufpush(0x10433); - break; - case 0x1040C: - bufpush(0x10434); - break; - case 0x1040D: - bufpush(0x10435); - break; - case 0x1040E: - bufpush(0x10436); - break; - case 0x1040F: - bufpush(0x10437); - break; - case 0x10410: - bufpush(0x10438); - break; - case 0x10411: - bufpush(0x10439); - break; - case 0x10412: - bufpush(0x1043A); - break; - case 0x10413: - bufpush(0x1043B); - break; - case 0x10414: - bufpush(0x1043C); - break; - case 0x10415: - bufpush(0x1043D); - break; - case 0x10416: - bufpush(0x1043E); - break; - case 0x10417: - bufpush(0x1043F); - break; - case 0x10418: - bufpush(0x10440); - break; - case 0x10419: - bufpush(0x10441); - break; - case 0x1041A: - bufpush(0x10442); - break; - case 0x1041B: - bufpush(0x10443); - break; - case 0x1041C: - bufpush(0x10444); - break; - case 0x1041D: - bufpush(0x10445); - break; - case 0x1041E: - bufpush(0x10446); - break; - case 0x1041F: - bufpush(0x10447); - break; - case 0x10420: - bufpush(0x10448); - break; - case 0x10421: - bufpush(0x10449); - break; - case 0x10422: - bufpush(0x1044A); - break; - case 0x10423: - bufpush(0x1044B); - break; - case 0x10424: - bufpush(0x1044C); - break; - case 0x10425: - bufpush(0x1044D); - break; - case 0x10426: - bufpush(0x1044E); - break; - case 0x10427: - bufpush(0x1044F); - break; - case 0x104B0: - bufpush(0x104D8); - break; - case 0x104B1: - bufpush(0x104D9); - break; - case 0x104B2: - bufpush(0x104DA); - break; - case 0x104B3: - bufpush(0x104DB); - break; - case 0x104B4: - bufpush(0x104DC); - break; - case 0x104B5: - bufpush(0x104DD); - break; - case 0x104B6: - bufpush(0x104DE); - break; - case 0x104B7: - bufpush(0x104DF); - break; - case 0x104B8: - bufpush(0x104E0); - break; - case 0x104B9: - bufpush(0x104E1); - break; - case 0x104BA: - bufpush(0x104E2); - break; - case 0x104BB: - bufpush(0x104E3); - break; - case 0x104BC: - bufpush(0x104E4); - break; - case 0x104BD: - bufpush(0x104E5); - break; - case 0x104BE: - bufpush(0x104E6); - break; - case 0x104BF: - bufpush(0x104E7); - break; - case 0x104C0: - bufpush(0x104E8); - break; - case 0x104C1: - bufpush(0x104E9); - break; - case 0x104C2: - bufpush(0x104EA); - break; - case 0x104C3: - bufpush(0x104EB); - break; - case 0x104C4: - bufpush(0x104EC); - break; - case 0x104C5: - bufpush(0x104ED); - break; - case 0x104C6: - bufpush(0x104EE); - break; - case 0x104C7: - bufpush(0x104EF); - break; - case 0x104C8: - bufpush(0x104F0); - break; - case 0x104C9: - bufpush(0x104F1); - break; - case 0x104CA: - bufpush(0x104F2); - break; - case 0x104CB: - bufpush(0x104F3); - break; - case 0x104CC: - bufpush(0x104F4); - break; - case 0x104CD: - bufpush(0x104F5); - break; - case 0x104CE: - bufpush(0x104F6); - break; - case 0x104CF: - bufpush(0x104F7); - break; - case 0x104D0: - bufpush(0x104F8); - break; - case 0x104D1: - bufpush(0x104F9); - break; - case 0x104D2: - bufpush(0x104FA); - break; - case 0x104D3: - bufpush(0x104FB); - break; - case 0x10C80: - bufpush(0x10CC0); - break; - case 0x10C81: - bufpush(0x10CC1); - break; - case 0x10C82: - bufpush(0x10CC2); - break; - case 0x10C83: - bufpush(0x10CC3); - break; - case 0x10C84: - bufpush(0x10CC4); - break; - case 0x10C85: - bufpush(0x10CC5); - break; - case 0x10C86: - bufpush(0x10CC6); - break; - case 0x10C87: - bufpush(0x10CC7); - break; - case 0x10C88: - bufpush(0x10CC8); - break; - case 0x10C89: - bufpush(0x10CC9); - break; - case 0x10C8A: - bufpush(0x10CCA); - break; - case 0x10C8B: - bufpush(0x10CCB); - break; - case 0x10C8C: - bufpush(0x10CCC); - break; - case 0x10C8D: - bufpush(0x10CCD); - break; - case 0x10C8E: - bufpush(0x10CCE); - break; - case 0x10C8F: - bufpush(0x10CCF); - break; - case 0x10C90: - bufpush(0x10CD0); - break; - case 0x10C91: - bufpush(0x10CD1); - break; - case 0x10C92: - bufpush(0x10CD2); - break; - case 0x10C93: - bufpush(0x10CD3); - break; - case 0x10C94: - bufpush(0x10CD4); - break; - case 0x10C95: - bufpush(0x10CD5); - break; - case 0x10C96: - bufpush(0x10CD6); - break; - case 0x10C97: - bufpush(0x10CD7); - break; - case 0x10C98: - bufpush(0x10CD8); - break; - case 0x10C99: - bufpush(0x10CD9); - break; - case 0x10C9A: - bufpush(0x10CDA); - break; - case 0x10C9B: - bufpush(0x10CDB); - break; - case 0x10C9C: - bufpush(0x10CDC); - break; - case 0x10C9D: - bufpush(0x10CDD); - break; - case 0x10C9E: - bufpush(0x10CDE); - break; - case 0x10C9F: - bufpush(0x10CDF); - break; - case 0x10CA0: - bufpush(0x10CE0); - break; - case 0x10CA1: - bufpush(0x10CE1); - break; - case 0x10CA2: - bufpush(0x10CE2); - break; - case 0x10CA3: - bufpush(0x10CE3); - break; - case 0x10CA4: - bufpush(0x10CE4); - break; - case 0x10CA5: - bufpush(0x10CE5); - break; - case 0x10CA6: - bufpush(0x10CE6); - break; - case 0x10CA7: - bufpush(0x10CE7); - break; - case 0x10CA8: - bufpush(0x10CE8); - break; - case 0x10CA9: - bufpush(0x10CE9); - break; - case 0x10CAA: - bufpush(0x10CEA); - break; - case 0x10CAB: - bufpush(0x10CEB); - break; - case 0x10CAC: - bufpush(0x10CEC); - break; - case 0x10CAD: - bufpush(0x10CED); - break; - case 0x10CAE: - bufpush(0x10CEE); - break; - case 0x10CAF: - bufpush(0x10CEF); - break; - case 0x10CB0: - bufpush(0x10CF0); - break; - case 0x10CB1: - bufpush(0x10CF1); - break; - case 0x10CB2: - bufpush(0x10CF2); - break; - case 0x118A0: - bufpush(0x118C0); - break; - case 0x118A1: - bufpush(0x118C1); - break; - case 0x118A2: - bufpush(0x118C2); - break; - case 0x118A3: - bufpush(0x118C3); - break; - case 0x118A4: - bufpush(0x118C4); - break; - case 0x118A5: - bufpush(0x118C5); - break; - case 0x118A6: - bufpush(0x118C6); - break; - case 0x118A7: - bufpush(0x118C7); - break; - case 0x118A8: - bufpush(0x118C8); - break; - case 0x118A9: - bufpush(0x118C9); - break; - case 0x118AA: - bufpush(0x118CA); - break; - case 0x118AB: - bufpush(0x118CB); - break; - case 0x118AC: - bufpush(0x118CC); - break; - case 0x118AD: - bufpush(0x118CD); - break; - case 0x118AE: - bufpush(0x118CE); - break; - case 0x118AF: - bufpush(0x118CF); - break; - case 0x118B0: - bufpush(0x118D0); - break; - case 0x118B1: - bufpush(0x118D1); - break; - case 0x118B2: - bufpush(0x118D2); - break; - case 0x118B3: - bufpush(0x118D3); - break; - case 0x118B4: - bufpush(0x118D4); - break; - case 0x118B5: - bufpush(0x118D5); - break; - case 0x118B6: - bufpush(0x118D6); - break; - case 0x118B7: - bufpush(0x118D7); - break; - case 0x118B8: - bufpush(0x118D8); - break; - case 0x118B9: - bufpush(0x118D9); - break; - case 0x118BA: - bufpush(0x118DA); - break; - case 0x118BB: - bufpush(0x118DB); - break; - case 0x118BC: - bufpush(0x118DC); - break; - case 0x118BD: - bufpush(0x118DD); - break; - case 0x118BE: - bufpush(0x118DE); - break; - case 0x118BF: - bufpush(0x118DF); - break; - case 0x1E900: - bufpush(0x1E922); - break; - case 0x1E901: - bufpush(0x1E923); - break; - case 0x1E902: - bufpush(0x1E924); - break; - case 0x1E903: - bufpush(0x1E925); - break; - case 0x1E904: - bufpush(0x1E926); - break; - case 0x1E905: - bufpush(0x1E927); - break; - case 0x1E906: - bufpush(0x1E928); - break; - case 0x1E907: - bufpush(0x1E929); - break; - case 0x1E908: - bufpush(0x1E92A); - break; - case 0x1E909: - bufpush(0x1E92B); - break; - case 0x1E90A: - bufpush(0x1E92C); - break; - case 0x1E90B: - bufpush(0x1E92D); - break; - case 0x1E90C: - bufpush(0x1E92E); - break; - case 0x1E90D: - bufpush(0x1E92F); - break; - case 0x1E90E: - bufpush(0x1E930); - break; - case 0x1E90F: - bufpush(0x1E931); - break; - case 0x1E910: - bufpush(0x1E932); - break; - case 0x1E911: - bufpush(0x1E933); - break; - case 0x1E912: - bufpush(0x1E934); - break; - case 0x1E913: - bufpush(0x1E935); - break; - case 0x1E914: - bufpush(0x1E936); - break; - case 0x1E915: - bufpush(0x1E937); - break; - case 0x1E916: - bufpush(0x1E938); - break; - case 0x1E917: - bufpush(0x1E939); - break; - case 0x1E918: - bufpush(0x1E93A); - break; - case 0x1E919: - bufpush(0x1E93B); - break; - case 0x1E91A: - bufpush(0x1E93C); - break; - case 0x1E91B: - bufpush(0x1E93D); - break; - case 0x1E91C: - bufpush(0x1E93E); - break; - case 0x1E91D: - bufpush(0x1E93F); - break; - case 0x1E91E: - bufpush(0x1E940); - break; - case 0x1E91F: - bufpush(0x1E941); - break; - case 0x1E920: - bufpush(0x1E942); - break; - case 0x1E921: - bufpush(0x1E943); - break; - default: - bufpush(c); - } diff --git a/vendor/core/vendor/cmark-gfm/src/chunk.h b/vendor/core/vendor/cmark-gfm/src/chunk.h deleted file mode 100644 index c411c04a4..000000000 --- a/vendor/core/vendor/cmark-gfm/src/chunk.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef CMARK_CHUNK_H -#define CMARK_CHUNK_H - -#include -#include -#include -#include "cmark-gfm.h" -#include "buffer.h" -#include "cmark_ctype.h" - -#define CMARK_CHUNK_EMPTY \ - { NULL, 0, 0 } - -typedef struct cmark_chunk { - unsigned char *data; - bufsize_t len; - bufsize_t alloc; // also implies a NULL-terminated string -} cmark_chunk; - -static CMARK_INLINE void cmark_chunk_free(cmark_mem *mem, cmark_chunk *c) { - if (c->alloc) - mem->free(c->data); - - c->data = NULL; - c->alloc = 0; - c->len = 0; -} - -static CMARK_INLINE void cmark_chunk_ltrim(cmark_chunk *c) { - assert(!c->alloc); - - while (c->len && cmark_isspace(c->data[0])) { - c->data++; - c->len--; - } -} - -static CMARK_INLINE void cmark_chunk_rtrim(cmark_chunk *c) { - assert(!c->alloc); - - while (c->len > 0) { - if (!cmark_isspace(c->data[c->len - 1])) - break; - - c->len--; - } -} - -static CMARK_INLINE void cmark_chunk_trim(cmark_chunk *c) { - cmark_chunk_ltrim(c); - cmark_chunk_rtrim(c); -} - -static CMARK_INLINE bufsize_t cmark_chunk_strchr(cmark_chunk *ch, int c, - bufsize_t offset) { - const unsigned char *p = - (unsigned char *)memchr(ch->data + offset, c, ch->len - offset); - return p ? (bufsize_t)(p - ch->data) : ch->len; -} - -static CMARK_INLINE const char *cmark_chunk_to_cstr(cmark_mem *mem, - cmark_chunk *c) { - unsigned char *str; - - if (c->alloc) { - return (char *)c->data; - } - str = (unsigned char *)mem->calloc(c->len + 1, 1); - if (c->len > 0) { - memcpy(str, c->data, c->len); - } - str[c->len] = 0; - c->data = str; - c->alloc = 1; - - return (char *)str; -} - -static CMARK_INLINE void cmark_chunk_set_cstr(cmark_mem *mem, cmark_chunk *c, - const char *str) { - unsigned char *old = c->alloc ? c->data : NULL; - if (str == NULL) { - c->len = 0; - c->data = NULL; - c->alloc = 0; - } else { - c->len = (bufsize_t)strlen(str); - c->data = (unsigned char *)mem->calloc(c->len + 1, 1); - c->alloc = 1; - memcpy(c->data, str, c->len + 1); - } - if (old != NULL) { - mem->free(old); - } -} - -static CMARK_INLINE cmark_chunk cmark_chunk_literal(const char *data) { - bufsize_t len = data ? (bufsize_t)strlen(data) : 0; - cmark_chunk c = {(unsigned char *)data, len, 0}; - return c; -} - -static CMARK_INLINE cmark_chunk cmark_chunk_dup(const cmark_chunk *ch, - bufsize_t pos, bufsize_t len) { - cmark_chunk c = {ch->data + pos, len, 0}; - return c; -} - -static CMARK_INLINE cmark_chunk cmark_chunk_buf_detach(cmark_strbuf *buf) { - cmark_chunk c; - - c.len = buf->size; - c.data = cmark_strbuf_detach(buf); - c.alloc = 1; - - 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/vendor/core/vendor/cmark-gfm/src/cmark-gfm-extension_api.h b/vendor/core/vendor/cmark-gfm/src/cmark-gfm-extension_api.h deleted file mode 100644 index bb92a59bf..000000000 --- a/vendor/core/vendor/cmark-gfm/src/cmark-gfm-extension_api.h +++ /dev/null @@ -1,737 +0,0 @@ -#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 position; - 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 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 image); - -/** 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/vendor/core/vendor/cmark-gfm/src/cmark-gfm.h b/vendor/core/vendor/cmark-gfm/src/cmark-gfm.h deleted file mode 100644 index 0544057a5..000000000 --- a/vendor/core/vendor/cmark-gfm/src/cmark-gfm.h +++ /dev/null @@ -1,833 +0,0 @@ -#ifndef CMARK_GFM_H -#define CMARK_GFM_H - -#include -#include -#include "cmark-gfm_export.h" -#include "cmark-gfm_version.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** # NAME - * - * **cmark-gfm** - CommonMark parsing, manipulating, and rendering - */ - -/** # DESCRIPTION - * - * ## Simple Interface - */ - -/** Convert 'text' (assumed to be a UTF-8 encoded string with length - * 'len') from CommonMark Markdown to HTML, returning a null-terminated, - * UTF-8-encoded string. It is the caller's responsibility - * to free the returned buffer. - */ -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 = 0x0000, - - /* Block */ - 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_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_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 -#define CMARK_NODE_HTML CMARK_NODE_HTML_BLOCK -#define CMARK_NODE_INLINE_HTML CMARK_NODE_HTML_INLINE - -typedef enum { - CMARK_NO_LIST, - CMARK_BULLET_LIST, - CMARK_ORDERED_LIST -} cmark_list_type; - -typedef enum { - CMARK_NO_DELIM, - CMARK_PERIOD_DELIM, - CMARK_PAREN_DELIM -} cmark_delim_type; - -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 - */ - -/** Defines the memory allocation functions to be used by CMark - * when parsing and allocating a document tree - */ -typedef struct cmark_mem { - void *(*calloc)(size_t, size_t); - void *(*realloc)(void *, size_t); - 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 - */ - -/** Creates a new node of type 'type'. Note that the node may have - * other required properties, which it is the caller's responsibility - * to assign. - */ -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_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_GFM_EXPORT void cmark_node_free(cmark_node *node); - -/** - * ## Tree Traversal - */ - -/** Returns the next node in the sequence after 'node', or NULL if - * there is none. - */ -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_GFM_EXPORT cmark_node *cmark_node_previous(cmark_node *node); - -/** Returns the parent of 'node', or NULL if there is none. - */ -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_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_GFM_EXPORT cmark_node *cmark_node_last_child(cmark_node *node); - -/** Returns the footnote reference of 'node', or NULL if 'node' doesn't have a - * footnote reference. - */ -CMARK_GFM_EXPORT cmark_node *cmark_node_parent_footnote_def(cmark_node *node); - -/** - * ## Iterator - * - * An iterator will walk through a tree of nodes, starting from a root - * node, returning one node at a time, together with information about - * whether the node is being entered or exited. The iterator will - * first descend to a child node, if there is one. When there is no - * child, the iterator will go to the next sibling. When there is no - * next sibling, the iterator will return to the parent (but with - * a 'cmark_event_type' of `CMARK_EVENT_EXIT`). The iterator will - * return `CMARK_EVENT_DONE` when it reaches the root node again. - * One natural application is an HTML renderer, where an `ENTER` event - * outputs an open tag and an `EXIT` event outputs a close tag. - * An iterator might also be used to transform an AST in some systematic - * way, for example, turning all level-3 headings into regular paragraphs. - * - * void - * usage_example(cmark_node *root) { - * cmark_event_type ev_type; - * cmark_iter *iter = cmark_iter_new(root); - * - * while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { - * cmark_node *cur = cmark_iter_get_node(iter); - * // Do something with `cur` and `ev_type` - * } - * - * cmark_iter_free(iter); - * } - * - * Iterators will never return `EXIT` events for leaf nodes, which are nodes - * of type: - * - * * CMARK_NODE_HTML_BLOCK - * * CMARK_NODE_THEMATIC_BREAK - * * CMARK_NODE_CODE_BLOCK - * * CMARK_NODE_TEXT - * * CMARK_NODE_SOFTBREAK - * * CMARK_NODE_LINEBREAK - * * CMARK_NODE_CODE - * * CMARK_NODE_HTML_INLINE - * - * Nodes must only be modified after an `EXIT` event, or an `ENTER` event for - * leaf nodes. - */ - -typedef enum { - CMARK_EVENT_NONE, - CMARK_EVENT_DONE, - CMARK_EVENT_ENTER, - CMARK_EVENT_EXIT -} cmark_event_type; - -/** Creates a new iterator starting at 'root'. The current node and event - * type are undefined until 'cmark_iter_next' is called for the first time. - * The memory allocated for the iterator should be released using - * 'cmark_iter_free' when it is no longer needed. - */ -CMARK_GFM_EXPORT -cmark_iter *cmark_iter_new(cmark_node *root); - -/** Frees the memory allocated for an iterator. - */ -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_GFM_EXPORT -cmark_event_type cmark_iter_next(cmark_iter *iter); - -/** Returns the current node. - */ -CMARK_GFM_EXPORT -cmark_node *cmark_iter_get_node(cmark_iter *iter); - -/** Returns the current event type. - */ -CMARK_GFM_EXPORT -cmark_event_type cmark_iter_get_event_type(cmark_iter *iter); - -/** Returns the root node. - */ -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_GFM_EXPORT -void cmark_iter_reset(cmark_iter *iter, cmark_node *current, - cmark_event_type event_type); - -/** - * ## Accessors - */ - -/** Returns the user data of '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_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_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_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_GFM_EXPORT const char *cmark_node_get_literal(cmark_node *node); - -/** Sets the string contents of 'node'. Returns 1 on success, - * 0 on failure. - */ -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_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 -#define cmark_node_set_header_level cmark_node_set_heading_level - -/** Sets the heading level of 'node', returning 1 on success and 0 on error. - */ -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_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_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_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_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_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_GFM_EXPORT int cmark_node_set_list_start(cmark_node *node, int start); - -/** Returns 1 if 'node' is a tight list, 0 otherwise. - */ -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_GFM_EXPORT int cmark_node_set_list_tight(cmark_node *node, int tight); - -/** - * Returns item index of 'node'. This is only used when rendering output - * formats such as commonmark, which need to output the index. It is not - * required for formats such as html or latex. - */ -CMARK_GFM_EXPORT int cmark_node_get_item_index(cmark_node *node); - -/** Sets item index of 'node'. Returns 1 on success, 0 on failure. - */ -CMARK_GFM_EXPORT int cmark_node_set_item_index(cmark_node *node, int idx); - -/** Returns the info string from a fenced code block. - */ -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_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_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_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_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_GFM_EXPORT int cmark_node_set_title(cmark_node *node, const char *title); - -/** 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_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_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_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_GFM_EXPORT int cmark_node_set_on_exit(cmark_node *node, const char *on_exit); - -/** Returns the line on which 'node' begins. - */ -CMARK_GFM_EXPORT int cmark_node_get_start_line(cmark_node *node); - -/** Returns the column at which 'node' begins. - */ -CMARK_GFM_EXPORT int cmark_node_get_start_column(cmark_node *node); - -/** Returns the line on which 'node' ends. - */ -CMARK_GFM_EXPORT int cmark_node_get_end_line(cmark_node *node); - -/** Returns the column at which 'node' ends. - */ -CMARK_GFM_EXPORT int cmark_node_get_end_column(cmark_node *node); - -/** - * ## Tree Manipulation - */ - -/** Unlinks a 'node', removing it from the tree, but not freeing its - * memory. (Use 'cmark_node_free' for that.) - */ -CMARK_GFM_EXPORT void cmark_node_unlink(cmark_node *node); - -/** Inserts 'sibling' before 'node'. Returns 1 on success, 0 on failure. - */ -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_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_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_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_GFM_EXPORT int cmark_node_append_child(cmark_node *node, cmark_node *child); - -/** Consolidates adjacent text nodes. - */ -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 - * - * Simple interface: - * - * cmark_node *document = cmark_parse_document("Hello *world*", 13, - * CMARK_OPT_DEFAULT); - * - * Streaming interface: - * - * cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT); - * FILE *fp = fopen("myfile.md", "rb"); - * while ((bytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) { - * cmark_parser_feed(parser, buffer, bytes); - * if (bytes < sizeof(buffer)) { - * break; - * } - * } - * document = cmark_parser_finish(parser); - * cmark_parser_free(parser); - */ - -/** Creates a new parser object. - */ -CMARK_GFM_EXPORT -cmark_parser *cmark_parser_new(int options); - -/** Creates a new parser object with the given memory allocator - */ -CMARK_GFM_EXPORT -cmark_parser *cmark_parser_new_with_mem(int options, cmark_mem *mem); - -/** Frees memory allocated for a parser object. - */ -CMARK_GFM_EXPORT -void cmark_parser_free(cmark_parser *parser); - -/** Feeds a string of length 'len' to 'parser'. - */ -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_GFM_EXPORT -cmark_node *cmark_parser_finish(cmark_parser *parser); - -/** Parse a CommonMark document in 'buffer' of length 'len'. - * Returns 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_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_GFM_EXPORT -cmark_node *cmark_parse_file(FILE *f, int options); - -/** - * ## Rendering - */ - -/** Render a 'node' tree as XML. It is the caller's responsibility - * to free the returned buffer. - */ -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_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_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_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_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 - */ - -/** Default options. - */ -#define CMARK_OPT_DEFAULT 0 - -/** - * ### Options affecting rendering - */ - -/** Include a `data-sourcepos` attribute on all block elements. - */ -#define CMARK_OPT_SOURCEPOS (1 << 1) - -/** Render `softbreak` elements as hard line breaks. - */ -#define CMARK_OPT_HARDBREAKS (1 << 2) - -/** `CMARK_OPT_SAFE` is defined here for API compatibility, - but it no longer has any effect. "Safe" mode is now the default: - set `CMARK_OPT_UNSAFE` to disable it. - */ -#define CMARK_OPT_SAFE (1 << 3) - -/** Render raw HTML and unsafe links (`javascript:`, `vbscript:`, - * `file:`, and `data:`, except for `image/png`, `image/gif`, - * `image/jpeg`, or `image/webp` mime types). By default, - * raw HTML is replaced by a placeholder HTML comment. Unsafe - * links are replaced by empty strings. - */ -#define CMARK_OPT_UNSAFE (1 << 17) - -/** Render `softbreak` elements as spaces. - */ -#define CMARK_OPT_NOBREAKS (1 << 4) - -/** - * ### Options affecting parsing - */ - -/** Legacy option (no effect). - */ -#define CMARK_OPT_NORMALIZE (1 << 8) - -/** Validate UTF-8 in the input before parsing, replacing illegal - * sequences with the replacement character U+FFFD. - */ -#define CMARK_OPT_VALIDATE_UTF8 (1 << 9) - -/** Convert straight quotes to curly, --- to em dashes, -- to en dashes. - */ -#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)
-
-/**
- * ## Version information
- */
-
-/** The library version as integer for runtime checks. Also available as
- * macro CMARK_VERSION for compile time checks.
- *
- * * Bits 16-23 contain the major version.
- * * Bits 8-15 contain the minor version.
- * * Bits 0-7 contain the patchlevel.
- *
- * In hexadecimal format, the number 0x010203 represents version 1.2.3.
- */
-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_GFM_EXPORT
-const char *cmark_version_string(void);
-
-/** # AUTHORS
- *
- * John MacFarlane, Vicent Marti,  Kārlis Gaņģis, Nick Wellnhofer.
- */
-
-#ifndef CMARK_NO_SHORT_NAMES
-#define NODE_DOCUMENT CMARK_NODE_DOCUMENT
-#define NODE_BLOCK_QUOTE CMARK_NODE_BLOCK_QUOTE
-#define NODE_LIST CMARK_NODE_LIST
-#define NODE_ITEM CMARK_NODE_ITEM
-#define NODE_CODE_BLOCK CMARK_NODE_CODE_BLOCK
-#define NODE_HTML_BLOCK CMARK_NODE_HTML_BLOCK
-#define NODE_CUSTOM_BLOCK CMARK_NODE_CUSTOM_BLOCK
-#define NODE_PARAGRAPH CMARK_NODE_PARAGRAPH
-#define NODE_HEADING CMARK_NODE_HEADING
-#define NODE_HEADER CMARK_NODE_HEADER
-#define NODE_THEMATIC_BREAK CMARK_NODE_THEMATIC_BREAK
-#define NODE_HRULE CMARK_NODE_HRULE
-#define NODE_TEXT CMARK_NODE_TEXT
-#define NODE_SOFTBREAK CMARK_NODE_SOFTBREAK
-#define NODE_LINEBREAK CMARK_NODE_LINEBREAK
-#define NODE_CODE CMARK_NODE_CODE
-#define NODE_HTML_INLINE CMARK_NODE_HTML_INLINE
-#define NODE_CUSTOM_INLINE CMARK_NODE_CUSTOM_INLINE
-#define NODE_EMPH CMARK_NODE_EMPH
-#define NODE_STRONG CMARK_NODE_STRONG
-#define NODE_LINK CMARK_NODE_LINK
-#define NODE_IMAGE CMARK_NODE_IMAGE
-#define BULLET_LIST CMARK_BULLET_LIST
-#define ORDERED_LIST CMARK_ORDERED_LIST
-#define PERIOD_DELIM CMARK_PERIOD_DELIM
-#define PAREN_DELIM CMARK_PAREN_DELIM
-#endif
-
-typedef int32_t bufsize_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/vendor/core/vendor/cmark-gfm/src/cmark-gfm_version.h.in b/vendor/core/vendor/cmark-gfm/src/cmark-gfm_version.h.in
deleted file mode 100644
index 0847d0095..000000000
--- a/vendor/core/vendor/cmark-gfm/src/cmark-gfm_version.h.in
+++ /dev/null
@@ -1,7 +0,0 @@
-#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/vendor/core/vendor/cmark-gfm/src/cmark.c b/vendor/core/vendor/cmark-gfm/src/cmark.c
deleted file mode 100644
index 68c40c477..000000000
--- a/vendor/core/vendor/cmark-gfm/src/cmark.c
+++ /dev/null
@@ -1,55 +0,0 @@
-#include 
-#include 
-#include 
-#include "registry.h"
-#include "node.h"
-#include "houdini.h"
-#include "cmark-gfm.h"
-#include "buffer.h"
-
-cmark_node_type CMARK_NODE_LAST_BLOCK = CMARK_NODE_FOOTNOTE_DEFINITION;
-cmark_node_type CMARK_NODE_LAST_INLINE = CMARK_NODE_FOOTNOTE_REFERENCE;
-
-int cmark_version(void) { return CMARK_GFM_VERSION; }
-
-const char *cmark_version_string(void) { return CMARK_GFM_VERSION_STRING; }
-
-static void *xcalloc(size_t nmem, size_t size) {
-  void *ptr = calloc(nmem, size);
-  if (!ptr) {
-    fprintf(stderr, "[cmark] calloc returned null pointer, aborting\n");
-    abort();
-  }
-  return ptr;
-}
-
-static void *xrealloc(void *ptr, size_t size) {
-  void *new_ptr = realloc(ptr, size);
-  if (!new_ptr) {
-    fprintf(stderr, "[cmark] realloc returned null pointer, aborting\n");
-    abort();
-  }
-  return new_ptr;
-}
-
-static void xfree(void *ptr) {
-  free(ptr);
-}
-
-cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR = {xcalloc, xrealloc, xfree};
-
-cmark_mem *cmark_get_default_mem_allocator(void) {
-  return &CMARK_DEFAULT_MEM_ALLOCATOR;
-}
-
-char *cmark_markdown_to_html(const char *text, size_t len, int options) {
-  cmark_node *doc;
-  char *result;
-
-  doc = cmark_parse_document(text, len, options);
-
-  result = cmark_render_html(doc, options, NULL);
-  cmark_node_free(doc);
-
-  return result;
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/cmark_ctype.c b/vendor/core/vendor/cmark-gfm/src/cmark_ctype.c
deleted file mode 100644
index c0c4d5b03..000000000
--- a/vendor/core/vendor/cmark-gfm/src/cmark_ctype.c
+++ /dev/null
@@ -1,44 +0,0 @@
-#include 
-
-#include "cmark_ctype.h"
-
-/** 1 = space, 2 = punct, 3 = digit, 4 = alpha, 0 = other
- */
-static const uint8_t cmark_ctype_class[256] = {
-    /*      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
-    /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0,
-    /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    /* 2 */ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    /* 3 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2,
-    /* 4 */ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    /* 5 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2,
-    /* 6 */ 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    /* 7 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 0,
-    /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    /* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    /* a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    /* b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    /* c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    /* d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    /* e */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    /* f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-/**
- * Returns 1 if c is a "whitespace" character as defined by the spec.
- */
-int cmark_isspace(char c) { return cmark_ctype_class[(uint8_t)c] == 1; }
-
-/**
- * Returns 1 if c is an ascii punctuation character.
- */
-int cmark_ispunct(char c) { return cmark_ctype_class[(uint8_t)c] == 2; }
-
-int cmark_isalnum(char c) {
-  uint8_t result;
-  result = cmark_ctype_class[(uint8_t)c];
-  return (result == 3 || result == 4);
-}
-
-int cmark_isdigit(char c) { return cmark_ctype_class[(uint8_t)c] == 3; }
-
-int cmark_isalpha(char c) { return cmark_ctype_class[(uint8_t)c] == 4; }
diff --git a/vendor/core/vendor/cmark-gfm/src/cmark_ctype.h b/vendor/core/vendor/cmark-gfm/src/cmark_ctype.h
deleted file mode 100644
index 67c1cb037..000000000
--- a/vendor/core/vendor/cmark-gfm/src/cmark_ctype.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef CMARK_CMARK_CTYPE_H
-#define CMARK_CMARK_CTYPE_H
-
-#ifdef __cplusplus
-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
-}
-#endif
-
-#endif
diff --git a/vendor/core/vendor/cmark-gfm/src/commonmark.c b/vendor/core/vendor/cmark-gfm/src/commonmark.c
deleted file mode 100644
index 987b47318..000000000
--- a/vendor/core/vendor/cmark-gfm/src/commonmark.c
+++ /dev/null
@@ -1,514 +0,0 @@
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "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, 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
-#define LISTMARKER_SIZE 20
-
-// Functions to convert cmark_nodes to commonmark strings.
-
-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 =
-      renderer->buffer->size > 0 &&
-      cmark_isdigit(renderer->buffer->ptr[renderer->buffer->size - 1]);
-  char encoded[ENCODED_SIZE];
-
-  needs_escaping =
-      c < 0x80 && escape != LITERAL &&
-      ((escape == NORMAL &&
-        (c < 0x20 ||
-	 c == '*' || c == '_' || c == '[' || c == ']' || c == '#' || c == '<' ||
-         c == '>' || c == '\\' || c == '`' || c == '~' || c == '!' ||
-         (c == '&' && cmark_isalpha(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...
-          !follows_digit) ||
-         (renderer->begin_content && (c == '.' || c == ')') && follows_digit &&
-          (nextc == 0 || cmark_isspace(nextc))))) ||
-       (escape == URL &&
-        (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((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((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 += (int)strlen(encoded);
-    }
-  } else {
-    cmark_render_code_point(renderer, c);
-  }
-}
-
-static int longest_backtick_sequence(const char *code) {
-  int longest = 0;
-  int current = 0;
-  size_t i = 0;
-  size_t code_len = strlen(code);
-  while (i <= code_len) {
-    if (code[i] == '`') {
-      current++;
-    } else {
-      if (current > longest) {
-        longest = current;
-      }
-      current = 0;
-    }
-    i++;
-  }
-  return longest;
-}
-
-static int shortest_unused_backtick_sequence(const char *code) {
-  // note: if the shortest sequence is >= 32, this returns 32
-  // so as not to overflow the bit array.
-  uint32_t used = 1;
-  int current = 0;
-  size_t i = 0;
-  size_t code_len = strlen(code);
-  while (i <= code_len) {
-    if (code[i] == '`') {
-      current++;
-    } else {
-      if (current > 0 && current < 32) {
-        used |= (1U << current);
-      }
-      current = 0;
-    }
-    i++;
-  }
-  // return number of first bit that is 0:
-  i = 0;
-  while (i < 32 && used & 1) {
-    used = used >> 1;
-    i++;
-  }
-  return (int)i;
-}
-
-static bool is_autolink(cmark_node *node) {
-  cmark_chunk *title;
-  cmark_chunk *url;
-  cmark_node *link_text;
-  char *realurl;
-  int realurllen;
-
-  if (node->type != CMARK_NODE_LINK) {
-    return false;
-  }
-
-  url = &node->as.link.url;
-  if (url->len == 0 || scan_scheme(url, 0) == 0) {
-    return false;
-  }
-
-  title = &node->as.link.title;
-  // if it has a title, we can't treat it as an autolink:
-  if (title->len > 0) {
-    return false;
-  }
-
-  link_text = node->first_child;
-  if (link_text == NULL) {
-    return false;
-  }
-  cmark_consolidate_text_nodes(link_text);
-  realurl = (char *)url->data;
-  realurllen = url->len;
-  if (strncmp(realurl, "mailto:", 7) == 0) {
-    realurl += 7;
-    realurllen -= 7;
-  }
-  return (realurllen == link_text->as.literal.len &&
-          strncmp(realurl, (char *)link_text->as.literal.data,
-                  link_text->as.literal.len) == 0);
-}
-
-static int S_render_node(cmark_renderer *renderer, cmark_node *node,
-                         cmark_event_type ev_type, int options) {
-  int list_number;
-  cmark_delim_type list_delim;
-  int numticks;
-  bool extra_spaces;
-  int i;
-  bool entering = (ev_type == CMARK_EVENT_ENTER);
-  const char *info, *code, *title;
-  char fencechar[2] = {'\0', '\0'};
-  size_t info_len, code_len;
-  char listmarker[LISTMARKER_SIZE];
-  const char *emph_delim;
-  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 (entering) {
-    if (node->parent && node->parent->type == CMARK_NODE_ITEM) {
-      renderer->in_tight_list_item = node->parent->parent->as.list.tight;
-    }
-  } else {
-    if (node->type == CMARK_NODE_LIST) {
-      renderer->in_tight_list_item =
-        node->parent &&
-        node->parent->type == CMARK_NODE_ITEM &&
-        node->parent->parent->as.list.tight;
-    }
-  }
-
-  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;
-
-  case CMARK_NODE_BLOCK_QUOTE:
-    if (entering) {
-      LIT("> ");
-      renderer->begin_content = true;
-      cmark_strbuf_puts(renderer->prefix, "> ");
-    } else {
-      cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 2);
-      BLANKLINE();
-    }
-    break;
-
-  case CMARK_NODE_LIST:
-    if (!entering && node->next && (node->next->type == CMARK_NODE_CODE_BLOCK ||
-                                    node->next->type == CMARK_NODE_LIST)) {
-      // this ensures that a following indented code block or list will be
-      // inteprereted correctly.
-      CR();
-      LIT("");
-      BLANKLINE();
-    }
-    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_item_index(node);
-      list_delim = cmark_node_get_list_delim(node->parent);
-      // 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) {
-      for (i = cmark_node_get_heading_level(node); i > 0; i--) {
-        LIT("#");
-      }
-      LIT(" ");
-      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();
-    }
-    info = cmark_node_get_fence_info(node);
-    info_len = strlen(info);
-    fencechar[0] = strchr(info, '`') == NULL ? '`' : '~';
-    code = cmark_node_get_literal(node);
-    code_len = strlen(code);
-    // use indented form if no info, and code doesn't
-    // begin or end with a blank line, and code isn't
-    // first thing in a list item
-    if (info_len == 0 && (code_len > 2 && !cmark_isspace(code[0]) &&
-                          !(cmark_isspace(code[code_len - 1]) &&
-                            cmark_isspace(code[code_len - 2]))) &&
-        !first_in_list_item) {
-      LIT("    ");
-      cmark_strbuf_puts(renderer->prefix, "    ");
-      OUT(cmark_node_get_literal(node), false, LITERAL);
-      cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 4);
-    } else {
-      numticks = longest_backtick_sequence(code) + 1;
-      if (numticks < 3) {
-        numticks = 3;
-      }
-      for (i = 0; i < numticks; i++) {
-        LIT(fencechar);
-      }
-      LIT(" ");
-      OUT(info, false, LITERAL);
-      CR();
-      OUT(cmark_node_get_literal(node), false, LITERAL);
-      CR();
-      for (i = 0; i < numticks; i++) {
-        LIT(fencechar);
-      }
-    }
-    BLANKLINE();
-    break;
-
-  case CMARK_NODE_HTML_BLOCK:
-    BLANKLINE();
-    OUT(cmark_node_get_literal(node), false, LITERAL);
-    BLANKLINE();
-    break;
-
-  case CMARK_NODE_CUSTOM_BLOCK:
-    BLANKLINE();
-    OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
-        false, LITERAL);
-    BLANKLINE();
-    break;
-
-  case CMARK_NODE_THEMATIC_BREAK:
-    BLANKLINE();
-    LIT("-----");
-    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:
-    if (!(CMARK_OPT_HARDBREAKS & options)) {
-      LIT("  ");
-    }
-    CR();
-    break;
-
-  case CMARK_NODE_SOFTBREAK:
-    if (CMARK_OPT_HARDBREAKS & options) {
-      LIT("  ");
-      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:
-    code = cmark_node_get_literal(node);
-    code_len = strlen(code);
-    numticks = shortest_unused_backtick_sequence(code);
-    extra_spaces = code_len == 0 ||
-	    code[0] == '`' || code[code_len - 1] == '`' ||
-	    code[0] == ' ' || code[code_len - 1] == ' ';
-    for (i = 0; i < numticks; i++) {
-      LIT("`");
-    }
-    if (extra_spaces) {
-      LIT(" ");
-    }
-    OUT(cmark_node_get_literal(node), allow_wrap, LITERAL);
-    if (extra_spaces) {
-      LIT(" ");
-    }
-    for (i = 0; i < numticks; i++) {
-      LIT("`");
-    }
-    break;
-
-  case CMARK_NODE_HTML_INLINE:
-    OUT(cmark_node_get_literal(node), false, LITERAL);
-    break;
-
-  case CMARK_NODE_CUSTOM_INLINE:
-    OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
-        false, LITERAL);
-    break;
-
-  case CMARK_NODE_STRONG:
-    if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) {
-      if (entering) {
-        LIT("**");
-      } else {
-        LIT("**");
-      }
-    }
-    break;
-
-  case CMARK_NODE_EMPH:
-    // If we have EMPH(EMPH(x)), we need to use *_x_*
-    // because **x** is STRONG(x):
-    if (node->parent && node->parent->type == CMARK_NODE_EMPH &&
-        node->next == NULL && node->prev == NULL) {
-      emph_delim = "_";
-    } else {
-      emph_delim = "*";
-    }
-    if (entering) {
-      LIT(emph_delim);
-    } else {
-      LIT(emph_delim);
-    }
-    break;
-
-  case CMARK_NODE_LINK:
-    if (is_autolink(node)) {
-      if (entering) {
-        LIT("<");
-        if (strncmp(cmark_node_get_url(node), "mailto:", 7) == 0) {
-          LIT((const char *)cmark_node_get_url(node) + 7);
-        } else {
-          LIT((const char *)cmark_node_get_url(node));
-        }
-        LIT(">");
-        // return signal to skip contents of node...
-        return 0;
-      }
-    } else {
-      if (entering) {
-        LIT("[");
-      } else {
-        LIT("](");
-        OUT(cmark_node_get_url(node), false, URL);
-        title = cmark_node_get_title(node);
-        if (strlen(title) > 0) {
-          LIT(" \"");
-          OUT(title, false, TITLE);
-          LIT("\"");
-        }
-        LIT(")");
-      }
-    }
-    break;
-
-  case CMARK_NODE_IMAGE:
-    if (entering) {
-      LIT("![");
-    } else {
-      LIT("](");
-      OUT(cmark_node_get_url(node), false, URL);
-      title = cmark_node_get_title(node);
-      if (strlen(title) > 0) {
-        OUT(" \"", allow_wrap, LITERAL);
-        OUT(title, false, TITLE);
-        LIT("\"");
-      }
-      LIT(")");
-    }
-    break;
-
-  case CMARK_NODE_FOOTNOTE_REFERENCE:
-    if (entering) {
-      LIT("[^");
-
-      char *footnote_label = renderer->mem->calloc(node->parent_footnote_def->as.literal.len + 1, sizeof(char));
-      memmove(footnote_label, node->parent_footnote_def->as.literal.data, node->parent_footnote_def->as.literal.len);
-
-      OUT(footnote_label, false, LITERAL);
-      renderer->mem->free(footnote_label);
-
-      LIT("]");
-    }
-    break;
-
-  case CMARK_NODE_FOOTNOTE_DEFINITION:
-    if (entering) {
-      renderer->footnote_ix += 1;
-      LIT("[^");
-
-      char *footnote_label = renderer->mem->calloc(node->as.literal.len + 1, sizeof(char));
-      memmove(footnote_label, node->as.literal.data, node->as.literal.len);
-
-      OUT(footnote_label, false, LITERAL);
-      renderer->mem->free(footnote_label);
-
-      LIT("]:\n");
-
-      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_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(mem, root, options, width, outc, S_render_node);
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/config.h.in b/vendor/core/vendor/cmark-gfm/src/config.h.in
deleted file mode 100644
index de1a4dd49..000000000
--- a/vendor/core/vendor/cmark-gfm/src/config.h.in
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef CMARK_CONFIG_H
-#define CMARK_CONFIG_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#cmakedefine HAVE_STDBOOL_H
-
-#ifdef HAVE_STDBOOL_H
-  #include 
-#elif !defined(__cplusplus)
-  typedef char bool;
-#endif
-
-#cmakedefine HAVE___BUILTIN_EXPECT
-
-#cmakedefine HAVE___ATTRIBUTE__
-
-#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/vendor/core/vendor/cmark-gfm/src/entities.inc b/vendor/core/vendor/cmark-gfm/src/entities.inc
deleted file mode 100644
index a7c36e26d..000000000
--- a/vendor/core/vendor/cmark-gfm/src/entities.inc
+++ /dev/null
@@ -1,2138 +0,0 @@
-/* Autogenerated by tools/make_headers_inc.py */
-
-struct cmark_entity_node {
-	unsigned char *entity;
-        unsigned char bytes[8];
-};
-
-#define CMARK_ENTITY_MIN_LENGTH 2
-#define CMARK_ENTITY_MAX_LENGTH 32
-#define CMARK_NUM_ENTITIES 2125
-
-static const struct cmark_entity_node cmark_entities[] = {
-{(unsigned char*)"AElig", {195, 134, 0}},
-{(unsigned char*)"AMP", {38, 0}},
-{(unsigned char*)"Aacute", {195, 129, 0}},
-{(unsigned char*)"Abreve", {196, 130, 0}},
-{(unsigned char*)"Acirc", {195, 130, 0}},
-{(unsigned char*)"Acy", {208, 144, 0}},
-{(unsigned char*)"Afr", {240, 157, 148, 132, 0}},
-{(unsigned char*)"Agrave", {195, 128, 0}},
-{(unsigned char*)"Alpha", {206, 145, 0}},
-{(unsigned char*)"Amacr", {196, 128, 0}},
-{(unsigned char*)"And", {226, 169, 147, 0}},
-{(unsigned char*)"Aogon", {196, 132, 0}},
-{(unsigned char*)"Aopf", {240, 157, 148, 184, 0}},
-{(unsigned char*)"ApplyFunction", {226, 129, 161, 0}},
-{(unsigned char*)"Aring", {195, 133, 0}},
-{(unsigned char*)"Ascr", {240, 157, 146, 156, 0}},
-{(unsigned char*)"Assign", {226, 137, 148, 0}},
-{(unsigned char*)"Atilde", {195, 131, 0}},
-{(unsigned char*)"Auml", {195, 132, 0}},
-{(unsigned char*)"Backslash", {226, 136, 150, 0}},
-{(unsigned char*)"Barv", {226, 171, 167, 0}},
-{(unsigned char*)"Barwed", {226, 140, 134, 0}},
-{(unsigned char*)"Bcy", {208, 145, 0}},
-{(unsigned char*)"Because", {226, 136, 181, 0}},
-{(unsigned char*)"Bernoullis", {226, 132, 172, 0}},
-{(unsigned char*)"Beta", {206, 146, 0}},
-{(unsigned char*)"Bfr", {240, 157, 148, 133, 0}},
-{(unsigned char*)"Bopf", {240, 157, 148, 185, 0}},
-{(unsigned char*)"Breve", {203, 152, 0}},
-{(unsigned char*)"Bscr", {226, 132, 172, 0}},
-{(unsigned char*)"Bumpeq", {226, 137, 142, 0}},
-{(unsigned char*)"CHcy", {208, 167, 0}},
-{(unsigned char*)"COPY", {194, 169, 0}},
-{(unsigned char*)"Cacute", {196, 134, 0}},
-{(unsigned char*)"Cap", {226, 139, 146, 0}},
-{(unsigned char*)"CapitalDifferentialD", {226, 133, 133, 0}},
-{(unsigned char*)"Cayleys", {226, 132, 173, 0}},
-{(unsigned char*)"Ccaron", {196, 140, 0}},
-{(unsigned char*)"Ccedil", {195, 135, 0}},
-{(unsigned char*)"Ccirc", {196, 136, 0}},
-{(unsigned char*)"Cconint", {226, 136, 176, 0}},
-{(unsigned char*)"Cdot", {196, 138, 0}},
-{(unsigned char*)"Cedilla", {194, 184, 0}},
-{(unsigned char*)"CenterDot", {194, 183, 0}},
-{(unsigned char*)"Cfr", {226, 132, 173, 0}},
-{(unsigned char*)"Chi", {206, 167, 0}},
-{(unsigned char*)"CircleDot", {226, 138, 153, 0}},
-{(unsigned char*)"CircleMinus", {226, 138, 150, 0}},
-{(unsigned char*)"CirclePlus", {226, 138, 149, 0}},
-{(unsigned char*)"CircleTimes", {226, 138, 151, 0}},
-{(unsigned char*)"ClockwiseContourIntegral", {226, 136, 178, 0}},
-{(unsigned char*)"CloseCurlyDoubleQuote", {226, 128, 157, 0}},
-{(unsigned char*)"CloseCurlyQuote", {226, 128, 153, 0}},
-{(unsigned char*)"Colon", {226, 136, 183, 0}},
-{(unsigned char*)"Colone", {226, 169, 180, 0}},
-{(unsigned char*)"Congruent", {226, 137, 161, 0}},
-{(unsigned char*)"Conint", {226, 136, 175, 0}},
-{(unsigned char*)"ContourIntegral", {226, 136, 174, 0}},
-{(unsigned char*)"Copf", {226, 132, 130, 0}},
-{(unsigned char*)"Coproduct", {226, 136, 144, 0}},
-{(unsigned char*)"CounterClockwiseContourIntegral", {226, 136, 179, 0}},
-{(unsigned char*)"Cross", {226, 168, 175, 0}},
-{(unsigned char*)"Cscr", {240, 157, 146, 158, 0}},
-{(unsigned char*)"Cup", {226, 139, 147, 0}},
-{(unsigned char*)"CupCap", {226, 137, 141, 0}},
-{(unsigned char*)"DD", {226, 133, 133, 0}},
-{(unsigned char*)"DDotrahd", {226, 164, 145, 0}},
-{(unsigned char*)"DJcy", {208, 130, 0}},
-{(unsigned char*)"DScy", {208, 133, 0}},
-{(unsigned char*)"DZcy", {208, 143, 0}},
-{(unsigned char*)"Dagger", {226, 128, 161, 0}},
-{(unsigned char*)"Darr", {226, 134, 161, 0}},
-{(unsigned char*)"Dashv", {226, 171, 164, 0}},
-{(unsigned char*)"Dcaron", {196, 142, 0}},
-{(unsigned char*)"Dcy", {208, 148, 0}},
-{(unsigned char*)"Del", {226, 136, 135, 0}},
-{(unsigned char*)"Delta", {206, 148, 0}},
-{(unsigned char*)"Dfr", {240, 157, 148, 135, 0}},
-{(unsigned char*)"DiacriticalAcute", {194, 180, 0}},
-{(unsigned char*)"DiacriticalDot", {203, 153, 0}},
-{(unsigned char*)"DiacriticalDoubleAcute", {203, 157, 0}},
-{(unsigned char*)"DiacriticalGrave", {96, 0}},
-{(unsigned char*)"DiacriticalTilde", {203, 156, 0}},
-{(unsigned char*)"Diamond", {226, 139, 132, 0}},
-{(unsigned char*)"DifferentialD", {226, 133, 134, 0}},
-{(unsigned char*)"Dopf", {240, 157, 148, 187, 0}},
-{(unsigned char*)"Dot", {194, 168, 0}},
-{(unsigned char*)"DotDot", {226, 131, 156, 0}},
-{(unsigned char*)"DotEqual", {226, 137, 144, 0}},
-{(unsigned char*)"DoubleContourIntegral", {226, 136, 175, 0}},
-{(unsigned char*)"DoubleDot", {194, 168, 0}},
-{(unsigned char*)"DoubleDownArrow", {226, 135, 147, 0}},
-{(unsigned char*)"DoubleLeftArrow", {226, 135, 144, 0}},
-{(unsigned char*)"DoubleLeftRightArrow", {226, 135, 148, 0}},
-{(unsigned char*)"DoubleLeftTee", {226, 171, 164, 0}},
-{(unsigned char*)"DoubleLongLeftArrow", {226, 159, 184, 0}},
-{(unsigned char*)"DoubleLongLeftRightArrow", {226, 159, 186, 0}},
-{(unsigned char*)"DoubleLongRightArrow", {226, 159, 185, 0}},
-{(unsigned char*)"DoubleRightArrow", {226, 135, 146, 0}},
-{(unsigned char*)"DoubleRightTee", {226, 138, 168, 0}},
-{(unsigned char*)"DoubleUpArrow", {226, 135, 145, 0}},
-{(unsigned char*)"DoubleUpDownArrow", {226, 135, 149, 0}},
-{(unsigned char*)"DoubleVerticalBar", {226, 136, 165, 0}},
-{(unsigned char*)"DownArrow", {226, 134, 147, 0}},
-{(unsigned char*)"DownArrowBar", {226, 164, 147, 0}},
-{(unsigned char*)"DownArrowUpArrow", {226, 135, 181, 0}},
-{(unsigned char*)"DownBreve", {204, 145, 0}},
-{(unsigned char*)"DownLeftRightVector", {226, 165, 144, 0}},
-{(unsigned char*)"DownLeftTeeVector", {226, 165, 158, 0}},
-{(unsigned char*)"DownLeftVector", {226, 134, 189, 0}},
-{(unsigned char*)"DownLeftVectorBar", {226, 165, 150, 0}},
-{(unsigned char*)"DownRightTeeVector", {226, 165, 159, 0}},
-{(unsigned char*)"DownRightVector", {226, 135, 129, 0}},
-{(unsigned char*)"DownRightVectorBar", {226, 165, 151, 0}},
-{(unsigned char*)"DownTee", {226, 138, 164, 0}},
-{(unsigned char*)"DownTeeArrow", {226, 134, 167, 0}},
-{(unsigned char*)"Downarrow", {226, 135, 147, 0}},
-{(unsigned char*)"Dscr", {240, 157, 146, 159, 0}},
-{(unsigned char*)"Dstrok", {196, 144, 0}},
-{(unsigned char*)"ENG", {197, 138, 0}},
-{(unsigned char*)"ETH", {195, 144, 0}},
-{(unsigned char*)"Eacute", {195, 137, 0}},
-{(unsigned char*)"Ecaron", {196, 154, 0}},
-{(unsigned char*)"Ecirc", {195, 138, 0}},
-{(unsigned char*)"Ecy", {208, 173, 0}},
-{(unsigned char*)"Edot", {196, 150, 0}},
-{(unsigned char*)"Efr", {240, 157, 148, 136, 0}},
-{(unsigned char*)"Egrave", {195, 136, 0}},
-{(unsigned char*)"Element", {226, 136, 136, 0}},
-{(unsigned char*)"Emacr", {196, 146, 0}},
-{(unsigned char*)"EmptySmallSquare", {226, 151, 187, 0}},
-{(unsigned char*)"EmptyVerySmallSquare", {226, 150, 171, 0}},
-{(unsigned char*)"Eogon", {196, 152, 0}},
-{(unsigned char*)"Eopf", {240, 157, 148, 188, 0}},
-{(unsigned char*)"Epsilon", {206, 149, 0}},
-{(unsigned char*)"Equal", {226, 169, 181, 0}},
-{(unsigned char*)"EqualTilde", {226, 137, 130, 0}},
-{(unsigned char*)"Equilibrium", {226, 135, 140, 0}},
-{(unsigned char*)"Escr", {226, 132, 176, 0}},
-{(unsigned char*)"Esim", {226, 169, 179, 0}},
-{(unsigned char*)"Eta", {206, 151, 0}},
-{(unsigned char*)"Euml", {195, 139, 0}},
-{(unsigned char*)"Exists", {226, 136, 131, 0}},
-{(unsigned char*)"ExponentialE", {226, 133, 135, 0}},
-{(unsigned char*)"Fcy", {208, 164, 0}},
-{(unsigned char*)"Ffr", {240, 157, 148, 137, 0}},
-{(unsigned char*)"FilledSmallSquare", {226, 151, 188, 0}},
-{(unsigned char*)"FilledVerySmallSquare", {226, 150, 170, 0}},
-{(unsigned char*)"Fopf", {240, 157, 148, 189, 0}},
-{(unsigned char*)"ForAll", {226, 136, 128, 0}},
-{(unsigned char*)"Fouriertrf", {226, 132, 177, 0}},
-{(unsigned char*)"Fscr", {226, 132, 177, 0}},
-{(unsigned char*)"GJcy", {208, 131, 0}},
-{(unsigned char*)"GT", {62, 0}},
-{(unsigned char*)"Gamma", {206, 147, 0}},
-{(unsigned char*)"Gammad", {207, 156, 0}},
-{(unsigned char*)"Gbreve", {196, 158, 0}},
-{(unsigned char*)"Gcedil", {196, 162, 0}},
-{(unsigned char*)"Gcirc", {196, 156, 0}},
-{(unsigned char*)"Gcy", {208, 147, 0}},
-{(unsigned char*)"Gdot", {196, 160, 0}},
-{(unsigned char*)"Gfr", {240, 157, 148, 138, 0}},
-{(unsigned char*)"Gg", {226, 139, 153, 0}},
-{(unsigned char*)"Gopf", {240, 157, 148, 190, 0}},
-{(unsigned char*)"GreaterEqual", {226, 137, 165, 0}},
-{(unsigned char*)"GreaterEqualLess", {226, 139, 155, 0}},
-{(unsigned char*)"GreaterFullEqual", {226, 137, 167, 0}},
-{(unsigned char*)"GreaterGreater", {226, 170, 162, 0}},
-{(unsigned char*)"GreaterLess", {226, 137, 183, 0}},
-{(unsigned char*)"GreaterSlantEqual", {226, 169, 190, 0}},
-{(unsigned char*)"GreaterTilde", {226, 137, 179, 0}},
-{(unsigned char*)"Gscr", {240, 157, 146, 162, 0}},
-{(unsigned char*)"Gt", {226, 137, 171, 0}},
-{(unsigned char*)"HARDcy", {208, 170, 0}},
-{(unsigned char*)"Hacek", {203, 135, 0}},
-{(unsigned char*)"Hat", {94, 0}},
-{(unsigned char*)"Hcirc", {196, 164, 0}},
-{(unsigned char*)"Hfr", {226, 132, 140, 0}},
-{(unsigned char*)"HilbertSpace", {226, 132, 139, 0}},
-{(unsigned char*)"Hopf", {226, 132, 141, 0}},
-{(unsigned char*)"HorizontalLine", {226, 148, 128, 0}},
-{(unsigned char*)"Hscr", {226, 132, 139, 0}},
-{(unsigned char*)"Hstrok", {196, 166, 0}},
-{(unsigned char*)"HumpDownHump", {226, 137, 142, 0}},
-{(unsigned char*)"HumpEqual", {226, 137, 143, 0}},
-{(unsigned char*)"IEcy", {208, 149, 0}},
-{(unsigned char*)"IJlig", {196, 178, 0}},
-{(unsigned char*)"IOcy", {208, 129, 0}},
-{(unsigned char*)"Iacute", {195, 141, 0}},
-{(unsigned char*)"Icirc", {195, 142, 0}},
-{(unsigned char*)"Icy", {208, 152, 0}},
-{(unsigned char*)"Idot", {196, 176, 0}},
-{(unsigned char*)"Ifr", {226, 132, 145, 0}},
-{(unsigned char*)"Igrave", {195, 140, 0}},
-{(unsigned char*)"Im", {226, 132, 145, 0}},
-{(unsigned char*)"Imacr", {196, 170, 0}},
-{(unsigned char*)"ImaginaryI", {226, 133, 136, 0}},
-{(unsigned char*)"Implies", {226, 135, 146, 0}},
-{(unsigned char*)"Int", {226, 136, 172, 0}},
-{(unsigned char*)"Integral", {226, 136, 171, 0}},
-{(unsigned char*)"Intersection", {226, 139, 130, 0}},
-{(unsigned char*)"InvisibleComma", {226, 129, 163, 0}},
-{(unsigned char*)"InvisibleTimes", {226, 129, 162, 0}},
-{(unsigned char*)"Iogon", {196, 174, 0}},
-{(unsigned char*)"Iopf", {240, 157, 149, 128, 0}},
-{(unsigned char*)"Iota", {206, 153, 0}},
-{(unsigned char*)"Iscr", {226, 132, 144, 0}},
-{(unsigned char*)"Itilde", {196, 168, 0}},
-{(unsigned char*)"Iukcy", {208, 134, 0}},
-{(unsigned char*)"Iuml", {195, 143, 0}},
-{(unsigned char*)"Jcirc", {196, 180, 0}},
-{(unsigned char*)"Jcy", {208, 153, 0}},
-{(unsigned char*)"Jfr", {240, 157, 148, 141, 0}},
-{(unsigned char*)"Jopf", {240, 157, 149, 129, 0}},
-{(unsigned char*)"Jscr", {240, 157, 146, 165, 0}},
-{(unsigned char*)"Jsercy", {208, 136, 0}},
-{(unsigned char*)"Jukcy", {208, 132, 0}},
-{(unsigned char*)"KHcy", {208, 165, 0}},
-{(unsigned char*)"KJcy", {208, 140, 0}},
-{(unsigned char*)"Kappa", {206, 154, 0}},
-{(unsigned char*)"Kcedil", {196, 182, 0}},
-{(unsigned char*)"Kcy", {208, 154, 0}},
-{(unsigned char*)"Kfr", {240, 157, 148, 142, 0}},
-{(unsigned char*)"Kopf", {240, 157, 149, 130, 0}},
-{(unsigned char*)"Kscr", {240, 157, 146, 166, 0}},
-{(unsigned char*)"LJcy", {208, 137, 0}},
-{(unsigned char*)"LT", {60, 0}},
-{(unsigned char*)"Lacute", {196, 185, 0}},
-{(unsigned char*)"Lambda", {206, 155, 0}},
-{(unsigned char*)"Lang", {226, 159, 170, 0}},
-{(unsigned char*)"Laplacetrf", {226, 132, 146, 0}},
-{(unsigned char*)"Larr", {226, 134, 158, 0}},
-{(unsigned char*)"Lcaron", {196, 189, 0}},
-{(unsigned char*)"Lcedil", {196, 187, 0}},
-{(unsigned char*)"Lcy", {208, 155, 0}},
-{(unsigned char*)"LeftAngleBracket", {226, 159, 168, 0}},
-{(unsigned char*)"LeftArrow", {226, 134, 144, 0}},
-{(unsigned char*)"LeftArrowBar", {226, 135, 164, 0}},
-{(unsigned char*)"LeftArrowRightArrow", {226, 135, 134, 0}},
-{(unsigned char*)"LeftCeiling", {226, 140, 136, 0}},
-{(unsigned char*)"LeftDoubleBracket", {226, 159, 166, 0}},
-{(unsigned char*)"LeftDownTeeVector", {226, 165, 161, 0}},
-{(unsigned char*)"LeftDownVector", {226, 135, 131, 0}},
-{(unsigned char*)"LeftDownVectorBar", {226, 165, 153, 0}},
-{(unsigned char*)"LeftFloor", {226, 140, 138, 0}},
-{(unsigned char*)"LeftRightArrow", {226, 134, 148, 0}},
-{(unsigned char*)"LeftRightVector", {226, 165, 142, 0}},
-{(unsigned char*)"LeftTee", {226, 138, 163, 0}},
-{(unsigned char*)"LeftTeeArrow", {226, 134, 164, 0}},
-{(unsigned char*)"LeftTeeVector", {226, 165, 154, 0}},
-{(unsigned char*)"LeftTriangle", {226, 138, 178, 0}},
-{(unsigned char*)"LeftTriangleBar", {226, 167, 143, 0}},
-{(unsigned char*)"LeftTriangleEqual", {226, 138, 180, 0}},
-{(unsigned char*)"LeftUpDownVector", {226, 165, 145, 0}},
-{(unsigned char*)"LeftUpTeeVector", {226, 165, 160, 0}},
-{(unsigned char*)"LeftUpVector", {226, 134, 191, 0}},
-{(unsigned char*)"LeftUpVectorBar", {226, 165, 152, 0}},
-{(unsigned char*)"LeftVector", {226, 134, 188, 0}},
-{(unsigned char*)"LeftVectorBar", {226, 165, 146, 0}},
-{(unsigned char*)"Leftarrow", {226, 135, 144, 0}},
-{(unsigned char*)"Leftrightarrow", {226, 135, 148, 0}},
-{(unsigned char*)"LessEqualGreater", {226, 139, 154, 0}},
-{(unsigned char*)"LessFullEqual", {226, 137, 166, 0}},
-{(unsigned char*)"LessGreater", {226, 137, 182, 0}},
-{(unsigned char*)"LessLess", {226, 170, 161, 0}},
-{(unsigned char*)"LessSlantEqual", {226, 169, 189, 0}},
-{(unsigned char*)"LessTilde", {226, 137, 178, 0}},
-{(unsigned char*)"Lfr", {240, 157, 148, 143, 0}},
-{(unsigned char*)"Ll", {226, 139, 152, 0}},
-{(unsigned char*)"Lleftarrow", {226, 135, 154, 0}},
-{(unsigned char*)"Lmidot", {196, 191, 0}},
-{(unsigned char*)"LongLeftArrow", {226, 159, 181, 0}},
-{(unsigned char*)"LongLeftRightArrow", {226, 159, 183, 0}},
-{(unsigned char*)"LongRightArrow", {226, 159, 182, 0}},
-{(unsigned char*)"Longleftarrow", {226, 159, 184, 0}},
-{(unsigned char*)"Longleftrightarrow", {226, 159, 186, 0}},
-{(unsigned char*)"Longrightarrow", {226, 159, 185, 0}},
-{(unsigned char*)"Lopf", {240, 157, 149, 131, 0}},
-{(unsigned char*)"LowerLeftArrow", {226, 134, 153, 0}},
-{(unsigned char*)"LowerRightArrow", {226, 134, 152, 0}},
-{(unsigned char*)"Lscr", {226, 132, 146, 0}},
-{(unsigned char*)"Lsh", {226, 134, 176, 0}},
-{(unsigned char*)"Lstrok", {197, 129, 0}},
-{(unsigned char*)"Lt", {226, 137, 170, 0}},
-{(unsigned char*)"Map", {226, 164, 133, 0}},
-{(unsigned char*)"Mcy", {208, 156, 0}},
-{(unsigned char*)"MediumSpace", {226, 129, 159, 0}},
-{(unsigned char*)"Mellintrf", {226, 132, 179, 0}},
-{(unsigned char*)"Mfr", {240, 157, 148, 144, 0}},
-{(unsigned char*)"MinusPlus", {226, 136, 147, 0}},
-{(unsigned char*)"Mopf", {240, 157, 149, 132, 0}},
-{(unsigned char*)"Mscr", {226, 132, 179, 0}},
-{(unsigned char*)"Mu", {206, 156, 0}},
-{(unsigned char*)"NJcy", {208, 138, 0}},
-{(unsigned char*)"Nacute", {197, 131, 0}},
-{(unsigned char*)"Ncaron", {197, 135, 0}},
-{(unsigned char*)"Ncedil", {197, 133, 0}},
-{(unsigned char*)"Ncy", {208, 157, 0}},
-{(unsigned char*)"NegativeMediumSpace", {226, 128, 139, 0}},
-{(unsigned char*)"NegativeThickSpace", {226, 128, 139, 0}},
-{(unsigned char*)"NegativeThinSpace", {226, 128, 139, 0}},
-{(unsigned char*)"NegativeVeryThinSpace", {226, 128, 139, 0}},
-{(unsigned char*)"NestedGreaterGreater", {226, 137, 171, 0}},
-{(unsigned char*)"NestedLessLess", {226, 137, 170, 0}},
-{(unsigned char*)"NewLine", {10, 0}},
-{(unsigned char*)"Nfr", {240, 157, 148, 145, 0}},
-{(unsigned char*)"NoBreak", {226, 129, 160, 0}},
-{(unsigned char*)"NonBreakingSpace", {194, 160, 0}},
-{(unsigned char*)"Nopf", {226, 132, 149, 0}},
-{(unsigned char*)"Not", {226, 171, 172, 0}},
-{(unsigned char*)"NotCongruent", {226, 137, 162, 0}},
-{(unsigned char*)"NotCupCap", {226, 137, 173, 0}},
-{(unsigned char*)"NotDoubleVerticalBar", {226, 136, 166, 0}},
-{(unsigned char*)"NotElement", {226, 136, 137, 0}},
-{(unsigned char*)"NotEqual", {226, 137, 160, 0}},
-{(unsigned char*)"NotEqualTilde", {226, 137, 130, 204, 184, 0}},
-{(unsigned char*)"NotExists", {226, 136, 132, 0}},
-{(unsigned char*)"NotGreater", {226, 137, 175, 0}},
-{(unsigned char*)"NotGreaterEqual", {226, 137, 177, 0}},
-{(unsigned char*)"NotGreaterFullEqual", {226, 137, 167, 204, 184, 0}},
-{(unsigned char*)"NotGreaterGreater", {226, 137, 171, 204, 184, 0}},
-{(unsigned char*)"NotGreaterLess", {226, 137, 185, 0}},
-{(unsigned char*)"NotGreaterSlantEqual", {226, 169, 190, 204, 184, 0}},
-{(unsigned char*)"NotGreaterTilde", {226, 137, 181, 0}},
-{(unsigned char*)"NotHumpDownHump", {226, 137, 142, 204, 184, 0}},
-{(unsigned char*)"NotHumpEqual", {226, 137, 143, 204, 184, 0}},
-{(unsigned char*)"NotLeftTriangle", {226, 139, 170, 0}},
-{(unsigned char*)"NotLeftTriangleBar", {226, 167, 143, 204, 184, 0}},
-{(unsigned char*)"NotLeftTriangleEqual", {226, 139, 172, 0}},
-{(unsigned char*)"NotLess", {226, 137, 174, 0}},
-{(unsigned char*)"NotLessEqual", {226, 137, 176, 0}},
-{(unsigned char*)"NotLessGreater", {226, 137, 184, 0}},
-{(unsigned char*)"NotLessLess", {226, 137, 170, 204, 184, 0}},
-{(unsigned char*)"NotLessSlantEqual", {226, 169, 189, 204, 184, 0}},
-{(unsigned char*)"NotLessTilde", {226, 137, 180, 0}},
-{(unsigned char*)"NotNestedGreaterGreater", {226, 170, 162, 204, 184, 0}},
-{(unsigned char*)"NotNestedLessLess", {226, 170, 161, 204, 184, 0}},
-{(unsigned char*)"NotPrecedes", {226, 138, 128, 0}},
-{(unsigned char*)"NotPrecedesEqual", {226, 170, 175, 204, 184, 0}},
-{(unsigned char*)"NotPrecedesSlantEqual", {226, 139, 160, 0}},
-{(unsigned char*)"NotReverseElement", {226, 136, 140, 0}},
-{(unsigned char*)"NotRightTriangle", {226, 139, 171, 0}},
-{(unsigned char*)"NotRightTriangleBar", {226, 167, 144, 204, 184, 0}},
-{(unsigned char*)"NotRightTriangleEqual", {226, 139, 173, 0}},
-{(unsigned char*)"NotSquareSubset", {226, 138, 143, 204, 184, 0}},
-{(unsigned char*)"NotSquareSubsetEqual", {226, 139, 162, 0}},
-{(unsigned char*)"NotSquareSuperset", {226, 138, 144, 204, 184, 0}},
-{(unsigned char*)"NotSquareSupersetEqual", {226, 139, 163, 0}},
-{(unsigned char*)"NotSubset", {226, 138, 130, 226, 131, 146, 0}},
-{(unsigned char*)"NotSubsetEqual", {226, 138, 136, 0}},
-{(unsigned char*)"NotSucceeds", {226, 138, 129, 0}},
-{(unsigned char*)"NotSucceedsEqual", {226, 170, 176, 204, 184, 0}},
-{(unsigned char*)"NotSucceedsSlantEqual", {226, 139, 161, 0}},
-{(unsigned char*)"NotSucceedsTilde", {226, 137, 191, 204, 184, 0}},
-{(unsigned char*)"NotSuperset", {226, 138, 131, 226, 131, 146, 0}},
-{(unsigned char*)"NotSupersetEqual", {226, 138, 137, 0}},
-{(unsigned char*)"NotTilde", {226, 137, 129, 0}},
-{(unsigned char*)"NotTildeEqual", {226, 137, 132, 0}},
-{(unsigned char*)"NotTildeFullEqual", {226, 137, 135, 0}},
-{(unsigned char*)"NotTildeTilde", {226, 137, 137, 0}},
-{(unsigned char*)"NotVerticalBar", {226, 136, 164, 0}},
-{(unsigned char*)"Nscr", {240, 157, 146, 169, 0}},
-{(unsigned char*)"Ntilde", {195, 145, 0}},
-{(unsigned char*)"Nu", {206, 157, 0}},
-{(unsigned char*)"OElig", {197, 146, 0}},
-{(unsigned char*)"Oacute", {195, 147, 0}},
-{(unsigned char*)"Ocirc", {195, 148, 0}},
-{(unsigned char*)"Ocy", {208, 158, 0}},
-{(unsigned char*)"Odblac", {197, 144, 0}},
-{(unsigned char*)"Ofr", {240, 157, 148, 146, 0}},
-{(unsigned char*)"Ograve", {195, 146, 0}},
-{(unsigned char*)"Omacr", {197, 140, 0}},
-{(unsigned char*)"Omega", {206, 169, 0}},
-{(unsigned char*)"Omicron", {206, 159, 0}},
-{(unsigned char*)"Oopf", {240, 157, 149, 134, 0}},
-{(unsigned char*)"OpenCurlyDoubleQuote", {226, 128, 156, 0}},
-{(unsigned char*)"OpenCurlyQuote", {226, 128, 152, 0}},
-{(unsigned char*)"Or", {226, 169, 148, 0}},
-{(unsigned char*)"Oscr", {240, 157, 146, 170, 0}},
-{(unsigned char*)"Oslash", {195, 152, 0}},
-{(unsigned char*)"Otilde", {195, 149, 0}},
-{(unsigned char*)"Otimes", {226, 168, 183, 0}},
-{(unsigned char*)"Ouml", {195, 150, 0}},
-{(unsigned char*)"OverBar", {226, 128, 190, 0}},
-{(unsigned char*)"OverBrace", {226, 143, 158, 0}},
-{(unsigned char*)"OverBracket", {226, 142, 180, 0}},
-{(unsigned char*)"OverParenthesis", {226, 143, 156, 0}},
-{(unsigned char*)"PartialD", {226, 136, 130, 0}},
-{(unsigned char*)"Pcy", {208, 159, 0}},
-{(unsigned char*)"Pfr", {240, 157, 148, 147, 0}},
-{(unsigned char*)"Phi", {206, 166, 0}},
-{(unsigned char*)"Pi", {206, 160, 0}},
-{(unsigned char*)"PlusMinus", {194, 177, 0}},
-{(unsigned char*)"Poincareplane", {226, 132, 140, 0}},
-{(unsigned char*)"Popf", {226, 132, 153, 0}},
-{(unsigned char*)"Pr", {226, 170, 187, 0}},
-{(unsigned char*)"Precedes", {226, 137, 186, 0}},
-{(unsigned char*)"PrecedesEqual", {226, 170, 175, 0}},
-{(unsigned char*)"PrecedesSlantEqual", {226, 137, 188, 0}},
-{(unsigned char*)"PrecedesTilde", {226, 137, 190, 0}},
-{(unsigned char*)"Prime", {226, 128, 179, 0}},
-{(unsigned char*)"Product", {226, 136, 143, 0}},
-{(unsigned char*)"Proportion", {226, 136, 183, 0}},
-{(unsigned char*)"Proportional", {226, 136, 157, 0}},
-{(unsigned char*)"Pscr", {240, 157, 146, 171, 0}},
-{(unsigned char*)"Psi", {206, 168, 0}},
-{(unsigned char*)"QUOT", {34, 0}},
-{(unsigned char*)"Qfr", {240, 157, 148, 148, 0}},
-{(unsigned char*)"Qopf", {226, 132, 154, 0}},
-{(unsigned char*)"Qscr", {240, 157, 146, 172, 0}},
-{(unsigned char*)"RBarr", {226, 164, 144, 0}},
-{(unsigned char*)"REG", {194, 174, 0}},
-{(unsigned char*)"Racute", {197, 148, 0}},
-{(unsigned char*)"Rang", {226, 159, 171, 0}},
-{(unsigned char*)"Rarr", {226, 134, 160, 0}},
-{(unsigned char*)"Rarrtl", {226, 164, 150, 0}},
-{(unsigned char*)"Rcaron", {197, 152, 0}},
-{(unsigned char*)"Rcedil", {197, 150, 0}},
-{(unsigned char*)"Rcy", {208, 160, 0}},
-{(unsigned char*)"Re", {226, 132, 156, 0}},
-{(unsigned char*)"ReverseElement", {226, 136, 139, 0}},
-{(unsigned char*)"ReverseEquilibrium", {226, 135, 139, 0}},
-{(unsigned char*)"ReverseUpEquilibrium", {226, 165, 175, 0}},
-{(unsigned char*)"Rfr", {226, 132, 156, 0}},
-{(unsigned char*)"Rho", {206, 161, 0}},
-{(unsigned char*)"RightAngleBracket", {226, 159, 169, 0}},
-{(unsigned char*)"RightArrow", {226, 134, 146, 0}},
-{(unsigned char*)"RightArrowBar", {226, 135, 165, 0}},
-{(unsigned char*)"RightArrowLeftArrow", {226, 135, 132, 0}},
-{(unsigned char*)"RightCeiling", {226, 140, 137, 0}},
-{(unsigned char*)"RightDoubleBracket", {226, 159, 167, 0}},
-{(unsigned char*)"RightDownTeeVector", {226, 165, 157, 0}},
-{(unsigned char*)"RightDownVector", {226, 135, 130, 0}},
-{(unsigned char*)"RightDownVectorBar", {226, 165, 149, 0}},
-{(unsigned char*)"RightFloor", {226, 140, 139, 0}},
-{(unsigned char*)"RightTee", {226, 138, 162, 0}},
-{(unsigned char*)"RightTeeArrow", {226, 134, 166, 0}},
-{(unsigned char*)"RightTeeVector", {226, 165, 155, 0}},
-{(unsigned char*)"RightTriangle", {226, 138, 179, 0}},
-{(unsigned char*)"RightTriangleBar", {226, 167, 144, 0}},
-{(unsigned char*)"RightTriangleEqual", {226, 138, 181, 0}},
-{(unsigned char*)"RightUpDownVector", {226, 165, 143, 0}},
-{(unsigned char*)"RightUpTeeVector", {226, 165, 156, 0}},
-{(unsigned char*)"RightUpVector", {226, 134, 190, 0}},
-{(unsigned char*)"RightUpVectorBar", {226, 165, 148, 0}},
-{(unsigned char*)"RightVector", {226, 135, 128, 0}},
-{(unsigned char*)"RightVectorBar", {226, 165, 147, 0}},
-{(unsigned char*)"Rightarrow", {226, 135, 146, 0}},
-{(unsigned char*)"Ropf", {226, 132, 157, 0}},
-{(unsigned char*)"RoundImplies", {226, 165, 176, 0}},
-{(unsigned char*)"Rrightarrow", {226, 135, 155, 0}},
-{(unsigned char*)"Rscr", {226, 132, 155, 0}},
-{(unsigned char*)"Rsh", {226, 134, 177, 0}},
-{(unsigned char*)"RuleDelayed", {226, 167, 180, 0}},
-{(unsigned char*)"SHCHcy", {208, 169, 0}},
-{(unsigned char*)"SHcy", {208, 168, 0}},
-{(unsigned char*)"SOFTcy", {208, 172, 0}},
-{(unsigned char*)"Sacute", {197, 154, 0}},
-{(unsigned char*)"Sc", {226, 170, 188, 0}},
-{(unsigned char*)"Scaron", {197, 160, 0}},
-{(unsigned char*)"Scedil", {197, 158, 0}},
-{(unsigned char*)"Scirc", {197, 156, 0}},
-{(unsigned char*)"Scy", {208, 161, 0}},
-{(unsigned char*)"Sfr", {240, 157, 148, 150, 0}},
-{(unsigned char*)"ShortDownArrow", {226, 134, 147, 0}},
-{(unsigned char*)"ShortLeftArrow", {226, 134, 144, 0}},
-{(unsigned char*)"ShortRightArrow", {226, 134, 146, 0}},
-{(unsigned char*)"ShortUpArrow", {226, 134, 145, 0}},
-{(unsigned char*)"Sigma", {206, 163, 0}},
-{(unsigned char*)"SmallCircle", {226, 136, 152, 0}},
-{(unsigned char*)"Sopf", {240, 157, 149, 138, 0}},
-{(unsigned char*)"Sqrt", {226, 136, 154, 0}},
-{(unsigned char*)"Square", {226, 150, 161, 0}},
-{(unsigned char*)"SquareIntersection", {226, 138, 147, 0}},
-{(unsigned char*)"SquareSubset", {226, 138, 143, 0}},
-{(unsigned char*)"SquareSubsetEqual", {226, 138, 145, 0}},
-{(unsigned char*)"SquareSuperset", {226, 138, 144, 0}},
-{(unsigned char*)"SquareSupersetEqual", {226, 138, 146, 0}},
-{(unsigned char*)"SquareUnion", {226, 138, 148, 0}},
-{(unsigned char*)"Sscr", {240, 157, 146, 174, 0}},
-{(unsigned char*)"Star", {226, 139, 134, 0}},
-{(unsigned char*)"Sub", {226, 139, 144, 0}},
-{(unsigned char*)"Subset", {226, 139, 144, 0}},
-{(unsigned char*)"SubsetEqual", {226, 138, 134, 0}},
-{(unsigned char*)"Succeeds", {226, 137, 187, 0}},
-{(unsigned char*)"SucceedsEqual", {226, 170, 176, 0}},
-{(unsigned char*)"SucceedsSlantEqual", {226, 137, 189, 0}},
-{(unsigned char*)"SucceedsTilde", {226, 137, 191, 0}},
-{(unsigned char*)"SuchThat", {226, 136, 139, 0}},
-{(unsigned char*)"Sum", {226, 136, 145, 0}},
-{(unsigned char*)"Sup", {226, 139, 145, 0}},
-{(unsigned char*)"Superset", {226, 138, 131, 0}},
-{(unsigned char*)"SupersetEqual", {226, 138, 135, 0}},
-{(unsigned char*)"Supset", {226, 139, 145, 0}},
-{(unsigned char*)"THORN", {195, 158, 0}},
-{(unsigned char*)"TRADE", {226, 132, 162, 0}},
-{(unsigned char*)"TSHcy", {208, 139, 0}},
-{(unsigned char*)"TScy", {208, 166, 0}},
-{(unsigned char*)"Tab", {9, 0}},
-{(unsigned char*)"Tau", {206, 164, 0}},
-{(unsigned char*)"Tcaron", {197, 164, 0}},
-{(unsigned char*)"Tcedil", {197, 162, 0}},
-{(unsigned char*)"Tcy", {208, 162, 0}},
-{(unsigned char*)"Tfr", {240, 157, 148, 151, 0}},
-{(unsigned char*)"Therefore", {226, 136, 180, 0}},
-{(unsigned char*)"Theta", {206, 152, 0}},
-{(unsigned char*)"ThickSpace", {226, 129, 159, 226, 128, 138, 0}},
-{(unsigned char*)"ThinSpace", {226, 128, 137, 0}},
-{(unsigned char*)"Tilde", {226, 136, 188, 0}},
-{(unsigned char*)"TildeEqual", {226, 137, 131, 0}},
-{(unsigned char*)"TildeFullEqual", {226, 137, 133, 0}},
-{(unsigned char*)"TildeTilde", {226, 137, 136, 0}},
-{(unsigned char*)"Topf", {240, 157, 149, 139, 0}},
-{(unsigned char*)"TripleDot", {226, 131, 155, 0}},
-{(unsigned char*)"Tscr", {240, 157, 146, 175, 0}},
-{(unsigned char*)"Tstrok", {197, 166, 0}},
-{(unsigned char*)"Uacute", {195, 154, 0}},
-{(unsigned char*)"Uarr", {226, 134, 159, 0}},
-{(unsigned char*)"Uarrocir", {226, 165, 137, 0}},
-{(unsigned char*)"Ubrcy", {208, 142, 0}},
-{(unsigned char*)"Ubreve", {197, 172, 0}},
-{(unsigned char*)"Ucirc", {195, 155, 0}},
-{(unsigned char*)"Ucy", {208, 163, 0}},
-{(unsigned char*)"Udblac", {197, 176, 0}},
-{(unsigned char*)"Ufr", {240, 157, 148, 152, 0}},
-{(unsigned char*)"Ugrave", {195, 153, 0}},
-{(unsigned char*)"Umacr", {197, 170, 0}},
-{(unsigned char*)"UnderBar", {95, 0}},
-{(unsigned char*)"UnderBrace", {226, 143, 159, 0}},
-{(unsigned char*)"UnderBracket", {226, 142, 181, 0}},
-{(unsigned char*)"UnderParenthesis", {226, 143, 157, 0}},
-{(unsigned char*)"Union", {226, 139, 131, 0}},
-{(unsigned char*)"UnionPlus", {226, 138, 142, 0}},
-{(unsigned char*)"Uogon", {197, 178, 0}},
-{(unsigned char*)"Uopf", {240, 157, 149, 140, 0}},
-{(unsigned char*)"UpArrow", {226, 134, 145, 0}},
-{(unsigned char*)"UpArrowBar", {226, 164, 146, 0}},
-{(unsigned char*)"UpArrowDownArrow", {226, 135, 133, 0}},
-{(unsigned char*)"UpDownArrow", {226, 134, 149, 0}},
-{(unsigned char*)"UpEquilibrium", {226, 165, 174, 0}},
-{(unsigned char*)"UpTee", {226, 138, 165, 0}},
-{(unsigned char*)"UpTeeArrow", {226, 134, 165, 0}},
-{(unsigned char*)"Uparrow", {226, 135, 145, 0}},
-{(unsigned char*)"Updownarrow", {226, 135, 149, 0}},
-{(unsigned char*)"UpperLeftArrow", {226, 134, 150, 0}},
-{(unsigned char*)"UpperRightArrow", {226, 134, 151, 0}},
-{(unsigned char*)"Upsi", {207, 146, 0}},
-{(unsigned char*)"Upsilon", {206, 165, 0}},
-{(unsigned char*)"Uring", {197, 174, 0}},
-{(unsigned char*)"Uscr", {240, 157, 146, 176, 0}},
-{(unsigned char*)"Utilde", {197, 168, 0}},
-{(unsigned char*)"Uuml", {195, 156, 0}},
-{(unsigned char*)"VDash", {226, 138, 171, 0}},
-{(unsigned char*)"Vbar", {226, 171, 171, 0}},
-{(unsigned char*)"Vcy", {208, 146, 0}},
-{(unsigned char*)"Vdash", {226, 138, 169, 0}},
-{(unsigned char*)"Vdashl", {226, 171, 166, 0}},
-{(unsigned char*)"Vee", {226, 139, 129, 0}},
-{(unsigned char*)"Verbar", {226, 128, 150, 0}},
-{(unsigned char*)"Vert", {226, 128, 150, 0}},
-{(unsigned char*)"VerticalBar", {226, 136, 163, 0}},
-{(unsigned char*)"VerticalLine", {124, 0}},
-{(unsigned char*)"VerticalSeparator", {226, 157, 152, 0}},
-{(unsigned char*)"VerticalTilde", {226, 137, 128, 0}},
-{(unsigned char*)"VeryThinSpace", {226, 128, 138, 0}},
-{(unsigned char*)"Vfr", {240, 157, 148, 153, 0}},
-{(unsigned char*)"Vopf", {240, 157, 149, 141, 0}},
-{(unsigned char*)"Vscr", {240, 157, 146, 177, 0}},
-{(unsigned char*)"Vvdash", {226, 138, 170, 0}},
-{(unsigned char*)"Wcirc", {197, 180, 0}},
-{(unsigned char*)"Wedge", {226, 139, 128, 0}},
-{(unsigned char*)"Wfr", {240, 157, 148, 154, 0}},
-{(unsigned char*)"Wopf", {240, 157, 149, 142, 0}},
-{(unsigned char*)"Wscr", {240, 157, 146, 178, 0}},
-{(unsigned char*)"Xfr", {240, 157, 148, 155, 0}},
-{(unsigned char*)"Xi", {206, 158, 0}},
-{(unsigned char*)"Xopf", {240, 157, 149, 143, 0}},
-{(unsigned char*)"Xscr", {240, 157, 146, 179, 0}},
-{(unsigned char*)"YAcy", {208, 175, 0}},
-{(unsigned char*)"YIcy", {208, 135, 0}},
-{(unsigned char*)"YUcy", {208, 174, 0}},
-{(unsigned char*)"Yacute", {195, 157, 0}},
-{(unsigned char*)"Ycirc", {197, 182, 0}},
-{(unsigned char*)"Ycy", {208, 171, 0}},
-{(unsigned char*)"Yfr", {240, 157, 148, 156, 0}},
-{(unsigned char*)"Yopf", {240, 157, 149, 144, 0}},
-{(unsigned char*)"Yscr", {240, 157, 146, 180, 0}},
-{(unsigned char*)"Yuml", {197, 184, 0}},
-{(unsigned char*)"ZHcy", {208, 150, 0}},
-{(unsigned char*)"Zacute", {197, 185, 0}},
-{(unsigned char*)"Zcaron", {197, 189, 0}},
-{(unsigned char*)"Zcy", {208, 151, 0}},
-{(unsigned char*)"Zdot", {197, 187, 0}},
-{(unsigned char*)"ZeroWidthSpace", {226, 128, 139, 0}},
-{(unsigned char*)"Zeta", {206, 150, 0}},
-{(unsigned char*)"Zfr", {226, 132, 168, 0}},
-{(unsigned char*)"Zopf", {226, 132, 164, 0}},
-{(unsigned char*)"Zscr", {240, 157, 146, 181, 0}},
-{(unsigned char*)"aacute", {195, 161, 0}},
-{(unsigned char*)"abreve", {196, 131, 0}},
-{(unsigned char*)"ac", {226, 136, 190, 0}},
-{(unsigned char*)"acE", {226, 136, 190, 204, 179, 0}},
-{(unsigned char*)"acd", {226, 136, 191, 0}},
-{(unsigned char*)"acirc", {195, 162, 0}},
-{(unsigned char*)"acute", {194, 180, 0}},
-{(unsigned char*)"acy", {208, 176, 0}},
-{(unsigned char*)"aelig", {195, 166, 0}},
-{(unsigned char*)"af", {226, 129, 161, 0}},
-{(unsigned char*)"afr", {240, 157, 148, 158, 0}},
-{(unsigned char*)"agrave", {195, 160, 0}},
-{(unsigned char*)"alefsym", {226, 132, 181, 0}},
-{(unsigned char*)"aleph", {226, 132, 181, 0}},
-{(unsigned char*)"alpha", {206, 177, 0}},
-{(unsigned char*)"amacr", {196, 129, 0}},
-{(unsigned char*)"amalg", {226, 168, 191, 0}},
-{(unsigned char*)"amp", {38, 0}},
-{(unsigned char*)"and", {226, 136, 167, 0}},
-{(unsigned char*)"andand", {226, 169, 149, 0}},
-{(unsigned char*)"andd", {226, 169, 156, 0}},
-{(unsigned char*)"andslope", {226, 169, 152, 0}},
-{(unsigned char*)"andv", {226, 169, 154, 0}},
-{(unsigned char*)"ang", {226, 136, 160, 0}},
-{(unsigned char*)"ange", {226, 166, 164, 0}},
-{(unsigned char*)"angle", {226, 136, 160, 0}},
-{(unsigned char*)"angmsd", {226, 136, 161, 0}},
-{(unsigned char*)"angmsdaa", {226, 166, 168, 0}},
-{(unsigned char*)"angmsdab", {226, 166, 169, 0}},
-{(unsigned char*)"angmsdac", {226, 166, 170, 0}},
-{(unsigned char*)"angmsdad", {226, 166, 171, 0}},
-{(unsigned char*)"angmsdae", {226, 166, 172, 0}},
-{(unsigned char*)"angmsdaf", {226, 166, 173, 0}},
-{(unsigned char*)"angmsdag", {226, 166, 174, 0}},
-{(unsigned char*)"angmsdah", {226, 166, 175, 0}},
-{(unsigned char*)"angrt", {226, 136, 159, 0}},
-{(unsigned char*)"angrtvb", {226, 138, 190, 0}},
-{(unsigned char*)"angrtvbd", {226, 166, 157, 0}},
-{(unsigned char*)"angsph", {226, 136, 162, 0}},
-{(unsigned char*)"angst", {195, 133, 0}},
-{(unsigned char*)"angzarr", {226, 141, 188, 0}},
-{(unsigned char*)"aogon", {196, 133, 0}},
-{(unsigned char*)"aopf", {240, 157, 149, 146, 0}},
-{(unsigned char*)"ap", {226, 137, 136, 0}},
-{(unsigned char*)"apE", {226, 169, 176, 0}},
-{(unsigned char*)"apacir", {226, 169, 175, 0}},
-{(unsigned char*)"ape", {226, 137, 138, 0}},
-{(unsigned char*)"apid", {226, 137, 139, 0}},
-{(unsigned char*)"apos", {39, 0}},
-{(unsigned char*)"approx", {226, 137, 136, 0}},
-{(unsigned char*)"approxeq", {226, 137, 138, 0}},
-{(unsigned char*)"aring", {195, 165, 0}},
-{(unsigned char*)"ascr", {240, 157, 146, 182, 0}},
-{(unsigned char*)"ast", {42, 0}},
-{(unsigned char*)"asymp", {226, 137, 136, 0}},
-{(unsigned char*)"asympeq", {226, 137, 141, 0}},
-{(unsigned char*)"atilde", {195, 163, 0}},
-{(unsigned char*)"auml", {195, 164, 0}},
-{(unsigned char*)"awconint", {226, 136, 179, 0}},
-{(unsigned char*)"awint", {226, 168, 145, 0}},
-{(unsigned char*)"bNot", {226, 171, 173, 0}},
-{(unsigned char*)"backcong", {226, 137, 140, 0}},
-{(unsigned char*)"backepsilon", {207, 182, 0}},
-{(unsigned char*)"backprime", {226, 128, 181, 0}},
-{(unsigned char*)"backsim", {226, 136, 189, 0}},
-{(unsigned char*)"backsimeq", {226, 139, 141, 0}},
-{(unsigned char*)"barvee", {226, 138, 189, 0}},
-{(unsigned char*)"barwed", {226, 140, 133, 0}},
-{(unsigned char*)"barwedge", {226, 140, 133, 0}},
-{(unsigned char*)"bbrk", {226, 142, 181, 0}},
-{(unsigned char*)"bbrktbrk", {226, 142, 182, 0}},
-{(unsigned char*)"bcong", {226, 137, 140, 0}},
-{(unsigned char*)"bcy", {208, 177, 0}},
-{(unsigned char*)"bdquo", {226, 128, 158, 0}},
-{(unsigned char*)"becaus", {226, 136, 181, 0}},
-{(unsigned char*)"because", {226, 136, 181, 0}},
-{(unsigned char*)"bemptyv", {226, 166, 176, 0}},
-{(unsigned char*)"bepsi", {207, 182, 0}},
-{(unsigned char*)"bernou", {226, 132, 172, 0}},
-{(unsigned char*)"beta", {206, 178, 0}},
-{(unsigned char*)"beth", {226, 132, 182, 0}},
-{(unsigned char*)"between", {226, 137, 172, 0}},
-{(unsigned char*)"bfr", {240, 157, 148, 159, 0}},
-{(unsigned char*)"bigcap", {226, 139, 130, 0}},
-{(unsigned char*)"bigcirc", {226, 151, 175, 0}},
-{(unsigned char*)"bigcup", {226, 139, 131, 0}},
-{(unsigned char*)"bigodot", {226, 168, 128, 0}},
-{(unsigned char*)"bigoplus", {226, 168, 129, 0}},
-{(unsigned char*)"bigotimes", {226, 168, 130, 0}},
-{(unsigned char*)"bigsqcup", {226, 168, 134, 0}},
-{(unsigned char*)"bigstar", {226, 152, 133, 0}},
-{(unsigned char*)"bigtriangledown", {226, 150, 189, 0}},
-{(unsigned char*)"bigtriangleup", {226, 150, 179, 0}},
-{(unsigned char*)"biguplus", {226, 168, 132, 0}},
-{(unsigned char*)"bigvee", {226, 139, 129, 0}},
-{(unsigned char*)"bigwedge", {226, 139, 128, 0}},
-{(unsigned char*)"bkarow", {226, 164, 141, 0}},
-{(unsigned char*)"blacklozenge", {226, 167, 171, 0}},
-{(unsigned char*)"blacksquare", {226, 150, 170, 0}},
-{(unsigned char*)"blacktriangle", {226, 150, 180, 0}},
-{(unsigned char*)"blacktriangledown", {226, 150, 190, 0}},
-{(unsigned char*)"blacktriangleleft", {226, 151, 130, 0}},
-{(unsigned char*)"blacktriangleright", {226, 150, 184, 0}},
-{(unsigned char*)"blank", {226, 144, 163, 0}},
-{(unsigned char*)"blk12", {226, 150, 146, 0}},
-{(unsigned char*)"blk14", {226, 150, 145, 0}},
-{(unsigned char*)"blk34", {226, 150, 147, 0}},
-{(unsigned char*)"block", {226, 150, 136, 0}},
-{(unsigned char*)"bne", {61, 226, 131, 165, 0}},
-{(unsigned char*)"bnequiv", {226, 137, 161, 226, 131, 165, 0}},
-{(unsigned char*)"bnot", {226, 140, 144, 0}},
-{(unsigned char*)"bopf", {240, 157, 149, 147, 0}},
-{(unsigned char*)"bot", {226, 138, 165, 0}},
-{(unsigned char*)"bottom", {226, 138, 165, 0}},
-{(unsigned char*)"bowtie", {226, 139, 136, 0}},
-{(unsigned char*)"boxDL", {226, 149, 151, 0}},
-{(unsigned char*)"boxDR", {226, 149, 148, 0}},
-{(unsigned char*)"boxDl", {226, 149, 150, 0}},
-{(unsigned char*)"boxDr", {226, 149, 147, 0}},
-{(unsigned char*)"boxH", {226, 149, 144, 0}},
-{(unsigned char*)"boxHD", {226, 149, 166, 0}},
-{(unsigned char*)"boxHU", {226, 149, 169, 0}},
-{(unsigned char*)"boxHd", {226, 149, 164, 0}},
-{(unsigned char*)"boxHu", {226, 149, 167, 0}},
-{(unsigned char*)"boxUL", {226, 149, 157, 0}},
-{(unsigned char*)"boxUR", {226, 149, 154, 0}},
-{(unsigned char*)"boxUl", {226, 149, 156, 0}},
-{(unsigned char*)"boxUr", {226, 149, 153, 0}},
-{(unsigned char*)"boxV", {226, 149, 145, 0}},
-{(unsigned char*)"boxVH", {226, 149, 172, 0}},
-{(unsigned char*)"boxVL", {226, 149, 163, 0}},
-{(unsigned char*)"boxVR", {226, 149, 160, 0}},
-{(unsigned char*)"boxVh", {226, 149, 171, 0}},
-{(unsigned char*)"boxVl", {226, 149, 162, 0}},
-{(unsigned char*)"boxVr", {226, 149, 159, 0}},
-{(unsigned char*)"boxbox", {226, 167, 137, 0}},
-{(unsigned char*)"boxdL", {226, 149, 149, 0}},
-{(unsigned char*)"boxdR", {226, 149, 146, 0}},
-{(unsigned char*)"boxdl", {226, 148, 144, 0}},
-{(unsigned char*)"boxdr", {226, 148, 140, 0}},
-{(unsigned char*)"boxh", {226, 148, 128, 0}},
-{(unsigned char*)"boxhD", {226, 149, 165, 0}},
-{(unsigned char*)"boxhU", {226, 149, 168, 0}},
-{(unsigned char*)"boxhd", {226, 148, 172, 0}},
-{(unsigned char*)"boxhu", {226, 148, 180, 0}},
-{(unsigned char*)"boxminus", {226, 138, 159, 0}},
-{(unsigned char*)"boxplus", {226, 138, 158, 0}},
-{(unsigned char*)"boxtimes", {226, 138, 160, 0}},
-{(unsigned char*)"boxuL", {226, 149, 155, 0}},
-{(unsigned char*)"boxuR", {226, 149, 152, 0}},
-{(unsigned char*)"boxul", {226, 148, 152, 0}},
-{(unsigned char*)"boxur", {226, 148, 148, 0}},
-{(unsigned char*)"boxv", {226, 148, 130, 0}},
-{(unsigned char*)"boxvH", {226, 149, 170, 0}},
-{(unsigned char*)"boxvL", {226, 149, 161, 0}},
-{(unsigned char*)"boxvR", {226, 149, 158, 0}},
-{(unsigned char*)"boxvh", {226, 148, 188, 0}},
-{(unsigned char*)"boxvl", {226, 148, 164, 0}},
-{(unsigned char*)"boxvr", {226, 148, 156, 0}},
-{(unsigned char*)"bprime", {226, 128, 181, 0}},
-{(unsigned char*)"breve", {203, 152, 0}},
-{(unsigned char*)"brvbar", {194, 166, 0}},
-{(unsigned char*)"bscr", {240, 157, 146, 183, 0}},
-{(unsigned char*)"bsemi", {226, 129, 143, 0}},
-{(unsigned char*)"bsim", {226, 136, 189, 0}},
-{(unsigned char*)"bsime", {226, 139, 141, 0}},
-{(unsigned char*)"bsol", {92, 0}},
-{(unsigned char*)"bsolb", {226, 167, 133, 0}},
-{(unsigned char*)"bsolhsub", {226, 159, 136, 0}},
-{(unsigned char*)"bull", {226, 128, 162, 0}},
-{(unsigned char*)"bullet", {226, 128, 162, 0}},
-{(unsigned char*)"bump", {226, 137, 142, 0}},
-{(unsigned char*)"bumpE", {226, 170, 174, 0}},
-{(unsigned char*)"bumpe", {226, 137, 143, 0}},
-{(unsigned char*)"bumpeq", {226, 137, 143, 0}},
-{(unsigned char*)"cacute", {196, 135, 0}},
-{(unsigned char*)"cap", {226, 136, 169, 0}},
-{(unsigned char*)"capand", {226, 169, 132, 0}},
-{(unsigned char*)"capbrcup", {226, 169, 137, 0}},
-{(unsigned char*)"capcap", {226, 169, 139, 0}},
-{(unsigned char*)"capcup", {226, 169, 135, 0}},
-{(unsigned char*)"capdot", {226, 169, 128, 0}},
-{(unsigned char*)"caps", {226, 136, 169, 239, 184, 128, 0}},
-{(unsigned char*)"caret", {226, 129, 129, 0}},
-{(unsigned char*)"caron", {203, 135, 0}},
-{(unsigned char*)"ccaps", {226, 169, 141, 0}},
-{(unsigned char*)"ccaron", {196, 141, 0}},
-{(unsigned char*)"ccedil", {195, 167, 0}},
-{(unsigned char*)"ccirc", {196, 137, 0}},
-{(unsigned char*)"ccups", {226, 169, 140, 0}},
-{(unsigned char*)"ccupssm", {226, 169, 144, 0}},
-{(unsigned char*)"cdot", {196, 139, 0}},
-{(unsigned char*)"cedil", {194, 184, 0}},
-{(unsigned char*)"cemptyv", {226, 166, 178, 0}},
-{(unsigned char*)"cent", {194, 162, 0}},
-{(unsigned char*)"centerdot", {194, 183, 0}},
-{(unsigned char*)"cfr", {240, 157, 148, 160, 0}},
-{(unsigned char*)"chcy", {209, 135, 0}},
-{(unsigned char*)"check", {226, 156, 147, 0}},
-{(unsigned char*)"checkmark", {226, 156, 147, 0}},
-{(unsigned char*)"chi", {207, 135, 0}},
-{(unsigned char*)"cir", {226, 151, 139, 0}},
-{(unsigned char*)"cirE", {226, 167, 131, 0}},
-{(unsigned char*)"circ", {203, 134, 0}},
-{(unsigned char*)"circeq", {226, 137, 151, 0}},
-{(unsigned char*)"circlearrowleft", {226, 134, 186, 0}},
-{(unsigned char*)"circlearrowright", {226, 134, 187, 0}},
-{(unsigned char*)"circledR", {194, 174, 0}},
-{(unsigned char*)"circledS", {226, 147, 136, 0}},
-{(unsigned char*)"circledast", {226, 138, 155, 0}},
-{(unsigned char*)"circledcirc", {226, 138, 154, 0}},
-{(unsigned char*)"circleddash", {226, 138, 157, 0}},
-{(unsigned char*)"cire", {226, 137, 151, 0}},
-{(unsigned char*)"cirfnint", {226, 168, 144, 0}},
-{(unsigned char*)"cirmid", {226, 171, 175, 0}},
-{(unsigned char*)"cirscir", {226, 167, 130, 0}},
-{(unsigned char*)"clubs", {226, 153, 163, 0}},
-{(unsigned char*)"clubsuit", {226, 153, 163, 0}},
-{(unsigned char*)"colon", {58, 0}},
-{(unsigned char*)"colone", {226, 137, 148, 0}},
-{(unsigned char*)"coloneq", {226, 137, 148, 0}},
-{(unsigned char*)"comma", {44, 0}},
-{(unsigned char*)"commat", {64, 0}},
-{(unsigned char*)"comp", {226, 136, 129, 0}},
-{(unsigned char*)"compfn", {226, 136, 152, 0}},
-{(unsigned char*)"complement", {226, 136, 129, 0}},
-{(unsigned char*)"complexes", {226, 132, 130, 0}},
-{(unsigned char*)"cong", {226, 137, 133, 0}},
-{(unsigned char*)"congdot", {226, 169, 173, 0}},
-{(unsigned char*)"conint", {226, 136, 174, 0}},
-{(unsigned char*)"copf", {240, 157, 149, 148, 0}},
-{(unsigned char*)"coprod", {226, 136, 144, 0}},
-{(unsigned char*)"copy", {194, 169, 0}},
-{(unsigned char*)"copysr", {226, 132, 151, 0}},
-{(unsigned char*)"crarr", {226, 134, 181, 0}},
-{(unsigned char*)"cross", {226, 156, 151, 0}},
-{(unsigned char*)"cscr", {240, 157, 146, 184, 0}},
-{(unsigned char*)"csub", {226, 171, 143, 0}},
-{(unsigned char*)"csube", {226, 171, 145, 0}},
-{(unsigned char*)"csup", {226, 171, 144, 0}},
-{(unsigned char*)"csupe", {226, 171, 146, 0}},
-{(unsigned char*)"ctdot", {226, 139, 175, 0}},
-{(unsigned char*)"cudarrl", {226, 164, 184, 0}},
-{(unsigned char*)"cudarrr", {226, 164, 181, 0}},
-{(unsigned char*)"cuepr", {226, 139, 158, 0}},
-{(unsigned char*)"cuesc", {226, 139, 159, 0}},
-{(unsigned char*)"cularr", {226, 134, 182, 0}},
-{(unsigned char*)"cularrp", {226, 164, 189, 0}},
-{(unsigned char*)"cup", {226, 136, 170, 0}},
-{(unsigned char*)"cupbrcap", {226, 169, 136, 0}},
-{(unsigned char*)"cupcap", {226, 169, 134, 0}},
-{(unsigned char*)"cupcup", {226, 169, 138, 0}},
-{(unsigned char*)"cupdot", {226, 138, 141, 0}},
-{(unsigned char*)"cupor", {226, 169, 133, 0}},
-{(unsigned char*)"cups", {226, 136, 170, 239, 184, 128, 0}},
-{(unsigned char*)"curarr", {226, 134, 183, 0}},
-{(unsigned char*)"curarrm", {226, 164, 188, 0}},
-{(unsigned char*)"curlyeqprec", {226, 139, 158, 0}},
-{(unsigned char*)"curlyeqsucc", {226, 139, 159, 0}},
-{(unsigned char*)"curlyvee", {226, 139, 142, 0}},
-{(unsigned char*)"curlywedge", {226, 139, 143, 0}},
-{(unsigned char*)"curren", {194, 164, 0}},
-{(unsigned char*)"curvearrowleft", {226, 134, 182, 0}},
-{(unsigned char*)"curvearrowright", {226, 134, 183, 0}},
-{(unsigned char*)"cuvee", {226, 139, 142, 0}},
-{(unsigned char*)"cuwed", {226, 139, 143, 0}},
-{(unsigned char*)"cwconint", {226, 136, 178, 0}},
-{(unsigned char*)"cwint", {226, 136, 177, 0}},
-{(unsigned char*)"cylcty", {226, 140, 173, 0}},
-{(unsigned char*)"dArr", {226, 135, 147, 0}},
-{(unsigned char*)"dHar", {226, 165, 165, 0}},
-{(unsigned char*)"dagger", {226, 128, 160, 0}},
-{(unsigned char*)"daleth", {226, 132, 184, 0}},
-{(unsigned char*)"darr", {226, 134, 147, 0}},
-{(unsigned char*)"dash", {226, 128, 144, 0}},
-{(unsigned char*)"dashv", {226, 138, 163, 0}},
-{(unsigned char*)"dbkarow", {226, 164, 143, 0}},
-{(unsigned char*)"dblac", {203, 157, 0}},
-{(unsigned char*)"dcaron", {196, 143, 0}},
-{(unsigned char*)"dcy", {208, 180, 0}},
-{(unsigned char*)"dd", {226, 133, 134, 0}},
-{(unsigned char*)"ddagger", {226, 128, 161, 0}},
-{(unsigned char*)"ddarr", {226, 135, 138, 0}},
-{(unsigned char*)"ddotseq", {226, 169, 183, 0}},
-{(unsigned char*)"deg", {194, 176, 0}},
-{(unsigned char*)"delta", {206, 180, 0}},
-{(unsigned char*)"demptyv", {226, 166, 177, 0}},
-{(unsigned char*)"dfisht", {226, 165, 191, 0}},
-{(unsigned char*)"dfr", {240, 157, 148, 161, 0}},
-{(unsigned char*)"dharl", {226, 135, 131, 0}},
-{(unsigned char*)"dharr", {226, 135, 130, 0}},
-{(unsigned char*)"diam", {226, 139, 132, 0}},
-{(unsigned char*)"diamond", {226, 139, 132, 0}},
-{(unsigned char*)"diamondsuit", {226, 153, 166, 0}},
-{(unsigned char*)"diams", {226, 153, 166, 0}},
-{(unsigned char*)"die", {194, 168, 0}},
-{(unsigned char*)"digamma", {207, 157, 0}},
-{(unsigned char*)"disin", {226, 139, 178, 0}},
-{(unsigned char*)"div", {195, 183, 0}},
-{(unsigned char*)"divide", {195, 183, 0}},
-{(unsigned char*)"divideontimes", {226, 139, 135, 0}},
-{(unsigned char*)"divonx", {226, 139, 135, 0}},
-{(unsigned char*)"djcy", {209, 146, 0}},
-{(unsigned char*)"dlcorn", {226, 140, 158, 0}},
-{(unsigned char*)"dlcrop", {226, 140, 141, 0}},
-{(unsigned char*)"dollar", {36, 0}},
-{(unsigned char*)"dopf", {240, 157, 149, 149, 0}},
-{(unsigned char*)"dot", {203, 153, 0}},
-{(unsigned char*)"doteq", {226, 137, 144, 0}},
-{(unsigned char*)"doteqdot", {226, 137, 145, 0}},
-{(unsigned char*)"dotminus", {226, 136, 184, 0}},
-{(unsigned char*)"dotplus", {226, 136, 148, 0}},
-{(unsigned char*)"dotsquare", {226, 138, 161, 0}},
-{(unsigned char*)"doublebarwedge", {226, 140, 134, 0}},
-{(unsigned char*)"downarrow", {226, 134, 147, 0}},
-{(unsigned char*)"downdownarrows", {226, 135, 138, 0}},
-{(unsigned char*)"downharpoonleft", {226, 135, 131, 0}},
-{(unsigned char*)"downharpoonright", {226, 135, 130, 0}},
-{(unsigned char*)"drbkarow", {226, 164, 144, 0}},
-{(unsigned char*)"drcorn", {226, 140, 159, 0}},
-{(unsigned char*)"drcrop", {226, 140, 140, 0}},
-{(unsigned char*)"dscr", {240, 157, 146, 185, 0}},
-{(unsigned char*)"dscy", {209, 149, 0}},
-{(unsigned char*)"dsol", {226, 167, 182, 0}},
-{(unsigned char*)"dstrok", {196, 145, 0}},
-{(unsigned char*)"dtdot", {226, 139, 177, 0}},
-{(unsigned char*)"dtri", {226, 150, 191, 0}},
-{(unsigned char*)"dtrif", {226, 150, 190, 0}},
-{(unsigned char*)"duarr", {226, 135, 181, 0}},
-{(unsigned char*)"duhar", {226, 165, 175, 0}},
-{(unsigned char*)"dwangle", {226, 166, 166, 0}},
-{(unsigned char*)"dzcy", {209, 159, 0}},
-{(unsigned char*)"dzigrarr", {226, 159, 191, 0}},
-{(unsigned char*)"eDDot", {226, 169, 183, 0}},
-{(unsigned char*)"eDot", {226, 137, 145, 0}},
-{(unsigned char*)"eacute", {195, 169, 0}},
-{(unsigned char*)"easter", {226, 169, 174, 0}},
-{(unsigned char*)"ecaron", {196, 155, 0}},
-{(unsigned char*)"ecir", {226, 137, 150, 0}},
-{(unsigned char*)"ecirc", {195, 170, 0}},
-{(unsigned char*)"ecolon", {226, 137, 149, 0}},
-{(unsigned char*)"ecy", {209, 141, 0}},
-{(unsigned char*)"edot", {196, 151, 0}},
-{(unsigned char*)"ee", {226, 133, 135, 0}},
-{(unsigned char*)"efDot", {226, 137, 146, 0}},
-{(unsigned char*)"efr", {240, 157, 148, 162, 0}},
-{(unsigned char*)"eg", {226, 170, 154, 0}},
-{(unsigned char*)"egrave", {195, 168, 0}},
-{(unsigned char*)"egs", {226, 170, 150, 0}},
-{(unsigned char*)"egsdot", {226, 170, 152, 0}},
-{(unsigned char*)"el", {226, 170, 153, 0}},
-{(unsigned char*)"elinters", {226, 143, 167, 0}},
-{(unsigned char*)"ell", {226, 132, 147, 0}},
-{(unsigned char*)"els", {226, 170, 149, 0}},
-{(unsigned char*)"elsdot", {226, 170, 151, 0}},
-{(unsigned char*)"emacr", {196, 147, 0}},
-{(unsigned char*)"empty", {226, 136, 133, 0}},
-{(unsigned char*)"emptyset", {226, 136, 133, 0}},
-{(unsigned char*)"emptyv", {226, 136, 133, 0}},
-{(unsigned char*)"emsp", {226, 128, 131, 0}},
-{(unsigned char*)"emsp13", {226, 128, 132, 0}},
-{(unsigned char*)"emsp14", {226, 128, 133, 0}},
-{(unsigned char*)"eng", {197, 139, 0}},
-{(unsigned char*)"ensp", {226, 128, 130, 0}},
-{(unsigned char*)"eogon", {196, 153, 0}},
-{(unsigned char*)"eopf", {240, 157, 149, 150, 0}},
-{(unsigned char*)"epar", {226, 139, 149, 0}},
-{(unsigned char*)"eparsl", {226, 167, 163, 0}},
-{(unsigned char*)"eplus", {226, 169, 177, 0}},
-{(unsigned char*)"epsi", {206, 181, 0}},
-{(unsigned char*)"epsilon", {206, 181, 0}},
-{(unsigned char*)"epsiv", {207, 181, 0}},
-{(unsigned char*)"eqcirc", {226, 137, 150, 0}},
-{(unsigned char*)"eqcolon", {226, 137, 149, 0}},
-{(unsigned char*)"eqsim", {226, 137, 130, 0}},
-{(unsigned char*)"eqslantgtr", {226, 170, 150, 0}},
-{(unsigned char*)"eqslantless", {226, 170, 149, 0}},
-{(unsigned char*)"equals", {61, 0}},
-{(unsigned char*)"equest", {226, 137, 159, 0}},
-{(unsigned char*)"equiv", {226, 137, 161, 0}},
-{(unsigned char*)"equivDD", {226, 169, 184, 0}},
-{(unsigned char*)"eqvparsl", {226, 167, 165, 0}},
-{(unsigned char*)"erDot", {226, 137, 147, 0}},
-{(unsigned char*)"erarr", {226, 165, 177, 0}},
-{(unsigned char*)"escr", {226, 132, 175, 0}},
-{(unsigned char*)"esdot", {226, 137, 144, 0}},
-{(unsigned char*)"esim", {226, 137, 130, 0}},
-{(unsigned char*)"eta", {206, 183, 0}},
-{(unsigned char*)"eth", {195, 176, 0}},
-{(unsigned char*)"euml", {195, 171, 0}},
-{(unsigned char*)"euro", {226, 130, 172, 0}},
-{(unsigned char*)"excl", {33, 0}},
-{(unsigned char*)"exist", {226, 136, 131, 0}},
-{(unsigned char*)"expectation", {226, 132, 176, 0}},
-{(unsigned char*)"exponentiale", {226, 133, 135, 0}},
-{(unsigned char*)"fallingdotseq", {226, 137, 146, 0}},
-{(unsigned char*)"fcy", {209, 132, 0}},
-{(unsigned char*)"female", {226, 153, 128, 0}},
-{(unsigned char*)"ffilig", {239, 172, 131, 0}},
-{(unsigned char*)"fflig", {239, 172, 128, 0}},
-{(unsigned char*)"ffllig", {239, 172, 132, 0}},
-{(unsigned char*)"ffr", {240, 157, 148, 163, 0}},
-{(unsigned char*)"filig", {239, 172, 129, 0}},
-{(unsigned char*)"fjlig", {102, 106, 0}},
-{(unsigned char*)"flat", {226, 153, 173, 0}},
-{(unsigned char*)"fllig", {239, 172, 130, 0}},
-{(unsigned char*)"fltns", {226, 150, 177, 0}},
-{(unsigned char*)"fnof", {198, 146, 0}},
-{(unsigned char*)"fopf", {240, 157, 149, 151, 0}},
-{(unsigned char*)"forall", {226, 136, 128, 0}},
-{(unsigned char*)"fork", {226, 139, 148, 0}},
-{(unsigned char*)"forkv", {226, 171, 153, 0}},
-{(unsigned char*)"fpartint", {226, 168, 141, 0}},
-{(unsigned char*)"frac12", {194, 189, 0}},
-{(unsigned char*)"frac13", {226, 133, 147, 0}},
-{(unsigned char*)"frac14", {194, 188, 0}},
-{(unsigned char*)"frac15", {226, 133, 149, 0}},
-{(unsigned char*)"frac16", {226, 133, 153, 0}},
-{(unsigned char*)"frac18", {226, 133, 155, 0}},
-{(unsigned char*)"frac23", {226, 133, 148, 0}},
-{(unsigned char*)"frac25", {226, 133, 150, 0}},
-{(unsigned char*)"frac34", {194, 190, 0}},
-{(unsigned char*)"frac35", {226, 133, 151, 0}},
-{(unsigned char*)"frac38", {226, 133, 156, 0}},
-{(unsigned char*)"frac45", {226, 133, 152, 0}},
-{(unsigned char*)"frac56", {226, 133, 154, 0}},
-{(unsigned char*)"frac58", {226, 133, 157, 0}},
-{(unsigned char*)"frac78", {226, 133, 158, 0}},
-{(unsigned char*)"frasl", {226, 129, 132, 0}},
-{(unsigned char*)"frown", {226, 140, 162, 0}},
-{(unsigned char*)"fscr", {240, 157, 146, 187, 0}},
-{(unsigned char*)"gE", {226, 137, 167, 0}},
-{(unsigned char*)"gEl", {226, 170, 140, 0}},
-{(unsigned char*)"gacute", {199, 181, 0}},
-{(unsigned char*)"gamma", {206, 179, 0}},
-{(unsigned char*)"gammad", {207, 157, 0}},
-{(unsigned char*)"gap", {226, 170, 134, 0}},
-{(unsigned char*)"gbreve", {196, 159, 0}},
-{(unsigned char*)"gcirc", {196, 157, 0}},
-{(unsigned char*)"gcy", {208, 179, 0}},
-{(unsigned char*)"gdot", {196, 161, 0}},
-{(unsigned char*)"ge", {226, 137, 165, 0}},
-{(unsigned char*)"gel", {226, 139, 155, 0}},
-{(unsigned char*)"geq", {226, 137, 165, 0}},
-{(unsigned char*)"geqq", {226, 137, 167, 0}},
-{(unsigned char*)"geqslant", {226, 169, 190, 0}},
-{(unsigned char*)"ges", {226, 169, 190, 0}},
-{(unsigned char*)"gescc", {226, 170, 169, 0}},
-{(unsigned char*)"gesdot", {226, 170, 128, 0}},
-{(unsigned char*)"gesdoto", {226, 170, 130, 0}},
-{(unsigned char*)"gesdotol", {226, 170, 132, 0}},
-{(unsigned char*)"gesl", {226, 139, 155, 239, 184, 128, 0}},
-{(unsigned char*)"gesles", {226, 170, 148, 0}},
-{(unsigned char*)"gfr", {240, 157, 148, 164, 0}},
-{(unsigned char*)"gg", {226, 137, 171, 0}},
-{(unsigned char*)"ggg", {226, 139, 153, 0}},
-{(unsigned char*)"gimel", {226, 132, 183, 0}},
-{(unsigned char*)"gjcy", {209, 147, 0}},
-{(unsigned char*)"gl", {226, 137, 183, 0}},
-{(unsigned char*)"glE", {226, 170, 146, 0}},
-{(unsigned char*)"gla", {226, 170, 165, 0}},
-{(unsigned char*)"glj", {226, 170, 164, 0}},
-{(unsigned char*)"gnE", {226, 137, 169, 0}},
-{(unsigned char*)"gnap", {226, 170, 138, 0}},
-{(unsigned char*)"gnapprox", {226, 170, 138, 0}},
-{(unsigned char*)"gne", {226, 170, 136, 0}},
-{(unsigned char*)"gneq", {226, 170, 136, 0}},
-{(unsigned char*)"gneqq", {226, 137, 169, 0}},
-{(unsigned char*)"gnsim", {226, 139, 167, 0}},
-{(unsigned char*)"gopf", {240, 157, 149, 152, 0}},
-{(unsigned char*)"grave", {96, 0}},
-{(unsigned char*)"gscr", {226, 132, 138, 0}},
-{(unsigned char*)"gsim", {226, 137, 179, 0}},
-{(unsigned char*)"gsime", {226, 170, 142, 0}},
-{(unsigned char*)"gsiml", {226, 170, 144, 0}},
-{(unsigned char*)"gt", {62, 0}},
-{(unsigned char*)"gtcc", {226, 170, 167, 0}},
-{(unsigned char*)"gtcir", {226, 169, 186, 0}},
-{(unsigned char*)"gtdot", {226, 139, 151, 0}},
-{(unsigned char*)"gtlPar", {226, 166, 149, 0}},
-{(unsigned char*)"gtquest", {226, 169, 188, 0}},
-{(unsigned char*)"gtrapprox", {226, 170, 134, 0}},
-{(unsigned char*)"gtrarr", {226, 165, 184, 0}},
-{(unsigned char*)"gtrdot", {226, 139, 151, 0}},
-{(unsigned char*)"gtreqless", {226, 139, 155, 0}},
-{(unsigned char*)"gtreqqless", {226, 170, 140, 0}},
-{(unsigned char*)"gtrless", {226, 137, 183, 0}},
-{(unsigned char*)"gtrsim", {226, 137, 179, 0}},
-{(unsigned char*)"gvertneqq", {226, 137, 169, 239, 184, 128, 0}},
-{(unsigned char*)"gvnE", {226, 137, 169, 239, 184, 128, 0}},
-{(unsigned char*)"hArr", {226, 135, 148, 0}},
-{(unsigned char*)"hairsp", {226, 128, 138, 0}},
-{(unsigned char*)"half", {194, 189, 0}},
-{(unsigned char*)"hamilt", {226, 132, 139, 0}},
-{(unsigned char*)"hardcy", {209, 138, 0}},
-{(unsigned char*)"harr", {226, 134, 148, 0}},
-{(unsigned char*)"harrcir", {226, 165, 136, 0}},
-{(unsigned char*)"harrw", {226, 134, 173, 0}},
-{(unsigned char*)"hbar", {226, 132, 143, 0}},
-{(unsigned char*)"hcirc", {196, 165, 0}},
-{(unsigned char*)"hearts", {226, 153, 165, 0}},
-{(unsigned char*)"heartsuit", {226, 153, 165, 0}},
-{(unsigned char*)"hellip", {226, 128, 166, 0}},
-{(unsigned char*)"hercon", {226, 138, 185, 0}},
-{(unsigned char*)"hfr", {240, 157, 148, 165, 0}},
-{(unsigned char*)"hksearow", {226, 164, 165, 0}},
-{(unsigned char*)"hkswarow", {226, 164, 166, 0}},
-{(unsigned char*)"hoarr", {226, 135, 191, 0}},
-{(unsigned char*)"homtht", {226, 136, 187, 0}},
-{(unsigned char*)"hookleftarrow", {226, 134, 169, 0}},
-{(unsigned char*)"hookrightarrow", {226, 134, 170, 0}},
-{(unsigned char*)"hopf", {240, 157, 149, 153, 0}},
-{(unsigned char*)"horbar", {226, 128, 149, 0}},
-{(unsigned char*)"hscr", {240, 157, 146, 189, 0}},
-{(unsigned char*)"hslash", {226, 132, 143, 0}},
-{(unsigned char*)"hstrok", {196, 167, 0}},
-{(unsigned char*)"hybull", {226, 129, 131, 0}},
-{(unsigned char*)"hyphen", {226, 128, 144, 0}},
-{(unsigned char*)"iacute", {195, 173, 0}},
-{(unsigned char*)"ic", {226, 129, 163, 0}},
-{(unsigned char*)"icirc", {195, 174, 0}},
-{(unsigned char*)"icy", {208, 184, 0}},
-{(unsigned char*)"iecy", {208, 181, 0}},
-{(unsigned char*)"iexcl", {194, 161, 0}},
-{(unsigned char*)"iff", {226, 135, 148, 0}},
-{(unsigned char*)"ifr", {240, 157, 148, 166, 0}},
-{(unsigned char*)"igrave", {195, 172, 0}},
-{(unsigned char*)"ii", {226, 133, 136, 0}},
-{(unsigned char*)"iiiint", {226, 168, 140, 0}},
-{(unsigned char*)"iiint", {226, 136, 173, 0}},
-{(unsigned char*)"iinfin", {226, 167, 156, 0}},
-{(unsigned char*)"iiota", {226, 132, 169, 0}},
-{(unsigned char*)"ijlig", {196, 179, 0}},
-{(unsigned char*)"imacr", {196, 171, 0}},
-{(unsigned char*)"image", {226, 132, 145, 0}},
-{(unsigned char*)"imagline", {226, 132, 144, 0}},
-{(unsigned char*)"imagpart", {226, 132, 145, 0}},
-{(unsigned char*)"imath", {196, 177, 0}},
-{(unsigned char*)"imof", {226, 138, 183, 0}},
-{(unsigned char*)"imped", {198, 181, 0}},
-{(unsigned char*)"in", {226, 136, 136, 0}},
-{(unsigned char*)"incare", {226, 132, 133, 0}},
-{(unsigned char*)"infin", {226, 136, 158, 0}},
-{(unsigned char*)"infintie", {226, 167, 157, 0}},
-{(unsigned char*)"inodot", {196, 177, 0}},
-{(unsigned char*)"int", {226, 136, 171, 0}},
-{(unsigned char*)"intcal", {226, 138, 186, 0}},
-{(unsigned char*)"integers", {226, 132, 164, 0}},
-{(unsigned char*)"intercal", {226, 138, 186, 0}},
-{(unsigned char*)"intlarhk", {226, 168, 151, 0}},
-{(unsigned char*)"intprod", {226, 168, 188, 0}},
-{(unsigned char*)"iocy", {209, 145, 0}},
-{(unsigned char*)"iogon", {196, 175, 0}},
-{(unsigned char*)"iopf", {240, 157, 149, 154, 0}},
-{(unsigned char*)"iota", {206, 185, 0}},
-{(unsigned char*)"iprod", {226, 168, 188, 0}},
-{(unsigned char*)"iquest", {194, 191, 0}},
-{(unsigned char*)"iscr", {240, 157, 146, 190, 0}},
-{(unsigned char*)"isin", {226, 136, 136, 0}},
-{(unsigned char*)"isinE", {226, 139, 185, 0}},
-{(unsigned char*)"isindot", {226, 139, 181, 0}},
-{(unsigned char*)"isins", {226, 139, 180, 0}},
-{(unsigned char*)"isinsv", {226, 139, 179, 0}},
-{(unsigned char*)"isinv", {226, 136, 136, 0}},
-{(unsigned char*)"it", {226, 129, 162, 0}},
-{(unsigned char*)"itilde", {196, 169, 0}},
-{(unsigned char*)"iukcy", {209, 150, 0}},
-{(unsigned char*)"iuml", {195, 175, 0}},
-{(unsigned char*)"jcirc", {196, 181, 0}},
-{(unsigned char*)"jcy", {208, 185, 0}},
-{(unsigned char*)"jfr", {240, 157, 148, 167, 0}},
-{(unsigned char*)"jmath", {200, 183, 0}},
-{(unsigned char*)"jopf", {240, 157, 149, 155, 0}},
-{(unsigned char*)"jscr", {240, 157, 146, 191, 0}},
-{(unsigned char*)"jsercy", {209, 152, 0}},
-{(unsigned char*)"jukcy", {209, 148, 0}},
-{(unsigned char*)"kappa", {206, 186, 0}},
-{(unsigned char*)"kappav", {207, 176, 0}},
-{(unsigned char*)"kcedil", {196, 183, 0}},
-{(unsigned char*)"kcy", {208, 186, 0}},
-{(unsigned char*)"kfr", {240, 157, 148, 168, 0}},
-{(unsigned char*)"kgreen", {196, 184, 0}},
-{(unsigned char*)"khcy", {209, 133, 0}},
-{(unsigned char*)"kjcy", {209, 156, 0}},
-{(unsigned char*)"kopf", {240, 157, 149, 156, 0}},
-{(unsigned char*)"kscr", {240, 157, 147, 128, 0}},
-{(unsigned char*)"lAarr", {226, 135, 154, 0}},
-{(unsigned char*)"lArr", {226, 135, 144, 0}},
-{(unsigned char*)"lAtail", {226, 164, 155, 0}},
-{(unsigned char*)"lBarr", {226, 164, 142, 0}},
-{(unsigned char*)"lE", {226, 137, 166, 0}},
-{(unsigned char*)"lEg", {226, 170, 139, 0}},
-{(unsigned char*)"lHar", {226, 165, 162, 0}},
-{(unsigned char*)"lacute", {196, 186, 0}},
-{(unsigned char*)"laemptyv", {226, 166, 180, 0}},
-{(unsigned char*)"lagran", {226, 132, 146, 0}},
-{(unsigned char*)"lambda", {206, 187, 0}},
-{(unsigned char*)"lang", {226, 159, 168, 0}},
-{(unsigned char*)"langd", {226, 166, 145, 0}},
-{(unsigned char*)"langle", {226, 159, 168, 0}},
-{(unsigned char*)"lap", {226, 170, 133, 0}},
-{(unsigned char*)"laquo", {194, 171, 0}},
-{(unsigned char*)"larr", {226, 134, 144, 0}},
-{(unsigned char*)"larrb", {226, 135, 164, 0}},
-{(unsigned char*)"larrbfs", {226, 164, 159, 0}},
-{(unsigned char*)"larrfs", {226, 164, 157, 0}},
-{(unsigned char*)"larrhk", {226, 134, 169, 0}},
-{(unsigned char*)"larrlp", {226, 134, 171, 0}},
-{(unsigned char*)"larrpl", {226, 164, 185, 0}},
-{(unsigned char*)"larrsim", {226, 165, 179, 0}},
-{(unsigned char*)"larrtl", {226, 134, 162, 0}},
-{(unsigned char*)"lat", {226, 170, 171, 0}},
-{(unsigned char*)"latail", {226, 164, 153, 0}},
-{(unsigned char*)"late", {226, 170, 173, 0}},
-{(unsigned char*)"lates", {226, 170, 173, 239, 184, 128, 0}},
-{(unsigned char*)"lbarr", {226, 164, 140, 0}},
-{(unsigned char*)"lbbrk", {226, 157, 178, 0}},
-{(unsigned char*)"lbrace", {123, 0}},
-{(unsigned char*)"lbrack", {91, 0}},
-{(unsigned char*)"lbrke", {226, 166, 139, 0}},
-{(unsigned char*)"lbrksld", {226, 166, 143, 0}},
-{(unsigned char*)"lbrkslu", {226, 166, 141, 0}},
-{(unsigned char*)"lcaron", {196, 190, 0}},
-{(unsigned char*)"lcedil", {196, 188, 0}},
-{(unsigned char*)"lceil", {226, 140, 136, 0}},
-{(unsigned char*)"lcub", {123, 0}},
-{(unsigned char*)"lcy", {208, 187, 0}},
-{(unsigned char*)"ldca", {226, 164, 182, 0}},
-{(unsigned char*)"ldquo", {226, 128, 156, 0}},
-{(unsigned char*)"ldquor", {226, 128, 158, 0}},
-{(unsigned char*)"ldrdhar", {226, 165, 167, 0}},
-{(unsigned char*)"ldrushar", {226, 165, 139, 0}},
-{(unsigned char*)"ldsh", {226, 134, 178, 0}},
-{(unsigned char*)"le", {226, 137, 164, 0}},
-{(unsigned char*)"leftarrow", {226, 134, 144, 0}},
-{(unsigned char*)"leftarrowtail", {226, 134, 162, 0}},
-{(unsigned char*)"leftharpoondown", {226, 134, 189, 0}},
-{(unsigned char*)"leftharpoonup", {226, 134, 188, 0}},
-{(unsigned char*)"leftleftarrows", {226, 135, 135, 0}},
-{(unsigned char*)"leftrightarrow", {226, 134, 148, 0}},
-{(unsigned char*)"leftrightarrows", {226, 135, 134, 0}},
-{(unsigned char*)"leftrightharpoons", {226, 135, 139, 0}},
-{(unsigned char*)"leftrightsquigarrow", {226, 134, 173, 0}},
-{(unsigned char*)"leftthreetimes", {226, 139, 139, 0}},
-{(unsigned char*)"leg", {226, 139, 154, 0}},
-{(unsigned char*)"leq", {226, 137, 164, 0}},
-{(unsigned char*)"leqq", {226, 137, 166, 0}},
-{(unsigned char*)"leqslant", {226, 169, 189, 0}},
-{(unsigned char*)"les", {226, 169, 189, 0}},
-{(unsigned char*)"lescc", {226, 170, 168, 0}},
-{(unsigned char*)"lesdot", {226, 169, 191, 0}},
-{(unsigned char*)"lesdoto", {226, 170, 129, 0}},
-{(unsigned char*)"lesdotor", {226, 170, 131, 0}},
-{(unsigned char*)"lesg", {226, 139, 154, 239, 184, 128, 0}},
-{(unsigned char*)"lesges", {226, 170, 147, 0}},
-{(unsigned char*)"lessapprox", {226, 170, 133, 0}},
-{(unsigned char*)"lessdot", {226, 139, 150, 0}},
-{(unsigned char*)"lesseqgtr", {226, 139, 154, 0}},
-{(unsigned char*)"lesseqqgtr", {226, 170, 139, 0}},
-{(unsigned char*)"lessgtr", {226, 137, 182, 0}},
-{(unsigned char*)"lesssim", {226, 137, 178, 0}},
-{(unsigned char*)"lfisht", {226, 165, 188, 0}},
-{(unsigned char*)"lfloor", {226, 140, 138, 0}},
-{(unsigned char*)"lfr", {240, 157, 148, 169, 0}},
-{(unsigned char*)"lg", {226, 137, 182, 0}},
-{(unsigned char*)"lgE", {226, 170, 145, 0}},
-{(unsigned char*)"lhard", {226, 134, 189, 0}},
-{(unsigned char*)"lharu", {226, 134, 188, 0}},
-{(unsigned char*)"lharul", {226, 165, 170, 0}},
-{(unsigned char*)"lhblk", {226, 150, 132, 0}},
-{(unsigned char*)"ljcy", {209, 153, 0}},
-{(unsigned char*)"ll", {226, 137, 170, 0}},
-{(unsigned char*)"llarr", {226, 135, 135, 0}},
-{(unsigned char*)"llcorner", {226, 140, 158, 0}},
-{(unsigned char*)"llhard", {226, 165, 171, 0}},
-{(unsigned char*)"lltri", {226, 151, 186, 0}},
-{(unsigned char*)"lmidot", {197, 128, 0}},
-{(unsigned char*)"lmoust", {226, 142, 176, 0}},
-{(unsigned char*)"lmoustache", {226, 142, 176, 0}},
-{(unsigned char*)"lnE", {226, 137, 168, 0}},
-{(unsigned char*)"lnap", {226, 170, 137, 0}},
-{(unsigned char*)"lnapprox", {226, 170, 137, 0}},
-{(unsigned char*)"lne", {226, 170, 135, 0}},
-{(unsigned char*)"lneq", {226, 170, 135, 0}},
-{(unsigned char*)"lneqq", {226, 137, 168, 0}},
-{(unsigned char*)"lnsim", {226, 139, 166, 0}},
-{(unsigned char*)"loang", {226, 159, 172, 0}},
-{(unsigned char*)"loarr", {226, 135, 189, 0}},
-{(unsigned char*)"lobrk", {226, 159, 166, 0}},
-{(unsigned char*)"longleftarrow", {226, 159, 181, 0}},
-{(unsigned char*)"longleftrightarrow", {226, 159, 183, 0}},
-{(unsigned char*)"longmapsto", {226, 159, 188, 0}},
-{(unsigned char*)"longrightarrow", {226, 159, 182, 0}},
-{(unsigned char*)"looparrowleft", {226, 134, 171, 0}},
-{(unsigned char*)"looparrowright", {226, 134, 172, 0}},
-{(unsigned char*)"lopar", {226, 166, 133, 0}},
-{(unsigned char*)"lopf", {240, 157, 149, 157, 0}},
-{(unsigned char*)"loplus", {226, 168, 173, 0}},
-{(unsigned char*)"lotimes", {226, 168, 180, 0}},
-{(unsigned char*)"lowast", {226, 136, 151, 0}},
-{(unsigned char*)"lowbar", {95, 0}},
-{(unsigned char*)"loz", {226, 151, 138, 0}},
-{(unsigned char*)"lozenge", {226, 151, 138, 0}},
-{(unsigned char*)"lozf", {226, 167, 171, 0}},
-{(unsigned char*)"lpar", {40, 0}},
-{(unsigned char*)"lparlt", {226, 166, 147, 0}},
-{(unsigned char*)"lrarr", {226, 135, 134, 0}},
-{(unsigned char*)"lrcorner", {226, 140, 159, 0}},
-{(unsigned char*)"lrhar", {226, 135, 139, 0}},
-{(unsigned char*)"lrhard", {226, 165, 173, 0}},
-{(unsigned char*)"lrm", {226, 128, 142, 0}},
-{(unsigned char*)"lrtri", {226, 138, 191, 0}},
-{(unsigned char*)"lsaquo", {226, 128, 185, 0}},
-{(unsigned char*)"lscr", {240, 157, 147, 129, 0}},
-{(unsigned char*)"lsh", {226, 134, 176, 0}},
-{(unsigned char*)"lsim", {226, 137, 178, 0}},
-{(unsigned char*)"lsime", {226, 170, 141, 0}},
-{(unsigned char*)"lsimg", {226, 170, 143, 0}},
-{(unsigned char*)"lsqb", {91, 0}},
-{(unsigned char*)"lsquo", {226, 128, 152, 0}},
-{(unsigned char*)"lsquor", {226, 128, 154, 0}},
-{(unsigned char*)"lstrok", {197, 130, 0}},
-{(unsigned char*)"lt", {60, 0}},
-{(unsigned char*)"ltcc", {226, 170, 166, 0}},
-{(unsigned char*)"ltcir", {226, 169, 185, 0}},
-{(unsigned char*)"ltdot", {226, 139, 150, 0}},
-{(unsigned char*)"lthree", {226, 139, 139, 0}},
-{(unsigned char*)"ltimes", {226, 139, 137, 0}},
-{(unsigned char*)"ltlarr", {226, 165, 182, 0}},
-{(unsigned char*)"ltquest", {226, 169, 187, 0}},
-{(unsigned char*)"ltrPar", {226, 166, 150, 0}},
-{(unsigned char*)"ltri", {226, 151, 131, 0}},
-{(unsigned char*)"ltrie", {226, 138, 180, 0}},
-{(unsigned char*)"ltrif", {226, 151, 130, 0}},
-{(unsigned char*)"lurdshar", {226, 165, 138, 0}},
-{(unsigned char*)"luruhar", {226, 165, 166, 0}},
-{(unsigned char*)"lvertneqq", {226, 137, 168, 239, 184, 128, 0}},
-{(unsigned char*)"lvnE", {226, 137, 168, 239, 184, 128, 0}},
-{(unsigned char*)"mDDot", {226, 136, 186, 0}},
-{(unsigned char*)"macr", {194, 175, 0}},
-{(unsigned char*)"male", {226, 153, 130, 0}},
-{(unsigned char*)"malt", {226, 156, 160, 0}},
-{(unsigned char*)"maltese", {226, 156, 160, 0}},
-{(unsigned char*)"map", {226, 134, 166, 0}},
-{(unsigned char*)"mapsto", {226, 134, 166, 0}},
-{(unsigned char*)"mapstodown", {226, 134, 167, 0}},
-{(unsigned char*)"mapstoleft", {226, 134, 164, 0}},
-{(unsigned char*)"mapstoup", {226, 134, 165, 0}},
-{(unsigned char*)"marker", {226, 150, 174, 0}},
-{(unsigned char*)"mcomma", {226, 168, 169, 0}},
-{(unsigned char*)"mcy", {208, 188, 0}},
-{(unsigned char*)"mdash", {226, 128, 148, 0}},
-{(unsigned char*)"measuredangle", {226, 136, 161, 0}},
-{(unsigned char*)"mfr", {240, 157, 148, 170, 0}},
-{(unsigned char*)"mho", {226, 132, 167, 0}},
-{(unsigned char*)"micro", {194, 181, 0}},
-{(unsigned char*)"mid", {226, 136, 163, 0}},
-{(unsigned char*)"midast", {42, 0}},
-{(unsigned char*)"midcir", {226, 171, 176, 0}},
-{(unsigned char*)"middot", {194, 183, 0}},
-{(unsigned char*)"minus", {226, 136, 146, 0}},
-{(unsigned char*)"minusb", {226, 138, 159, 0}},
-{(unsigned char*)"minusd", {226, 136, 184, 0}},
-{(unsigned char*)"minusdu", {226, 168, 170, 0}},
-{(unsigned char*)"mlcp", {226, 171, 155, 0}},
-{(unsigned char*)"mldr", {226, 128, 166, 0}},
-{(unsigned char*)"mnplus", {226, 136, 147, 0}},
-{(unsigned char*)"models", {226, 138, 167, 0}},
-{(unsigned char*)"mopf", {240, 157, 149, 158, 0}},
-{(unsigned char*)"mp", {226, 136, 147, 0}},
-{(unsigned char*)"mscr", {240, 157, 147, 130, 0}},
-{(unsigned char*)"mstpos", {226, 136, 190, 0}},
-{(unsigned char*)"mu", {206, 188, 0}},
-{(unsigned char*)"multimap", {226, 138, 184, 0}},
-{(unsigned char*)"mumap", {226, 138, 184, 0}},
-{(unsigned char*)"nGg", {226, 139, 153, 204, 184, 0}},
-{(unsigned char*)"nGt", {226, 137, 171, 226, 131, 146, 0}},
-{(unsigned char*)"nGtv", {226, 137, 171, 204, 184, 0}},
-{(unsigned char*)"nLeftarrow", {226, 135, 141, 0}},
-{(unsigned char*)"nLeftrightarrow", {226, 135, 142, 0}},
-{(unsigned char*)"nLl", {226, 139, 152, 204, 184, 0}},
-{(unsigned char*)"nLt", {226, 137, 170, 226, 131, 146, 0}},
-{(unsigned char*)"nLtv", {226, 137, 170, 204, 184, 0}},
-{(unsigned char*)"nRightarrow", {226, 135, 143, 0}},
-{(unsigned char*)"nVDash", {226, 138, 175, 0}},
-{(unsigned char*)"nVdash", {226, 138, 174, 0}},
-{(unsigned char*)"nabla", {226, 136, 135, 0}},
-{(unsigned char*)"nacute", {197, 132, 0}},
-{(unsigned char*)"nang", {226, 136, 160, 226, 131, 146, 0}},
-{(unsigned char*)"nap", {226, 137, 137, 0}},
-{(unsigned char*)"napE", {226, 169, 176, 204, 184, 0}},
-{(unsigned char*)"napid", {226, 137, 139, 204, 184, 0}},
-{(unsigned char*)"napos", {197, 137, 0}},
-{(unsigned char*)"napprox", {226, 137, 137, 0}},
-{(unsigned char*)"natur", {226, 153, 174, 0}},
-{(unsigned char*)"natural", {226, 153, 174, 0}},
-{(unsigned char*)"naturals", {226, 132, 149, 0}},
-{(unsigned char*)"nbsp", {194, 160, 0}},
-{(unsigned char*)"nbump", {226, 137, 142, 204, 184, 0}},
-{(unsigned char*)"nbumpe", {226, 137, 143, 204, 184, 0}},
-{(unsigned char*)"ncap", {226, 169, 131, 0}},
-{(unsigned char*)"ncaron", {197, 136, 0}},
-{(unsigned char*)"ncedil", {197, 134, 0}},
-{(unsigned char*)"ncong", {226, 137, 135, 0}},
-{(unsigned char*)"ncongdot", {226, 169, 173, 204, 184, 0}},
-{(unsigned char*)"ncup", {226, 169, 130, 0}},
-{(unsigned char*)"ncy", {208, 189, 0}},
-{(unsigned char*)"ndash", {226, 128, 147, 0}},
-{(unsigned char*)"ne", {226, 137, 160, 0}},
-{(unsigned char*)"neArr", {226, 135, 151, 0}},
-{(unsigned char*)"nearhk", {226, 164, 164, 0}},
-{(unsigned char*)"nearr", {226, 134, 151, 0}},
-{(unsigned char*)"nearrow", {226, 134, 151, 0}},
-{(unsigned char*)"nedot", {226, 137, 144, 204, 184, 0}},
-{(unsigned char*)"nequiv", {226, 137, 162, 0}},
-{(unsigned char*)"nesear", {226, 164, 168, 0}},
-{(unsigned char*)"nesim", {226, 137, 130, 204, 184, 0}},
-{(unsigned char*)"nexist", {226, 136, 132, 0}},
-{(unsigned char*)"nexists", {226, 136, 132, 0}},
-{(unsigned char*)"nfr", {240, 157, 148, 171, 0}},
-{(unsigned char*)"ngE", {226, 137, 167, 204, 184, 0}},
-{(unsigned char*)"nge", {226, 137, 177, 0}},
-{(unsigned char*)"ngeq", {226, 137, 177, 0}},
-{(unsigned char*)"ngeqq", {226, 137, 167, 204, 184, 0}},
-{(unsigned char*)"ngeqslant", {226, 169, 190, 204, 184, 0}},
-{(unsigned char*)"nges", {226, 169, 190, 204, 184, 0}},
-{(unsigned char*)"ngsim", {226, 137, 181, 0}},
-{(unsigned char*)"ngt", {226, 137, 175, 0}},
-{(unsigned char*)"ngtr", {226, 137, 175, 0}},
-{(unsigned char*)"nhArr", {226, 135, 142, 0}},
-{(unsigned char*)"nharr", {226, 134, 174, 0}},
-{(unsigned char*)"nhpar", {226, 171, 178, 0}},
-{(unsigned char*)"ni", {226, 136, 139, 0}},
-{(unsigned char*)"nis", {226, 139, 188, 0}},
-{(unsigned char*)"nisd", {226, 139, 186, 0}},
-{(unsigned char*)"niv", {226, 136, 139, 0}},
-{(unsigned char*)"njcy", {209, 154, 0}},
-{(unsigned char*)"nlArr", {226, 135, 141, 0}},
-{(unsigned char*)"nlE", {226, 137, 166, 204, 184, 0}},
-{(unsigned char*)"nlarr", {226, 134, 154, 0}},
-{(unsigned char*)"nldr", {226, 128, 165, 0}},
-{(unsigned char*)"nle", {226, 137, 176, 0}},
-{(unsigned char*)"nleftarrow", {226, 134, 154, 0}},
-{(unsigned char*)"nleftrightarrow", {226, 134, 174, 0}},
-{(unsigned char*)"nleq", {226, 137, 176, 0}},
-{(unsigned char*)"nleqq", {226, 137, 166, 204, 184, 0}},
-{(unsigned char*)"nleqslant", {226, 169, 189, 204, 184, 0}},
-{(unsigned char*)"nles", {226, 169, 189, 204, 184, 0}},
-{(unsigned char*)"nless", {226, 137, 174, 0}},
-{(unsigned char*)"nlsim", {226, 137, 180, 0}},
-{(unsigned char*)"nlt", {226, 137, 174, 0}},
-{(unsigned char*)"nltri", {226, 139, 170, 0}},
-{(unsigned char*)"nltrie", {226, 139, 172, 0}},
-{(unsigned char*)"nmid", {226, 136, 164, 0}},
-{(unsigned char*)"nopf", {240, 157, 149, 159, 0}},
-{(unsigned char*)"not", {194, 172, 0}},
-{(unsigned char*)"notin", {226, 136, 137, 0}},
-{(unsigned char*)"notinE", {226, 139, 185, 204, 184, 0}},
-{(unsigned char*)"notindot", {226, 139, 181, 204, 184, 0}},
-{(unsigned char*)"notinva", {226, 136, 137, 0}},
-{(unsigned char*)"notinvb", {226, 139, 183, 0}},
-{(unsigned char*)"notinvc", {226, 139, 182, 0}},
-{(unsigned char*)"notni", {226, 136, 140, 0}},
-{(unsigned char*)"notniva", {226, 136, 140, 0}},
-{(unsigned char*)"notnivb", {226, 139, 190, 0}},
-{(unsigned char*)"notnivc", {226, 139, 189, 0}},
-{(unsigned char*)"npar", {226, 136, 166, 0}},
-{(unsigned char*)"nparallel", {226, 136, 166, 0}},
-{(unsigned char*)"nparsl", {226, 171, 189, 226, 131, 165, 0}},
-{(unsigned char*)"npart", {226, 136, 130, 204, 184, 0}},
-{(unsigned char*)"npolint", {226, 168, 148, 0}},
-{(unsigned char*)"npr", {226, 138, 128, 0}},
-{(unsigned char*)"nprcue", {226, 139, 160, 0}},
-{(unsigned char*)"npre", {226, 170, 175, 204, 184, 0}},
-{(unsigned char*)"nprec", {226, 138, 128, 0}},
-{(unsigned char*)"npreceq", {226, 170, 175, 204, 184, 0}},
-{(unsigned char*)"nrArr", {226, 135, 143, 0}},
-{(unsigned char*)"nrarr", {226, 134, 155, 0}},
-{(unsigned char*)"nrarrc", {226, 164, 179, 204, 184, 0}},
-{(unsigned char*)"nrarrw", {226, 134, 157, 204, 184, 0}},
-{(unsigned char*)"nrightarrow", {226, 134, 155, 0}},
-{(unsigned char*)"nrtri", {226, 139, 171, 0}},
-{(unsigned char*)"nrtrie", {226, 139, 173, 0}},
-{(unsigned char*)"nsc", {226, 138, 129, 0}},
-{(unsigned char*)"nsccue", {226, 139, 161, 0}},
-{(unsigned char*)"nsce", {226, 170, 176, 204, 184, 0}},
-{(unsigned char*)"nscr", {240, 157, 147, 131, 0}},
-{(unsigned char*)"nshortmid", {226, 136, 164, 0}},
-{(unsigned char*)"nshortparallel", {226, 136, 166, 0}},
-{(unsigned char*)"nsim", {226, 137, 129, 0}},
-{(unsigned char*)"nsime", {226, 137, 132, 0}},
-{(unsigned char*)"nsimeq", {226, 137, 132, 0}},
-{(unsigned char*)"nsmid", {226, 136, 164, 0}},
-{(unsigned char*)"nspar", {226, 136, 166, 0}},
-{(unsigned char*)"nsqsube", {226, 139, 162, 0}},
-{(unsigned char*)"nsqsupe", {226, 139, 163, 0}},
-{(unsigned char*)"nsub", {226, 138, 132, 0}},
-{(unsigned char*)"nsubE", {226, 171, 133, 204, 184, 0}},
-{(unsigned char*)"nsube", {226, 138, 136, 0}},
-{(unsigned char*)"nsubset", {226, 138, 130, 226, 131, 146, 0}},
-{(unsigned char*)"nsubseteq", {226, 138, 136, 0}},
-{(unsigned char*)"nsubseteqq", {226, 171, 133, 204, 184, 0}},
-{(unsigned char*)"nsucc", {226, 138, 129, 0}},
-{(unsigned char*)"nsucceq", {226, 170, 176, 204, 184, 0}},
-{(unsigned char*)"nsup", {226, 138, 133, 0}},
-{(unsigned char*)"nsupE", {226, 171, 134, 204, 184, 0}},
-{(unsigned char*)"nsupe", {226, 138, 137, 0}},
-{(unsigned char*)"nsupset", {226, 138, 131, 226, 131, 146, 0}},
-{(unsigned char*)"nsupseteq", {226, 138, 137, 0}},
-{(unsigned char*)"nsupseteqq", {226, 171, 134, 204, 184, 0}},
-{(unsigned char*)"ntgl", {226, 137, 185, 0}},
-{(unsigned char*)"ntilde", {195, 177, 0}},
-{(unsigned char*)"ntlg", {226, 137, 184, 0}},
-{(unsigned char*)"ntriangleleft", {226, 139, 170, 0}},
-{(unsigned char*)"ntrianglelefteq", {226, 139, 172, 0}},
-{(unsigned char*)"ntriangleright", {226, 139, 171, 0}},
-{(unsigned char*)"ntrianglerighteq", {226, 139, 173, 0}},
-{(unsigned char*)"nu", {206, 189, 0}},
-{(unsigned char*)"num", {35, 0}},
-{(unsigned char*)"numero", {226, 132, 150, 0}},
-{(unsigned char*)"numsp", {226, 128, 135, 0}},
-{(unsigned char*)"nvDash", {226, 138, 173, 0}},
-{(unsigned char*)"nvHarr", {226, 164, 132, 0}},
-{(unsigned char*)"nvap", {226, 137, 141, 226, 131, 146, 0}},
-{(unsigned char*)"nvdash", {226, 138, 172, 0}},
-{(unsigned char*)"nvge", {226, 137, 165, 226, 131, 146, 0}},
-{(unsigned char*)"nvgt", {62, 226, 131, 146, 0}},
-{(unsigned char*)"nvinfin", {226, 167, 158, 0}},
-{(unsigned char*)"nvlArr", {226, 164, 130, 0}},
-{(unsigned char*)"nvle", {226, 137, 164, 226, 131, 146, 0}},
-{(unsigned char*)"nvlt", {60, 226, 131, 146, 0}},
-{(unsigned char*)"nvltrie", {226, 138, 180, 226, 131, 146, 0}},
-{(unsigned char*)"nvrArr", {226, 164, 131, 0}},
-{(unsigned char*)"nvrtrie", {226, 138, 181, 226, 131, 146, 0}},
-{(unsigned char*)"nvsim", {226, 136, 188, 226, 131, 146, 0}},
-{(unsigned char*)"nwArr", {226, 135, 150, 0}},
-{(unsigned char*)"nwarhk", {226, 164, 163, 0}},
-{(unsigned char*)"nwarr", {226, 134, 150, 0}},
-{(unsigned char*)"nwarrow", {226, 134, 150, 0}},
-{(unsigned char*)"nwnear", {226, 164, 167, 0}},
-{(unsigned char*)"oS", {226, 147, 136, 0}},
-{(unsigned char*)"oacute", {195, 179, 0}},
-{(unsigned char*)"oast", {226, 138, 155, 0}},
-{(unsigned char*)"ocir", {226, 138, 154, 0}},
-{(unsigned char*)"ocirc", {195, 180, 0}},
-{(unsigned char*)"ocy", {208, 190, 0}},
-{(unsigned char*)"odash", {226, 138, 157, 0}},
-{(unsigned char*)"odblac", {197, 145, 0}},
-{(unsigned char*)"odiv", {226, 168, 184, 0}},
-{(unsigned char*)"odot", {226, 138, 153, 0}},
-{(unsigned char*)"odsold", {226, 166, 188, 0}},
-{(unsigned char*)"oelig", {197, 147, 0}},
-{(unsigned char*)"ofcir", {226, 166, 191, 0}},
-{(unsigned char*)"ofr", {240, 157, 148, 172, 0}},
-{(unsigned char*)"ogon", {203, 155, 0}},
-{(unsigned char*)"ograve", {195, 178, 0}},
-{(unsigned char*)"ogt", {226, 167, 129, 0}},
-{(unsigned char*)"ohbar", {226, 166, 181, 0}},
-{(unsigned char*)"ohm", {206, 169, 0}},
-{(unsigned char*)"oint", {226, 136, 174, 0}},
-{(unsigned char*)"olarr", {226, 134, 186, 0}},
-{(unsigned char*)"olcir", {226, 166, 190, 0}},
-{(unsigned char*)"olcross", {226, 166, 187, 0}},
-{(unsigned char*)"oline", {226, 128, 190, 0}},
-{(unsigned char*)"olt", {226, 167, 128, 0}},
-{(unsigned char*)"omacr", {197, 141, 0}},
-{(unsigned char*)"omega", {207, 137, 0}},
-{(unsigned char*)"omicron", {206, 191, 0}},
-{(unsigned char*)"omid", {226, 166, 182, 0}},
-{(unsigned char*)"ominus", {226, 138, 150, 0}},
-{(unsigned char*)"oopf", {240, 157, 149, 160, 0}},
-{(unsigned char*)"opar", {226, 166, 183, 0}},
-{(unsigned char*)"operp", {226, 166, 185, 0}},
-{(unsigned char*)"oplus", {226, 138, 149, 0}},
-{(unsigned char*)"or", {226, 136, 168, 0}},
-{(unsigned char*)"orarr", {226, 134, 187, 0}},
-{(unsigned char*)"ord", {226, 169, 157, 0}},
-{(unsigned char*)"order", {226, 132, 180, 0}},
-{(unsigned char*)"orderof", {226, 132, 180, 0}},
-{(unsigned char*)"ordf", {194, 170, 0}},
-{(unsigned char*)"ordm", {194, 186, 0}},
-{(unsigned char*)"origof", {226, 138, 182, 0}},
-{(unsigned char*)"oror", {226, 169, 150, 0}},
-{(unsigned char*)"orslope", {226, 169, 151, 0}},
-{(unsigned char*)"orv", {226, 169, 155, 0}},
-{(unsigned char*)"oscr", {226, 132, 180, 0}},
-{(unsigned char*)"oslash", {195, 184, 0}},
-{(unsigned char*)"osol", {226, 138, 152, 0}},
-{(unsigned char*)"otilde", {195, 181, 0}},
-{(unsigned char*)"otimes", {226, 138, 151, 0}},
-{(unsigned char*)"otimesas", {226, 168, 182, 0}},
-{(unsigned char*)"ouml", {195, 182, 0}},
-{(unsigned char*)"ovbar", {226, 140, 189, 0}},
-{(unsigned char*)"par", {226, 136, 165, 0}},
-{(unsigned char*)"para", {194, 182, 0}},
-{(unsigned char*)"parallel", {226, 136, 165, 0}},
-{(unsigned char*)"parsim", {226, 171, 179, 0}},
-{(unsigned char*)"parsl", {226, 171, 189, 0}},
-{(unsigned char*)"part", {226, 136, 130, 0}},
-{(unsigned char*)"pcy", {208, 191, 0}},
-{(unsigned char*)"percnt", {37, 0}},
-{(unsigned char*)"period", {46, 0}},
-{(unsigned char*)"permil", {226, 128, 176, 0}},
-{(unsigned char*)"perp", {226, 138, 165, 0}},
-{(unsigned char*)"pertenk", {226, 128, 177, 0}},
-{(unsigned char*)"pfr", {240, 157, 148, 173, 0}},
-{(unsigned char*)"phi", {207, 134, 0}},
-{(unsigned char*)"phiv", {207, 149, 0}},
-{(unsigned char*)"phmmat", {226, 132, 179, 0}},
-{(unsigned char*)"phone", {226, 152, 142, 0}},
-{(unsigned char*)"pi", {207, 128, 0}},
-{(unsigned char*)"pitchfork", {226, 139, 148, 0}},
-{(unsigned char*)"piv", {207, 150, 0}},
-{(unsigned char*)"planck", {226, 132, 143, 0}},
-{(unsigned char*)"planckh", {226, 132, 142, 0}},
-{(unsigned char*)"plankv", {226, 132, 143, 0}},
-{(unsigned char*)"plus", {43, 0}},
-{(unsigned char*)"plusacir", {226, 168, 163, 0}},
-{(unsigned char*)"plusb", {226, 138, 158, 0}},
-{(unsigned char*)"pluscir", {226, 168, 162, 0}},
-{(unsigned char*)"plusdo", {226, 136, 148, 0}},
-{(unsigned char*)"plusdu", {226, 168, 165, 0}},
-{(unsigned char*)"pluse", {226, 169, 178, 0}},
-{(unsigned char*)"plusmn", {194, 177, 0}},
-{(unsigned char*)"plussim", {226, 168, 166, 0}},
-{(unsigned char*)"plustwo", {226, 168, 167, 0}},
-{(unsigned char*)"pm", {194, 177, 0}},
-{(unsigned char*)"pointint", {226, 168, 149, 0}},
-{(unsigned char*)"popf", {240, 157, 149, 161, 0}},
-{(unsigned char*)"pound", {194, 163, 0}},
-{(unsigned char*)"pr", {226, 137, 186, 0}},
-{(unsigned char*)"prE", {226, 170, 179, 0}},
-{(unsigned char*)"prap", {226, 170, 183, 0}},
-{(unsigned char*)"prcue", {226, 137, 188, 0}},
-{(unsigned char*)"pre", {226, 170, 175, 0}},
-{(unsigned char*)"prec", {226, 137, 186, 0}},
-{(unsigned char*)"precapprox", {226, 170, 183, 0}},
-{(unsigned char*)"preccurlyeq", {226, 137, 188, 0}},
-{(unsigned char*)"preceq", {226, 170, 175, 0}},
-{(unsigned char*)"precnapprox", {226, 170, 185, 0}},
-{(unsigned char*)"precneqq", {226, 170, 181, 0}},
-{(unsigned char*)"precnsim", {226, 139, 168, 0}},
-{(unsigned char*)"precsim", {226, 137, 190, 0}},
-{(unsigned char*)"prime", {226, 128, 178, 0}},
-{(unsigned char*)"primes", {226, 132, 153, 0}},
-{(unsigned char*)"prnE", {226, 170, 181, 0}},
-{(unsigned char*)"prnap", {226, 170, 185, 0}},
-{(unsigned char*)"prnsim", {226, 139, 168, 0}},
-{(unsigned char*)"prod", {226, 136, 143, 0}},
-{(unsigned char*)"profalar", {226, 140, 174, 0}},
-{(unsigned char*)"profline", {226, 140, 146, 0}},
-{(unsigned char*)"profsurf", {226, 140, 147, 0}},
-{(unsigned char*)"prop", {226, 136, 157, 0}},
-{(unsigned char*)"propto", {226, 136, 157, 0}},
-{(unsigned char*)"prsim", {226, 137, 190, 0}},
-{(unsigned char*)"prurel", {226, 138, 176, 0}},
-{(unsigned char*)"pscr", {240, 157, 147, 133, 0}},
-{(unsigned char*)"psi", {207, 136, 0}},
-{(unsigned char*)"puncsp", {226, 128, 136, 0}},
-{(unsigned char*)"qfr", {240, 157, 148, 174, 0}},
-{(unsigned char*)"qint", {226, 168, 140, 0}},
-{(unsigned char*)"qopf", {240, 157, 149, 162, 0}},
-{(unsigned char*)"qprime", {226, 129, 151, 0}},
-{(unsigned char*)"qscr", {240, 157, 147, 134, 0}},
-{(unsigned char*)"quaternions", {226, 132, 141, 0}},
-{(unsigned char*)"quatint", {226, 168, 150, 0}},
-{(unsigned char*)"quest", {63, 0}},
-{(unsigned char*)"questeq", {226, 137, 159, 0}},
-{(unsigned char*)"quot", {34, 0}},
-{(unsigned char*)"rAarr", {226, 135, 155, 0}},
-{(unsigned char*)"rArr", {226, 135, 146, 0}},
-{(unsigned char*)"rAtail", {226, 164, 156, 0}},
-{(unsigned char*)"rBarr", {226, 164, 143, 0}},
-{(unsigned char*)"rHar", {226, 165, 164, 0}},
-{(unsigned char*)"race", {226, 136, 189, 204, 177, 0}},
-{(unsigned char*)"racute", {197, 149, 0}},
-{(unsigned char*)"radic", {226, 136, 154, 0}},
-{(unsigned char*)"raemptyv", {226, 166, 179, 0}},
-{(unsigned char*)"rang", {226, 159, 169, 0}},
-{(unsigned char*)"rangd", {226, 166, 146, 0}},
-{(unsigned char*)"range", {226, 166, 165, 0}},
-{(unsigned char*)"rangle", {226, 159, 169, 0}},
-{(unsigned char*)"raquo", {194, 187, 0}},
-{(unsigned char*)"rarr", {226, 134, 146, 0}},
-{(unsigned char*)"rarrap", {226, 165, 181, 0}},
-{(unsigned char*)"rarrb", {226, 135, 165, 0}},
-{(unsigned char*)"rarrbfs", {226, 164, 160, 0}},
-{(unsigned char*)"rarrc", {226, 164, 179, 0}},
-{(unsigned char*)"rarrfs", {226, 164, 158, 0}},
-{(unsigned char*)"rarrhk", {226, 134, 170, 0}},
-{(unsigned char*)"rarrlp", {226, 134, 172, 0}},
-{(unsigned char*)"rarrpl", {226, 165, 133, 0}},
-{(unsigned char*)"rarrsim", {226, 165, 180, 0}},
-{(unsigned char*)"rarrtl", {226, 134, 163, 0}},
-{(unsigned char*)"rarrw", {226, 134, 157, 0}},
-{(unsigned char*)"ratail", {226, 164, 154, 0}},
-{(unsigned char*)"ratio", {226, 136, 182, 0}},
-{(unsigned char*)"rationals", {226, 132, 154, 0}},
-{(unsigned char*)"rbarr", {226, 164, 141, 0}},
-{(unsigned char*)"rbbrk", {226, 157, 179, 0}},
-{(unsigned char*)"rbrace", {125, 0}},
-{(unsigned char*)"rbrack", {93, 0}},
-{(unsigned char*)"rbrke", {226, 166, 140, 0}},
-{(unsigned char*)"rbrksld", {226, 166, 142, 0}},
-{(unsigned char*)"rbrkslu", {226, 166, 144, 0}},
-{(unsigned char*)"rcaron", {197, 153, 0}},
-{(unsigned char*)"rcedil", {197, 151, 0}},
-{(unsigned char*)"rceil", {226, 140, 137, 0}},
-{(unsigned char*)"rcub", {125, 0}},
-{(unsigned char*)"rcy", {209, 128, 0}},
-{(unsigned char*)"rdca", {226, 164, 183, 0}},
-{(unsigned char*)"rdldhar", {226, 165, 169, 0}},
-{(unsigned char*)"rdquo", {226, 128, 157, 0}},
-{(unsigned char*)"rdquor", {226, 128, 157, 0}},
-{(unsigned char*)"rdsh", {226, 134, 179, 0}},
-{(unsigned char*)"real", {226, 132, 156, 0}},
-{(unsigned char*)"realine", {226, 132, 155, 0}},
-{(unsigned char*)"realpart", {226, 132, 156, 0}},
-{(unsigned char*)"reals", {226, 132, 157, 0}},
-{(unsigned char*)"rect", {226, 150, 173, 0}},
-{(unsigned char*)"reg", {194, 174, 0}},
-{(unsigned char*)"rfisht", {226, 165, 189, 0}},
-{(unsigned char*)"rfloor", {226, 140, 139, 0}},
-{(unsigned char*)"rfr", {240, 157, 148, 175, 0}},
-{(unsigned char*)"rhard", {226, 135, 129, 0}},
-{(unsigned char*)"rharu", {226, 135, 128, 0}},
-{(unsigned char*)"rharul", {226, 165, 172, 0}},
-{(unsigned char*)"rho", {207, 129, 0}},
-{(unsigned char*)"rhov", {207, 177, 0}},
-{(unsigned char*)"rightarrow", {226, 134, 146, 0}},
-{(unsigned char*)"rightarrowtail", {226, 134, 163, 0}},
-{(unsigned char*)"rightharpoondown", {226, 135, 129, 0}},
-{(unsigned char*)"rightharpoonup", {226, 135, 128, 0}},
-{(unsigned char*)"rightleftarrows", {226, 135, 132, 0}},
-{(unsigned char*)"rightleftharpoons", {226, 135, 140, 0}},
-{(unsigned char*)"rightrightarrows", {226, 135, 137, 0}},
-{(unsigned char*)"rightsquigarrow", {226, 134, 157, 0}},
-{(unsigned char*)"rightthreetimes", {226, 139, 140, 0}},
-{(unsigned char*)"ring", {203, 154, 0}},
-{(unsigned char*)"risingdotseq", {226, 137, 147, 0}},
-{(unsigned char*)"rlarr", {226, 135, 132, 0}},
-{(unsigned char*)"rlhar", {226, 135, 140, 0}},
-{(unsigned char*)"rlm", {226, 128, 143, 0}},
-{(unsigned char*)"rmoust", {226, 142, 177, 0}},
-{(unsigned char*)"rmoustache", {226, 142, 177, 0}},
-{(unsigned char*)"rnmid", {226, 171, 174, 0}},
-{(unsigned char*)"roang", {226, 159, 173, 0}},
-{(unsigned char*)"roarr", {226, 135, 190, 0}},
-{(unsigned char*)"robrk", {226, 159, 167, 0}},
-{(unsigned char*)"ropar", {226, 166, 134, 0}},
-{(unsigned char*)"ropf", {240, 157, 149, 163, 0}},
-{(unsigned char*)"roplus", {226, 168, 174, 0}},
-{(unsigned char*)"rotimes", {226, 168, 181, 0}},
-{(unsigned char*)"rpar", {41, 0}},
-{(unsigned char*)"rpargt", {226, 166, 148, 0}},
-{(unsigned char*)"rppolint", {226, 168, 146, 0}},
-{(unsigned char*)"rrarr", {226, 135, 137, 0}},
-{(unsigned char*)"rsaquo", {226, 128, 186, 0}},
-{(unsigned char*)"rscr", {240, 157, 147, 135, 0}},
-{(unsigned char*)"rsh", {226, 134, 177, 0}},
-{(unsigned char*)"rsqb", {93, 0}},
-{(unsigned char*)"rsquo", {226, 128, 153, 0}},
-{(unsigned char*)"rsquor", {226, 128, 153, 0}},
-{(unsigned char*)"rthree", {226, 139, 140, 0}},
-{(unsigned char*)"rtimes", {226, 139, 138, 0}},
-{(unsigned char*)"rtri", {226, 150, 185, 0}},
-{(unsigned char*)"rtrie", {226, 138, 181, 0}},
-{(unsigned char*)"rtrif", {226, 150, 184, 0}},
-{(unsigned char*)"rtriltri", {226, 167, 142, 0}},
-{(unsigned char*)"ruluhar", {226, 165, 168, 0}},
-{(unsigned char*)"rx", {226, 132, 158, 0}},
-{(unsigned char*)"sacute", {197, 155, 0}},
-{(unsigned char*)"sbquo", {226, 128, 154, 0}},
-{(unsigned char*)"sc", {226, 137, 187, 0}},
-{(unsigned char*)"scE", {226, 170, 180, 0}},
-{(unsigned char*)"scap", {226, 170, 184, 0}},
-{(unsigned char*)"scaron", {197, 161, 0}},
-{(unsigned char*)"sccue", {226, 137, 189, 0}},
-{(unsigned char*)"sce", {226, 170, 176, 0}},
-{(unsigned char*)"scedil", {197, 159, 0}},
-{(unsigned char*)"scirc", {197, 157, 0}},
-{(unsigned char*)"scnE", {226, 170, 182, 0}},
-{(unsigned char*)"scnap", {226, 170, 186, 0}},
-{(unsigned char*)"scnsim", {226, 139, 169, 0}},
-{(unsigned char*)"scpolint", {226, 168, 147, 0}},
-{(unsigned char*)"scsim", {226, 137, 191, 0}},
-{(unsigned char*)"scy", {209, 129, 0}},
-{(unsigned char*)"sdot", {226, 139, 133, 0}},
-{(unsigned char*)"sdotb", {226, 138, 161, 0}},
-{(unsigned char*)"sdote", {226, 169, 166, 0}},
-{(unsigned char*)"seArr", {226, 135, 152, 0}},
-{(unsigned char*)"searhk", {226, 164, 165, 0}},
-{(unsigned char*)"searr", {226, 134, 152, 0}},
-{(unsigned char*)"searrow", {226, 134, 152, 0}},
-{(unsigned char*)"sect", {194, 167, 0}},
-{(unsigned char*)"semi", {59, 0}},
-{(unsigned char*)"seswar", {226, 164, 169, 0}},
-{(unsigned char*)"setminus", {226, 136, 150, 0}},
-{(unsigned char*)"setmn", {226, 136, 150, 0}},
-{(unsigned char*)"sext", {226, 156, 182, 0}},
-{(unsigned char*)"sfr", {240, 157, 148, 176, 0}},
-{(unsigned char*)"sfrown", {226, 140, 162, 0}},
-{(unsigned char*)"sharp", {226, 153, 175, 0}},
-{(unsigned char*)"shchcy", {209, 137, 0}},
-{(unsigned char*)"shcy", {209, 136, 0}},
-{(unsigned char*)"shortmid", {226, 136, 163, 0}},
-{(unsigned char*)"shortparallel", {226, 136, 165, 0}},
-{(unsigned char*)"shy", {194, 173, 0}},
-{(unsigned char*)"sigma", {207, 131, 0}},
-{(unsigned char*)"sigmaf", {207, 130, 0}},
-{(unsigned char*)"sigmav", {207, 130, 0}},
-{(unsigned char*)"sim", {226, 136, 188, 0}},
-{(unsigned char*)"simdot", {226, 169, 170, 0}},
-{(unsigned char*)"sime", {226, 137, 131, 0}},
-{(unsigned char*)"simeq", {226, 137, 131, 0}},
-{(unsigned char*)"simg", {226, 170, 158, 0}},
-{(unsigned char*)"simgE", {226, 170, 160, 0}},
-{(unsigned char*)"siml", {226, 170, 157, 0}},
-{(unsigned char*)"simlE", {226, 170, 159, 0}},
-{(unsigned char*)"simne", {226, 137, 134, 0}},
-{(unsigned char*)"simplus", {226, 168, 164, 0}},
-{(unsigned char*)"simrarr", {226, 165, 178, 0}},
-{(unsigned char*)"slarr", {226, 134, 144, 0}},
-{(unsigned char*)"smallsetminus", {226, 136, 150, 0}},
-{(unsigned char*)"smashp", {226, 168, 179, 0}},
-{(unsigned char*)"smeparsl", {226, 167, 164, 0}},
-{(unsigned char*)"smid", {226, 136, 163, 0}},
-{(unsigned char*)"smile", {226, 140, 163, 0}},
-{(unsigned char*)"smt", {226, 170, 170, 0}},
-{(unsigned char*)"smte", {226, 170, 172, 0}},
-{(unsigned char*)"smtes", {226, 170, 172, 239, 184, 128, 0}},
-{(unsigned char*)"softcy", {209, 140, 0}},
-{(unsigned char*)"sol", {47, 0}},
-{(unsigned char*)"solb", {226, 167, 132, 0}},
-{(unsigned char*)"solbar", {226, 140, 191, 0}},
-{(unsigned char*)"sopf", {240, 157, 149, 164, 0}},
-{(unsigned char*)"spades", {226, 153, 160, 0}},
-{(unsigned char*)"spadesuit", {226, 153, 160, 0}},
-{(unsigned char*)"spar", {226, 136, 165, 0}},
-{(unsigned char*)"sqcap", {226, 138, 147, 0}},
-{(unsigned char*)"sqcaps", {226, 138, 147, 239, 184, 128, 0}},
-{(unsigned char*)"sqcup", {226, 138, 148, 0}},
-{(unsigned char*)"sqcups", {226, 138, 148, 239, 184, 128, 0}},
-{(unsigned char*)"sqsub", {226, 138, 143, 0}},
-{(unsigned char*)"sqsube", {226, 138, 145, 0}},
-{(unsigned char*)"sqsubset", {226, 138, 143, 0}},
-{(unsigned char*)"sqsubseteq", {226, 138, 145, 0}},
-{(unsigned char*)"sqsup", {226, 138, 144, 0}},
-{(unsigned char*)"sqsupe", {226, 138, 146, 0}},
-{(unsigned char*)"sqsupset", {226, 138, 144, 0}},
-{(unsigned char*)"sqsupseteq", {226, 138, 146, 0}},
-{(unsigned char*)"squ", {226, 150, 161, 0}},
-{(unsigned char*)"square", {226, 150, 161, 0}},
-{(unsigned char*)"squarf", {226, 150, 170, 0}},
-{(unsigned char*)"squf", {226, 150, 170, 0}},
-{(unsigned char*)"srarr", {226, 134, 146, 0}},
-{(unsigned char*)"sscr", {240, 157, 147, 136, 0}},
-{(unsigned char*)"ssetmn", {226, 136, 150, 0}},
-{(unsigned char*)"ssmile", {226, 140, 163, 0}},
-{(unsigned char*)"sstarf", {226, 139, 134, 0}},
-{(unsigned char*)"star", {226, 152, 134, 0}},
-{(unsigned char*)"starf", {226, 152, 133, 0}},
-{(unsigned char*)"straightepsilon", {207, 181, 0}},
-{(unsigned char*)"straightphi", {207, 149, 0}},
-{(unsigned char*)"strns", {194, 175, 0}},
-{(unsigned char*)"sub", {226, 138, 130, 0}},
-{(unsigned char*)"subE", {226, 171, 133, 0}},
-{(unsigned char*)"subdot", {226, 170, 189, 0}},
-{(unsigned char*)"sube", {226, 138, 134, 0}},
-{(unsigned char*)"subedot", {226, 171, 131, 0}},
-{(unsigned char*)"submult", {226, 171, 129, 0}},
-{(unsigned char*)"subnE", {226, 171, 139, 0}},
-{(unsigned char*)"subne", {226, 138, 138, 0}},
-{(unsigned char*)"subplus", {226, 170, 191, 0}},
-{(unsigned char*)"subrarr", {226, 165, 185, 0}},
-{(unsigned char*)"subset", {226, 138, 130, 0}},
-{(unsigned char*)"subseteq", {226, 138, 134, 0}},
-{(unsigned char*)"subseteqq", {226, 171, 133, 0}},
-{(unsigned char*)"subsetneq", {226, 138, 138, 0}},
-{(unsigned char*)"subsetneqq", {226, 171, 139, 0}},
-{(unsigned char*)"subsim", {226, 171, 135, 0}},
-{(unsigned char*)"subsub", {226, 171, 149, 0}},
-{(unsigned char*)"subsup", {226, 171, 147, 0}},
-{(unsigned char*)"succ", {226, 137, 187, 0}},
-{(unsigned char*)"succapprox", {226, 170, 184, 0}},
-{(unsigned char*)"succcurlyeq", {226, 137, 189, 0}},
-{(unsigned char*)"succeq", {226, 170, 176, 0}},
-{(unsigned char*)"succnapprox", {226, 170, 186, 0}},
-{(unsigned char*)"succneqq", {226, 170, 182, 0}},
-{(unsigned char*)"succnsim", {226, 139, 169, 0}},
-{(unsigned char*)"succsim", {226, 137, 191, 0}},
-{(unsigned char*)"sum", {226, 136, 145, 0}},
-{(unsigned char*)"sung", {226, 153, 170, 0}},
-{(unsigned char*)"sup", {226, 138, 131, 0}},
-{(unsigned char*)"sup1", {194, 185, 0}},
-{(unsigned char*)"sup2", {194, 178, 0}},
-{(unsigned char*)"sup3", {194, 179, 0}},
-{(unsigned char*)"supE", {226, 171, 134, 0}},
-{(unsigned char*)"supdot", {226, 170, 190, 0}},
-{(unsigned char*)"supdsub", {226, 171, 152, 0}},
-{(unsigned char*)"supe", {226, 138, 135, 0}},
-{(unsigned char*)"supedot", {226, 171, 132, 0}},
-{(unsigned char*)"suphsol", {226, 159, 137, 0}},
-{(unsigned char*)"suphsub", {226, 171, 151, 0}},
-{(unsigned char*)"suplarr", {226, 165, 187, 0}},
-{(unsigned char*)"supmult", {226, 171, 130, 0}},
-{(unsigned char*)"supnE", {226, 171, 140, 0}},
-{(unsigned char*)"supne", {226, 138, 139, 0}},
-{(unsigned char*)"supplus", {226, 171, 128, 0}},
-{(unsigned char*)"supset", {226, 138, 131, 0}},
-{(unsigned char*)"supseteq", {226, 138, 135, 0}},
-{(unsigned char*)"supseteqq", {226, 171, 134, 0}},
-{(unsigned char*)"supsetneq", {226, 138, 139, 0}},
-{(unsigned char*)"supsetneqq", {226, 171, 140, 0}},
-{(unsigned char*)"supsim", {226, 171, 136, 0}},
-{(unsigned char*)"supsub", {226, 171, 148, 0}},
-{(unsigned char*)"supsup", {226, 171, 150, 0}},
-{(unsigned char*)"swArr", {226, 135, 153, 0}},
-{(unsigned char*)"swarhk", {226, 164, 166, 0}},
-{(unsigned char*)"swarr", {226, 134, 153, 0}},
-{(unsigned char*)"swarrow", {226, 134, 153, 0}},
-{(unsigned char*)"swnwar", {226, 164, 170, 0}},
-{(unsigned char*)"szlig", {195, 159, 0}},
-{(unsigned char*)"target", {226, 140, 150, 0}},
-{(unsigned char*)"tau", {207, 132, 0}},
-{(unsigned char*)"tbrk", {226, 142, 180, 0}},
-{(unsigned char*)"tcaron", {197, 165, 0}},
-{(unsigned char*)"tcedil", {197, 163, 0}},
-{(unsigned char*)"tcy", {209, 130, 0}},
-{(unsigned char*)"tdot", {226, 131, 155, 0}},
-{(unsigned char*)"telrec", {226, 140, 149, 0}},
-{(unsigned char*)"tfr", {240, 157, 148, 177, 0}},
-{(unsigned char*)"there4", {226, 136, 180, 0}},
-{(unsigned char*)"therefore", {226, 136, 180, 0}},
-{(unsigned char*)"theta", {206, 184, 0}},
-{(unsigned char*)"thetasym", {207, 145, 0}},
-{(unsigned char*)"thetav", {207, 145, 0}},
-{(unsigned char*)"thickapprox", {226, 137, 136, 0}},
-{(unsigned char*)"thicksim", {226, 136, 188, 0}},
-{(unsigned char*)"thinsp", {226, 128, 137, 0}},
-{(unsigned char*)"thkap", {226, 137, 136, 0}},
-{(unsigned char*)"thksim", {226, 136, 188, 0}},
-{(unsigned char*)"thorn", {195, 190, 0}},
-{(unsigned char*)"tilde", {203, 156, 0}},
-{(unsigned char*)"times", {195, 151, 0}},
-{(unsigned char*)"timesb", {226, 138, 160, 0}},
-{(unsigned char*)"timesbar", {226, 168, 177, 0}},
-{(unsigned char*)"timesd", {226, 168, 176, 0}},
-{(unsigned char*)"tint", {226, 136, 173, 0}},
-{(unsigned char*)"toea", {226, 164, 168, 0}},
-{(unsigned char*)"top", {226, 138, 164, 0}},
-{(unsigned char*)"topbot", {226, 140, 182, 0}},
-{(unsigned char*)"topcir", {226, 171, 177, 0}},
-{(unsigned char*)"topf", {240, 157, 149, 165, 0}},
-{(unsigned char*)"topfork", {226, 171, 154, 0}},
-{(unsigned char*)"tosa", {226, 164, 169, 0}},
-{(unsigned char*)"tprime", {226, 128, 180, 0}},
-{(unsigned char*)"trade", {226, 132, 162, 0}},
-{(unsigned char*)"triangle", {226, 150, 181, 0}},
-{(unsigned char*)"triangledown", {226, 150, 191, 0}},
-{(unsigned char*)"triangleleft", {226, 151, 131, 0}},
-{(unsigned char*)"trianglelefteq", {226, 138, 180, 0}},
-{(unsigned char*)"triangleq", {226, 137, 156, 0}},
-{(unsigned char*)"triangleright", {226, 150, 185, 0}},
-{(unsigned char*)"trianglerighteq", {226, 138, 181, 0}},
-{(unsigned char*)"tridot", {226, 151, 172, 0}},
-{(unsigned char*)"trie", {226, 137, 156, 0}},
-{(unsigned char*)"triminus", {226, 168, 186, 0}},
-{(unsigned char*)"triplus", {226, 168, 185, 0}},
-{(unsigned char*)"trisb", {226, 167, 141, 0}},
-{(unsigned char*)"tritime", {226, 168, 187, 0}},
-{(unsigned char*)"trpezium", {226, 143, 162, 0}},
-{(unsigned char*)"tscr", {240, 157, 147, 137, 0}},
-{(unsigned char*)"tscy", {209, 134, 0}},
-{(unsigned char*)"tshcy", {209, 155, 0}},
-{(unsigned char*)"tstrok", {197, 167, 0}},
-{(unsigned char*)"twixt", {226, 137, 172, 0}},
-{(unsigned char*)"twoheadleftarrow", {226, 134, 158, 0}},
-{(unsigned char*)"twoheadrightarrow", {226, 134, 160, 0}},
-{(unsigned char*)"uArr", {226, 135, 145, 0}},
-{(unsigned char*)"uHar", {226, 165, 163, 0}},
-{(unsigned char*)"uacute", {195, 186, 0}},
-{(unsigned char*)"uarr", {226, 134, 145, 0}},
-{(unsigned char*)"ubrcy", {209, 158, 0}},
-{(unsigned char*)"ubreve", {197, 173, 0}},
-{(unsigned char*)"ucirc", {195, 187, 0}},
-{(unsigned char*)"ucy", {209, 131, 0}},
-{(unsigned char*)"udarr", {226, 135, 133, 0}},
-{(unsigned char*)"udblac", {197, 177, 0}},
-{(unsigned char*)"udhar", {226, 165, 174, 0}},
-{(unsigned char*)"ufisht", {226, 165, 190, 0}},
-{(unsigned char*)"ufr", {240, 157, 148, 178, 0}},
-{(unsigned char*)"ugrave", {195, 185, 0}},
-{(unsigned char*)"uharl", {226, 134, 191, 0}},
-{(unsigned char*)"uharr", {226, 134, 190, 0}},
-{(unsigned char*)"uhblk", {226, 150, 128, 0}},
-{(unsigned char*)"ulcorn", {226, 140, 156, 0}},
-{(unsigned char*)"ulcorner", {226, 140, 156, 0}},
-{(unsigned char*)"ulcrop", {226, 140, 143, 0}},
-{(unsigned char*)"ultri", {226, 151, 184, 0}},
-{(unsigned char*)"umacr", {197, 171, 0}},
-{(unsigned char*)"uml", {194, 168, 0}},
-{(unsigned char*)"uogon", {197, 179, 0}},
-{(unsigned char*)"uopf", {240, 157, 149, 166, 0}},
-{(unsigned char*)"uparrow", {226, 134, 145, 0}},
-{(unsigned char*)"updownarrow", {226, 134, 149, 0}},
-{(unsigned char*)"upharpoonleft", {226, 134, 191, 0}},
-{(unsigned char*)"upharpoonright", {226, 134, 190, 0}},
-{(unsigned char*)"uplus", {226, 138, 142, 0}},
-{(unsigned char*)"upsi", {207, 133, 0}},
-{(unsigned char*)"upsih", {207, 146, 0}},
-{(unsigned char*)"upsilon", {207, 133, 0}},
-{(unsigned char*)"upuparrows", {226, 135, 136, 0}},
-{(unsigned char*)"urcorn", {226, 140, 157, 0}},
-{(unsigned char*)"urcorner", {226, 140, 157, 0}},
-{(unsigned char*)"urcrop", {226, 140, 142, 0}},
-{(unsigned char*)"uring", {197, 175, 0}},
-{(unsigned char*)"urtri", {226, 151, 185, 0}},
-{(unsigned char*)"uscr", {240, 157, 147, 138, 0}},
-{(unsigned char*)"utdot", {226, 139, 176, 0}},
-{(unsigned char*)"utilde", {197, 169, 0}},
-{(unsigned char*)"utri", {226, 150, 181, 0}},
-{(unsigned char*)"utrif", {226, 150, 180, 0}},
-{(unsigned char*)"uuarr", {226, 135, 136, 0}},
-{(unsigned char*)"uuml", {195, 188, 0}},
-{(unsigned char*)"uwangle", {226, 166, 167, 0}},
-{(unsigned char*)"vArr", {226, 135, 149, 0}},
-{(unsigned char*)"vBar", {226, 171, 168, 0}},
-{(unsigned char*)"vBarv", {226, 171, 169, 0}},
-{(unsigned char*)"vDash", {226, 138, 168, 0}},
-{(unsigned char*)"vangrt", {226, 166, 156, 0}},
-{(unsigned char*)"varepsilon", {207, 181, 0}},
-{(unsigned char*)"varkappa", {207, 176, 0}},
-{(unsigned char*)"varnothing", {226, 136, 133, 0}},
-{(unsigned char*)"varphi", {207, 149, 0}},
-{(unsigned char*)"varpi", {207, 150, 0}},
-{(unsigned char*)"varpropto", {226, 136, 157, 0}},
-{(unsigned char*)"varr", {226, 134, 149, 0}},
-{(unsigned char*)"varrho", {207, 177, 0}},
-{(unsigned char*)"varsigma", {207, 130, 0}},
-{(unsigned char*)"varsubsetneq", {226, 138, 138, 239, 184, 128, 0}},
-{(unsigned char*)"varsubsetneqq", {226, 171, 139, 239, 184, 128, 0}},
-{(unsigned char*)"varsupsetneq", {226, 138, 139, 239, 184, 128, 0}},
-{(unsigned char*)"varsupsetneqq", {226, 171, 140, 239, 184, 128, 0}},
-{(unsigned char*)"vartheta", {207, 145, 0}},
-{(unsigned char*)"vartriangleleft", {226, 138, 178, 0}},
-{(unsigned char*)"vartriangleright", {226, 138, 179, 0}},
-{(unsigned char*)"vcy", {208, 178, 0}},
-{(unsigned char*)"vdash", {226, 138, 162, 0}},
-{(unsigned char*)"vee", {226, 136, 168, 0}},
-{(unsigned char*)"veebar", {226, 138, 187, 0}},
-{(unsigned char*)"veeeq", {226, 137, 154, 0}},
-{(unsigned char*)"vellip", {226, 139, 174, 0}},
-{(unsigned char*)"verbar", {124, 0}},
-{(unsigned char*)"vert", {124, 0}},
-{(unsigned char*)"vfr", {240, 157, 148, 179, 0}},
-{(unsigned char*)"vltri", {226, 138, 178, 0}},
-{(unsigned char*)"vnsub", {226, 138, 130, 226, 131, 146, 0}},
-{(unsigned char*)"vnsup", {226, 138, 131, 226, 131, 146, 0}},
-{(unsigned char*)"vopf", {240, 157, 149, 167, 0}},
-{(unsigned char*)"vprop", {226, 136, 157, 0}},
-{(unsigned char*)"vrtri", {226, 138, 179, 0}},
-{(unsigned char*)"vscr", {240, 157, 147, 139, 0}},
-{(unsigned char*)"vsubnE", {226, 171, 139, 239, 184, 128, 0}},
-{(unsigned char*)"vsubne", {226, 138, 138, 239, 184, 128, 0}},
-{(unsigned char*)"vsupnE", {226, 171, 140, 239, 184, 128, 0}},
-{(unsigned char*)"vsupne", {226, 138, 139, 239, 184, 128, 0}},
-{(unsigned char*)"vzigzag", {226, 166, 154, 0}},
-{(unsigned char*)"wcirc", {197, 181, 0}},
-{(unsigned char*)"wedbar", {226, 169, 159, 0}},
-{(unsigned char*)"wedge", {226, 136, 167, 0}},
-{(unsigned char*)"wedgeq", {226, 137, 153, 0}},
-{(unsigned char*)"weierp", {226, 132, 152, 0}},
-{(unsigned char*)"wfr", {240, 157, 148, 180, 0}},
-{(unsigned char*)"wopf", {240, 157, 149, 168, 0}},
-{(unsigned char*)"wp", {226, 132, 152, 0}},
-{(unsigned char*)"wr", {226, 137, 128, 0}},
-{(unsigned char*)"wreath", {226, 137, 128, 0}},
-{(unsigned char*)"wscr", {240, 157, 147, 140, 0}},
-{(unsigned char*)"xcap", {226, 139, 130, 0}},
-{(unsigned char*)"xcirc", {226, 151, 175, 0}},
-{(unsigned char*)"xcup", {226, 139, 131, 0}},
-{(unsigned char*)"xdtri", {226, 150, 189, 0}},
-{(unsigned char*)"xfr", {240, 157, 148, 181, 0}},
-{(unsigned char*)"xhArr", {226, 159, 186, 0}},
-{(unsigned char*)"xharr", {226, 159, 183, 0}},
-{(unsigned char*)"xi", {206, 190, 0}},
-{(unsigned char*)"xlArr", {226, 159, 184, 0}},
-{(unsigned char*)"xlarr", {226, 159, 181, 0}},
-{(unsigned char*)"xmap", {226, 159, 188, 0}},
-{(unsigned char*)"xnis", {226, 139, 187, 0}},
-{(unsigned char*)"xodot", {226, 168, 128, 0}},
-{(unsigned char*)"xopf", {240, 157, 149, 169, 0}},
-{(unsigned char*)"xoplus", {226, 168, 129, 0}},
-{(unsigned char*)"xotime", {226, 168, 130, 0}},
-{(unsigned char*)"xrArr", {226, 159, 185, 0}},
-{(unsigned char*)"xrarr", {226, 159, 182, 0}},
-{(unsigned char*)"xscr", {240, 157, 147, 141, 0}},
-{(unsigned char*)"xsqcup", {226, 168, 134, 0}},
-{(unsigned char*)"xuplus", {226, 168, 132, 0}},
-{(unsigned char*)"xutri", {226, 150, 179, 0}},
-{(unsigned char*)"xvee", {226, 139, 129, 0}},
-{(unsigned char*)"xwedge", {226, 139, 128, 0}},
-{(unsigned char*)"yacute", {195, 189, 0}},
-{(unsigned char*)"yacy", {209, 143, 0}},
-{(unsigned char*)"ycirc", {197, 183, 0}},
-{(unsigned char*)"ycy", {209, 139, 0}},
-{(unsigned char*)"yen", {194, 165, 0}},
-{(unsigned char*)"yfr", {240, 157, 148, 182, 0}},
-{(unsigned char*)"yicy", {209, 151, 0}},
-{(unsigned char*)"yopf", {240, 157, 149, 170, 0}},
-{(unsigned char*)"yscr", {240, 157, 147, 142, 0}},
-{(unsigned char*)"yucy", {209, 142, 0}},
-{(unsigned char*)"yuml", {195, 191, 0}},
-{(unsigned char*)"zacute", {197, 186, 0}},
-{(unsigned char*)"zcaron", {197, 190, 0}},
-{(unsigned char*)"zcy", {208, 183, 0}},
-{(unsigned char*)"zdot", {197, 188, 0}},
-{(unsigned char*)"zeetrf", {226, 132, 168, 0}},
-{(unsigned char*)"zeta", {206, 182, 0}},
-{(unsigned char*)"zfr", {240, 157, 148, 183, 0}},
-{(unsigned char*)"zhcy", {208, 182, 0}},
-{(unsigned char*)"zigrarr", {226, 135, 157, 0}},
-{(unsigned char*)"zopf", {240, 157, 149, 171, 0}},
-{(unsigned char*)"zscr", {240, 157, 147, 143, 0}},
-{(unsigned char*)"zwj", {226, 128, 141, 0}},
-{(unsigned char*)"zwnj", {226, 128, 140, 0}},
-};
diff --git a/vendor/core/vendor/cmark-gfm/src/footnotes.c b/vendor/core/vendor/cmark-gfm/src/footnotes.c
deleted file mode 100644
index c2b745f79..000000000
--- a/vendor/core/vendor/cmark-gfm/src/footnotes.c
+++ /dev/null
@@ -1,63 +0,0 @@
-#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);
-}
-
-// Before calling `cmark_map_free` on a map with `cmark_footnotes`, first
-// unlink all of the footnote nodes before freeing their memory.
-//
-// Sometimes, two (unused) footnote nodes can end up referencing each other,
-// which as they get freed up by calling `cmark_map_free` -> `footnote_free` ->
-// etc, can lead to a use-after-free error.
-//
-// Better to `unlink` every footnote node first, setting their next, prev, and
-// parent pointers to NULL, and only then walk thru & free them up.
-void cmark_unlink_footnotes_map(cmark_map *map) {
-  cmark_map_entry *ref;
-  cmark_map_entry *next;
-
-  ref = map->refs;
-  while(ref) {
-    next = ref->next;
-    if (((cmark_footnote *)ref)->node) {
-      cmark_node_unlink(((cmark_footnote *)ref)->node);
-    }
-    ref = next;
-  }
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/footnotes.h b/vendor/core/vendor/cmark-gfm/src/footnotes.h
deleted file mode 100644
index 64e2901e3..000000000
--- a/vendor/core/vendor/cmark-gfm/src/footnotes.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#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);
-
-void cmark_unlink_footnotes_map(cmark_map *map);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/vendor/core/vendor/cmark-gfm/src/houdini.h b/vendor/core/vendor/cmark-gfm/src/houdini.h
deleted file mode 100644
index 7625b045b..000000000
--- a/vendor/core/vendor/cmark-gfm/src/houdini.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef CMARK_HOUDINI_H
-#define CMARK_HOUDINI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include 
-#include "config.h"
-#include "buffer.h"
-
-#ifdef HAVE___BUILTIN_EXPECT
-#define likely(x) __builtin_expect((x), 1)
-#define unlikely(x) __builtin_expect((x), 0)
-#else
-#define likely(x) (x)
-#define unlikely(x) (x)
-#endif
-
-#ifdef HOUDINI_USE_LOCALE
-#define _isxdigit(c) isxdigit(c)
-#define _isdigit(c) isdigit(c)
-#else
-/*
- * Helper _isdigit methods -- do not trust the current locale
- * */
-#define _isxdigit(c) (strchr("0123456789ABCDEFabcdef", (c)) != NULL)
-#define _isdigit(c) ((c) >= '0' && (c) <= '9')
-#endif
-
-#define HOUDINI_ESCAPED_SIZE(x) (((x)*12) / 10)
-#define HOUDINI_UNESCAPED_SIZE(x) (x)
-
-CMARK_GFM_EXPORT
-bufsize_t houdini_unescape_ent(cmark_strbuf *ob, const uint8_t *src,
-                                      bufsize_t size);
-CMARK_GFM_EXPORT
-int houdini_escape_html(cmark_strbuf *ob, const uint8_t *src,
-                               bufsize_t size);
-CMARK_GFM_EXPORT
-int houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src,
-                                bufsize_t size, int secure);
-CMARK_GFM_EXPORT
-int houdini_unescape_html(cmark_strbuf *ob, const uint8_t *src,
-                                 bufsize_t size);
-CMARK_GFM_EXPORT
-void houdini_unescape_html_f(cmark_strbuf *ob, const uint8_t *src,
-                                    bufsize_t size);
-CMARK_GFM_EXPORT
-int houdini_escape_href(cmark_strbuf *ob, const uint8_t *src,
-                               bufsize_t size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/vendor/core/vendor/cmark-gfm/src/houdini_href_e.c b/vendor/core/vendor/cmark-gfm/src/houdini_href_e.c
deleted file mode 100644
index 169389197..000000000
--- a/vendor/core/vendor/cmark-gfm/src/houdini_href_e.c
+++ /dev/null
@@ -1,100 +0,0 @@
-#include 
-#include 
-#include 
-
-#include "houdini.h"
-
-/*
- * The following characters will not be escaped:
- *
- *		-_.+!*'(),%#@?=;:/,+&$~ alphanum
- *
- * Note that this character set is the addition of:
- *
- *	- The characters which are safe to be in an URL
- *	- The characters which are *not* safe to be in
- *	an URL because they are RESERVED characters.
- *
- * We assume (lazily) that any RESERVED char that
- * appears inside an URL is actually meant to
- * have its native function (i.e. as an URL
- * component/separator) and hence needs no escaping.
- *
- * There are two exceptions: the chacters & (amp)
- * and ' (single quote) do not appear in the table.
- * They are meant to appear in the URL as components,
- * yet they require special HTML-entity escaping
- * to generate valid HTML markup.
- *
- * All other characters will be escaped to %XX.
- *
- */
-static const char HREF_SAFE[] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
-    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-int houdini_escape_href(cmark_strbuf *ob, const uint8_t *src, bufsize_t size) {
-  static const uint8_t hex_chars[] = "0123456789ABCDEF";
-  bufsize_t i = 0, org;
-  uint8_t hex_str[3];
-
-  hex_str[0] = '%';
-
-  while (i < size) {
-    org = i;
-    while (i < size && HREF_SAFE[src[i]] != 0)
-      i++;
-
-    if (likely(i > org))
-      cmark_strbuf_put(ob, src + org, i - org);
-
-    /* escaping */
-    if (i >= size)
-      break;
-
-    switch (src[i]) {
-    /* amp appears all the time in URLs, but needs
-     * HTML-entity escaping to be inside an href */
-    case '&':
-      cmark_strbuf_puts(ob, "&");
-      break;
-
-    /* the single quote is a valid URL character
-     * according to the standard; it needs HTML
-     * entity escaping too */
-    case '\'':
-      cmark_strbuf_puts(ob, "'");
-      break;
-
-/* the space can be escaped to %20 or a plus
- * sign. we're going with the generic escape
- * for now. the plus thing is more commonly seen
- * when building GET strings */
-#if 0
-		case ' ':
-			cmark_strbuf_putc(ob, '+');
-			break;
-#endif
-
-    /* every other character goes with a %XX escaping */
-    default:
-      hex_str[1] = hex_chars[(src[i] >> 4) & 0xF];
-      hex_str[2] = hex_chars[src[i] & 0xF];
-      cmark_strbuf_put(ob, hex_str, 3);
-    }
-
-    i++;
-  }
-
-  return 1;
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/houdini_html_e.c b/vendor/core/vendor/cmark-gfm/src/houdini_html_e.c
deleted file mode 100644
index da0b15c53..000000000
--- a/vendor/core/vendor/cmark-gfm/src/houdini_html_e.c
+++ /dev/null
@@ -1,66 +0,0 @@
-#include 
-#include 
-#include 
-
-#include "houdini.h"
-
-/**
- * According to the OWASP rules:
- *
- * & --> &
- * < --> <
- * > --> >
- * " --> "
- * ' --> '     ' is not recommended
- * / --> /     forward slash is included as it helps end an HTML entity
- *
- */
-static const char HTML_ESCAPE_TABLE[] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-static const char *HTML_ESCAPES[] = {"",      """, "&", "'",
-                                     "/", "<",   ">"};
-
-int houdini_escape_html0(cmark_strbuf *ob, const uint8_t *src, bufsize_t size,
-                         int secure) {
-  bufsize_t i = 0, org, esc = 0;
-
-  while (i < size) {
-    org = i;
-    while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0)
-      i++;
-
-    if (i > org)
-      cmark_strbuf_put(ob, src + org, i - org);
-
-    /* escaping */
-    if (unlikely(i >= size))
-      break;
-
-    /* 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 {
-      cmark_strbuf_puts(ob, HTML_ESCAPES[esc]);
-    }
-
-    i++;
-  }
-
-  return 1;
-}
-
-int houdini_escape_html(cmark_strbuf *ob, const uint8_t *src, bufsize_t size) {
-  return houdini_escape_html0(ob, src, size, 1);
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/houdini_html_u.c b/vendor/core/vendor/cmark-gfm/src/houdini_html_u.c
deleted file mode 100644
index 30d08aa4a..000000000
--- a/vendor/core/vendor/cmark-gfm/src/houdini_html_u.c
+++ /dev/null
@@ -1,149 +0,0 @@
-#include 
-#include 
-#include 
-
-#include "buffer.h"
-#include "houdini.h"
-#include "utf8.h"
-#include "entities.inc"
-
-/* Binary tree lookup code for entities added by JGM */
-
-static const unsigned char *S_lookup(int i, int low, int hi,
-                                     const unsigned char *s, int len) {
-  int j;
-  int cmp =
-      strncmp((const char *)s, (const char *)cmark_entities[i].entity, len);
-  if (cmp == 0 && cmark_entities[i].entity[len] == 0) {
-    return (const unsigned char *)cmark_entities[i].bytes;
-  } else if (cmp <= 0 && i > low) {
-    j = i - ((i - low) / 2);
-    if (j == i)
-      j -= 1;
-    return S_lookup(j, low, i - 1, s, len);
-  } else if (cmp > 0 && i < hi) {
-    j = i + ((hi - i) / 2);
-    if (j == i)
-      j += 1;
-    return S_lookup(j, i + 1, hi, s, len);
-  } else {
-    return NULL;
-  }
-}
-
-static const unsigned char *S_lookup_entity(const unsigned char *s, int len) {
-  return S_lookup(CMARK_NUM_ENTITIES / 2, 0, CMARK_NUM_ENTITIES - 1, s, len);
-}
-
-bufsize_t houdini_unescape_ent(cmark_strbuf *ob, const uint8_t *src,
-                               bufsize_t size) {
-  bufsize_t i = 0;
-
-  if (size >= 3 && src[0] == '#') {
-    int codepoint = 0;
-    int num_digits = 0;
-
-    if (_isdigit(src[1])) {
-      for (i = 1; i < size && _isdigit(src[i]); ++i) {
-        codepoint = (codepoint * 10) + (src[i] - '0');
-
-        if (codepoint >= 0x110000) {
-          // Keep counting digits but
-          // avoid integer overflow.
-          codepoint = 0x110000;
-        }
-      }
-
-      num_digits = i - 1;
-    }
-
-    else if (src[1] == 'x' || src[1] == 'X') {
-      for (i = 2; i < size && _isxdigit(src[i]); ++i) {
-        codepoint = (codepoint * 16) + ((src[i] | 32) % 39 - 9);
-
-        if (codepoint >= 0x110000) {
-          // Keep counting digits but
-          // avoid integer overflow.
-          codepoint = 0x110000;
-        }
-      }
-
-      num_digits = i - 2;
-    }
-
-    if (num_digits >= 1 && num_digits <= 8 && i < size && src[i] == ';') {
-      if (codepoint == 0 || (codepoint >= 0xD800 && codepoint < 0xE000) ||
-          codepoint >= 0x110000) {
-        codepoint = 0xFFFD;
-      }
-      cmark_utf8proc_encode_char(codepoint, ob);
-      return i + 1;
-    }
-  }
-
-  else {
-    if (size > CMARK_ENTITY_MAX_LENGTH)
-      size = CMARK_ENTITY_MAX_LENGTH;
-
-    for (i = CMARK_ENTITY_MIN_LENGTH; i < size; ++i) {
-      if (src[i] == ' ')
-        break;
-
-      if (src[i] == ';') {
-        const unsigned char *entity = S_lookup_entity(src, i);
-
-        if (entity != NULL) {
-          cmark_strbuf_puts(ob, (const char *)entity);
-          return i + 1;
-        }
-
-        break;
-      }
-    }
-  }
-
-  return 0;
-}
-
-int houdini_unescape_html(cmark_strbuf *ob, const uint8_t *src,
-                          bufsize_t size) {
-  bufsize_t i = 0, org, ent;
-
-  while (i < size) {
-    org = i;
-    while (i < size && src[i] != '&')
-      i++;
-
-    if (likely(i > org)) {
-      if (unlikely(org == 0)) {
-        if (i >= size)
-          return 0;
-
-        cmark_strbuf_grow(ob, HOUDINI_UNESCAPED_SIZE(size));
-      }
-
-      cmark_strbuf_put(ob, src + org, i - org);
-    }
-
-    /* escaping */
-    if (i >= size)
-      break;
-
-    i++;
-
-    ent = houdini_unescape_ent(ob, src + i, size - i);
-    i += ent;
-
-    /* not really an entity */
-    if (ent == 0)
-      cmark_strbuf_putc(ob, '&');
-  }
-
-  return 1;
-}
-
-void houdini_unescape_html_f(cmark_strbuf *ob, const uint8_t *src,
-                             bufsize_t size) {
-  if (!houdini_unescape_html(ob, src, size))
-    cmark_strbuf_put(ob, src, size);
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/html.c b/vendor/core/vendor/cmark-gfm/src/html.c
deleted file mode 100644
index 22513c939..000000000
--- a/vendor/core/vendor/cmark-gfm/src/html.c
+++ /dev/null
@@ -1,502 +0,0 @@
-#include 
-#include 
-#include 
-#include 
-#include "cmark_ctype.h"
-#include "config.h"
-#include "cmark-gfm.h"
-#include "houdini.h"
-#include "scanners.h"
-#include "syntax_extension.h"
-#include "html.h"
-#include "render.h"
-
-// Functions to convert cmark_nodes to HTML strings.
-
-static void escape_html(cmark_strbuf *dest, const unsigned char *source,
-                        bufsize_t length) {
-  houdini_escape_html0(dest, source, length, 0);
-}
-
-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;
-
-  while (len) {
-    match = (uint8_t *) memchr(data, '<', len);
-    if (!match)
-      break;
-
-    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 bool S_put_footnote_backref(cmark_html_renderer *renderer, cmark_strbuf *html, cmark_node *node) {
-  if (renderer->written_footnote_ix >= renderer->footnote_ix)
-    return false;
-  renderer->written_footnote_ix = renderer->footnote_ix;
-  char m[32];
-  snprintf(m, sizeof(m), "%d", renderer->written_footnote_ix);
-
-  cmark_strbuf_puts(html, "as.literal.data, node->as.literal.len);
-  cmark_strbuf_puts(html, "\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"");
-  cmark_strbuf_puts(html, m);
-  cmark_strbuf_puts(html, "\" aria-label=\"Back to reference ");
-  cmark_strbuf_puts(html, m);
-  cmark_strbuf_puts(html, "\">↩");
-
-  if (node->footnote.def_count > 1)
-  {
-    for(int i = 2; i <= node->footnote.def_count; i++) {
-      char n[32];
-      snprintf(n, sizeof(n), "%d", i);
-
-      cmark_strbuf_puts(html, " as.literal.data, node->as.literal.len);
-      cmark_strbuf_puts(html, "-");
-      cmark_strbuf_puts(html, n);
-      cmark_strbuf_puts(html, "\" class=\"footnote-backref\" data-footnote-backref data-footnote-backref-idx=\"");
-      cmark_strbuf_puts(html, m);
-      cmark_strbuf_puts(html, "-");
-      cmark_strbuf_puts(html, n);
-      cmark_strbuf_puts(html, "\" aria-label=\"Back to reference ");
-      cmark_strbuf_puts(html, m);
-      cmark_strbuf_puts(html, "-");
-      cmark_strbuf_puts(html, n);
-      cmark_strbuf_puts(html, "\">↩");
-      cmark_strbuf_puts(html, n);
-      cmark_strbuf_puts(html, "");
-    }
-  }
-
-  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 = renderer->html;
-  cmark_llist *it;
-  cmark_syntax_extension *ext;
-  char start_heading[] = "plain == node) { // back at original node
-    renderer->plain = NULL;
-  }
-
-  if (renderer->plain != NULL) {
-    switch (node->type) {
-    case CMARK_NODE_TEXT:
-    case CMARK_NODE_CODE:
-    case CMARK_NODE_HTML_INLINE:
-      escape_html(html, node->as.literal.data, node->as.literal.len);
-      break;
-
-    case CMARK_NODE_LINEBREAK:
-    case CMARK_NODE_SOFTBREAK:
-      cmark_strbuf_putc(html, ' ');
-      break;
-
-    default:
-      break;
-    }
-    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) {
-      cmark_html_render_cr(html);
-      cmark_strbuf_puts(html, "\n");
-    } else {
-      cmark_html_render_cr(html);
-      cmark_strbuf_puts(html, "\n");
-    }
-    break;
-
-  case CMARK_NODE_LIST: {
-    cmark_list_type list_type = node->as.list.list_type;
-    int start = node->as.list.start;
-
-    if (entering) {
-      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 { - cmark_strbuf_puts(html, - list_type == CMARK_BULLET_LIST ? "\n" : "
\n"); - } - break; - } - - case CMARK_NODE_ITEM: - if (entering) { - cmark_html_render_cr(html); - cmark_strbuf_puts(html, "'); - } else { - cmark_strbuf_puts(html, "\n"); - } - break; - - case CMARK_NODE_HEADING: - if (entering) { - cmark_html_render_cr(html); - start_heading[2] = (char)('0' + node->as.heading.level); - cmark_strbuf_puts(html, start_heading); - cmark_html_render_sourcepos(node, html, options); - cmark_strbuf_putc(html, '>'); - } else { - end_heading[3] = (char)('0' + node->as.heading.level); - cmark_strbuf_puts(html, end_heading); - cmark_strbuf_puts(html, ">\n"); - } - break; - - case CMARK_NODE_CODE_BLOCK: - cmark_html_render_cr(html); - - if (node->as.code.info.len == 0) { - cmark_strbuf_puts(html, ""); - } else { - bufsize_t first_tag = 0; - while (first_tag < node->as.code.info.len && - !cmark_isspace(node->as.code.info.data[first_tag])) { - first_tag += 1; - } - - 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); - cmark_strbuf_puts(html, "
\n"); - break; - - case CMARK_NODE_HTML_BLOCK: - 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); - } - cmark_html_render_cr(html); - break; - - case CMARK_NODE_CUSTOM_BLOCK: - cmark_html_render_cr(html); - if (entering) { - cmark_strbuf_put(html, node->as.custom.on_enter.data, - node->as.custom.on_enter.len); - } else { - cmark_strbuf_put(html, node->as.custom.on_exit.data, - node->as.custom.on_exit.len); - } - cmark_html_render_cr(html); - break; - - case CMARK_NODE_THEMATIC_BREAK: - cmark_html_render_cr(html); - cmark_strbuf_puts(html, "\n"); - break; - - case CMARK_NODE_PARAGRAPH: - parent = cmark_node_parent(node); - grandparent = cmark_node_parent(parent); - if (grandparent != NULL && grandparent->type == CMARK_NODE_LIST) { - tight = grandparent->as.list.tight; - } else { - tight = false; - } - if (!tight) { - if (entering) { - 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, parent); - } - cmark_strbuf_puts(html, "

\n"); - } - } - break; - - case CMARK_NODE_TEXT: - escape_html(html, node->as.literal.data, node->as.literal.len); - break; - - case CMARK_NODE_LINEBREAK: - cmark_strbuf_puts(html, "
\n"); - break; - - case CMARK_NODE_SOFTBREAK: - if (options & CMARK_OPT_HARDBREAKS) { - cmark_strbuf_puts(html, "
\n"); - } else if (options & CMARK_OPT_NOBREAKS) { - cmark_strbuf_putc(html, ' '); - } else { - cmark_strbuf_putc(html, '\n'); - } - break; - - case CMARK_NODE_CODE: - cmark_strbuf_puts(html, ""); - escape_html(html, node->as.literal.data, node->as.literal.len); - cmark_strbuf_puts(html, ""); - break; - - case CMARK_NODE_HTML_INLINE: - if (!(options & CMARK_OPT_UNSAFE)) { - cmark_strbuf_puts(html, ""); - } else { - 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; - - case CMARK_NODE_CUSTOM_INLINE: - if (entering) { - cmark_strbuf_put(html, node->as.custom.on_enter.data, - node->as.custom.on_enter.len); - } else { - cmark_strbuf_put(html, node->as.custom.on_exit.data, - node->as.custom.on_exit.len); - } - break; - - case CMARK_NODE_STRONG: - if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) { - if (entering) { - cmark_strbuf_puts(html, ""); - } else { - cmark_strbuf_puts(html, ""); - } - } - break; - - case CMARK_NODE_EMPH: - if (entering) { - cmark_strbuf_puts(html, ""); - } else { - cmark_strbuf_puts(html, ""); - } - break; - - case CMARK_NODE_LINK: - if (entering) { - cmark_strbuf_puts(html, "as.link.url, 0))) { - houdini_escape_href(html, node->as.link.url.data, - node->as.link.url.len); - } - if (node->as.link.title.len) { - cmark_strbuf_puts(html, "\" title=\""); - escape_html(html, node->as.link.title.data, node->as.link.title.len); - } - cmark_strbuf_puts(html, "\">"); - } else { - cmark_strbuf_puts(html, ""); - } - break; - - case CMARK_NODE_IMAGE: - if (entering) { - cmark_strbuf_puts(html, "as.link.url, 0))) { - houdini_escape_href(html, node->as.link.url.data, - node->as.link.url.len); - } - cmark_strbuf_puts(html, "\" alt=\""); - renderer->plain = node; - } else { - if (node->as.link.title.len) { - cmark_strbuf_puts(html, "\" title=\""); - escape_html(html, node->as.link.title.data, node->as.link.title.len); - } - - cmark_strbuf_puts(html, "\" />"); - } - break; - - 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. as.literal.data, node->as.literal.len); - cmark_strbuf_puts(html, "\">\n"); - } else { - if (S_put_footnote_backref(renderer, html, node)) { - cmark_strbuf_putc(html, '\n'); - } - cmark_strbuf_puts(html, "
  2. \n"); - } - break; - - case CMARK_NODE_FOOTNOTE_REFERENCE: - if (entering) { - cmark_strbuf_puts(html, "parent_footnote_def->as.literal.data, node->parent_footnote_def->as.literal.len); - cmark_strbuf_puts(html, "\" id=\"fnref-"); - houdini_escape_href(html, node->parent_footnote_def->as.literal.data, node->parent_footnote_def->as.literal.len); - - if (node->footnote.ref_ix > 1) { - char n[32]; - snprintf(n, sizeof(n), "%d", node->footnote.ref_ix); - cmark_strbuf_puts(html, "-"); - cmark_strbuf_puts(html, n); - } - - cmark_strbuf_puts(html, "\" data-footnote-ref>"); - houdini_escape_href(html, node->as.literal.data, node->as.literal.len); - cmark_strbuf_puts(html, ""); - } - break; - - default: - assert(false); - break; - } - - return 1; -} - -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(mem); - cmark_event_type ev_type; - cmark_node *cur; - 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(&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/vendor/core/vendor/cmark-gfm/src/html.h b/vendor/core/vendor/cmark-gfm/src/html.h deleted file mode 100644 index aeba7bcda..000000000 --- a/vendor/core/vendor/cmark-gfm/src/html.h +++ /dev/null @@ -1,27 +0,0 @@ -#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/vendor/core/vendor/cmark-gfm/src/inlines.c b/vendor/core/vendor/cmark-gfm/src/inlines.c deleted file mode 100644 index 30f2c1700..000000000 --- a/vendor/core/vendor/cmark-gfm/src/inlines.c +++ /dev/null @@ -1,1788 +0,0 @@ -#include -#include -#include - -#include "cmark_ctype.h" -#include "config.h" -#include "node.h" -#include "parser.h" -#include "references.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"; -static const char *ELLIPSES = "\xE2\x80\xA6"; -static const char *LEFTDOUBLEQUOTE = "\xE2\x80\x9C"; -static const char *RIGHTDOUBLEQUOTE = "\xE2\x80\x9D"; -static const char *LEFTSINGLEQUOTE = "\xE2\x80\x98"; -static const char *RIGHTSINGLEQUOTE = "\xE2\x80\x99"; - -// Macros for creating various kinds of simple. -#define make_str(subj, sc, ec, s) make_literal(subj, CMARK_NODE_TEXT, sc, ec, s) -#define make_code(subj, sc, ec, s) make_literal(subj, CMARK_NODE_CODE, sc, ec, s) -#define make_raw_html(subj, sc, ec, s) make_literal(subj, CMARK_NODE_HTML_INLINE, sc, ec, s) -#define make_linebreak(mem) make_simple(mem, CMARK_NODE_LINEBREAK) -#define make_softbreak(mem) make_simple(mem, CMARK_NODE_SOFTBREAK) -#define make_emph(mem) make_simple(mem, CMARK_NODE_EMPH) -#define make_strong(mem) make_simple(mem, CMARK_NODE_STRONG) - -#define MAXBACKTICKS 80 - -typedef struct bracket { - struct bracket *previous; - cmark_node *inl_text; - bufsize_t position; - bool image; - bool active; - bool bracket_after; - bool in_bracket_image0; - bool in_bracket_image1; -} bracket; - -#define FLAG_SKIP_HTML_CDATA (1u << 0) -#define FLAG_SKIP_HTML_DECLARATION (1u << 1) -#define FLAG_SKIP_HTML_PI (1u << 2) -#define FLAG_SKIP_HTML_COMMENT (1u << 3) - -typedef struct subject{ - cmark_mem *mem; - cmark_chunk input; - unsigned flags; - int line; - bufsize_t pos; - int block_offset; - int column_offset; - cmark_map *refmap; - delimiter *last_delim; - bracket *last_bracket; - bufsize_t backticks[MAXBACKTICKS + 1]; - bool scanned_for_backticks; - bool no_link_openers; -} subject; - -// Extensions may populate this. -static int8_t SKIP_CHARS[256]; - -static CMARK_INLINE bool S_is_line_end_char(char c) { - return (c == '\n' || c == '\r'); -} - -static delimiter *S_insert_emph(subject *subj, delimiter *opener, - delimiter *closer); - -static int parse_inline(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 *buffer, cmark_map *refmap); -static bufsize_t subject_find_special_char(subject *subj, int options); - -// Create an inline with a literal string value. -static CMARK_INLINE cmark_node *make_literal(subject *subj, cmark_node_type t, - int start_column, int end_column, - cmark_chunk s) { - cmark_node *e = (cmark_node *)subj->mem->calloc(1, sizeof(*e)); - cmark_strbuf_init(subj->mem, &e->content, 0); - e->type = (uint16_t)t; - e->as.literal = s; - e->start_line = e->end_line = subj->line; - // columns are 1 based. - e->start_column = start_column + 1 + subj->column_offset + subj->block_offset; - e->end_column = end_column + 1 + subj->column_offset + subj->block_offset; - return e; -} - -// Create an inline with no value. -static CMARK_INLINE cmark_node *make_simple(cmark_mem *mem, cmark_node_type t) { - cmark_node *e = (cmark_node *)mem->calloc(1, sizeof(*e)); - cmark_strbuf_init(mem, &e->content, 0); - e->type = (uint16_t)t; - return e; -} - -// Like make_str, but parses entities. -static cmark_node *make_str_with_entities(subject *subj, - int start_column, int end_column, - cmark_chunk *content) { - cmark_strbuf unescaped = CMARK_BUF_INIT(subj->mem); - - if (houdini_unescape_html(&unescaped, content->data, content->len)) { - return make_str(subj, start_column, end_column, cmark_chunk_buf_detach(&unescaped)); - } else { - return make_str(subj, start_column, end_column, *content); - } -} - -// Like cmark_node_append_child but without costly sanity checks. -// Assumes that child was newly created. -static void append_child(cmark_node *node, cmark_node *child) { - cmark_node *old_last_child = node->last_child; - - child->next = NULL; - child->prev = old_last_child; - child->parent = node; - node->last_child = child; - - if (old_last_child) { - old_last_child->next = child; - } else { - // Also set first_child if node previously had no children. - node->first_child = child; - } -} - -// Duplicate a chunk by creating a copy of the buffer not by reusing the -// buffer like cmark_chunk_dup does. -static cmark_chunk chunk_clone(cmark_mem *mem, cmark_chunk *src) { - cmark_chunk c; - bufsize_t len = src->len; - - c.len = len; - c.data = (unsigned char *)mem->calloc(len + 1, 1); - c.alloc = 1; - if (len) - memcpy(c.data, src->data, len); - c.data[len] = '\0'; - - return c; -} - -static cmark_chunk cmark_clean_autolink(cmark_mem *mem, cmark_chunk *url, - int is_email) { - cmark_strbuf buf = CMARK_BUF_INIT(mem); - - cmark_chunk_trim(url); - - if (url->len == 0) { - cmark_chunk result = CMARK_CHUNK_EMPTY; - return result; - } - - if (is_email) - cmark_strbuf_puts(&buf, "mailto:"); - - houdini_unescape_html_f(&buf, url->data, url->len); - return cmark_chunk_buf_detach(&buf); -} - -static CMARK_INLINE cmark_node *make_autolink(subject *subj, - int start_column, int end_column, - cmark_chunk url, int is_email) { - cmark_node *link = make_simple(subj->mem, CMARK_NODE_LINK); - link->as.link.url = cmark_clean_autolink(subj->mem, &url, is_email); - link->as.link.title = cmark_chunk_literal(""); - link->start_line = link->end_line = subj->line; - link->start_column = start_column + 1; - link->end_column = end_column + 1; - 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_map *refmap) { - int i; - e->mem = mem; - e->input = *chunk; - e->flags = 0; - e->line = line_number; - e->pos = 0; - e->block_offset = block_offset; - e->column_offset = 0; - e->refmap = refmap; - e->last_delim = NULL; - e->last_bracket = NULL; - for (i = 0; i <= MAXBACKTICKS; i++) { - e->backticks[i] = 0; - } - e->scanned_for_backticks = false; - e->no_link_openers = true; -} - -static CMARK_INLINE int isbacktick(int c) { return (c == '`'); } - -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 + 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) { - return subj->input.data[pos]; -} - -// Return true if there are more characters in the subject. -static CMARK_INLINE int is_eof(subject *subj) { - return (subj->pos >= subj->input.len); -} - -// Advance the subject. Doesn't check for eof. -#define advance(subj) (subj)->pos += 1 - -static CMARK_INLINE bool skip_spaces(subject *subj) { - bool skipped = false; - while (peek_char(subj) == ' ' || peek_char(subj) == '\t') { - advance(subj); - skipped = true; - } - return skipped; -} - -static CMARK_INLINE bool skip_line_end(subject *subj) { - bool seen_line_end_char = false; - if (peek_char(subj) == '\r') { - advance(subj); - seen_line_end_char = true; - } - if (peek_char(subj) == '\n') { - advance(subj); - seen_line_end_char = true; - } - return seen_line_end_char || is_eof(subj); -} - -// Take characters while a predicate holds, and return a string. -static CMARK_INLINE cmark_chunk take_while(subject *subj, int (*f)(int)) { - unsigned char c; - bufsize_t startpos = subj->pos; - bufsize_t len = 0; - - while ((c = peek_char(subj)) && (*f)(c)) { - advance(subj); - len++; - } - - return cmark_chunk_dup(&subj->input, startpos, len); -} - -// Return the number of newlines in a given span of text in a subject. If -// the number is greater than zero, also return the number of characters -// between the last newline and the end of the span in `since_newline`. -static int count_newlines(subject *subj, bufsize_t from, bufsize_t len, int *since_newline) { - int nls = 0; - int since_nl = 0; - - while (len--) { - if (subj->input.data[from++] == '\n') { - ++nls; - since_nl = 0; - } else { - ++since_nl; - } - } - - if (!nls) - return 0; - - *since_newline = since_nl; - return nls; -} - -// Adjust `node`'s `end_line`, `end_column`, and `subj`'s `line` and -// `column_offset` according to the number of newlines in a just-matched span -// of text in `subj`. -static void adjust_subj_node_newlines(subject *subj, cmark_node *node, int matchlen, int extra, int options) { - if (!(options & CMARK_OPT_SOURCEPOS)) { - return; - } - - int since_newline; - int newlines = count_newlines(subj, subj->pos - matchlen - extra, matchlen, &since_newline); - if (newlines) { - subj->line += newlines; - node->end_line += newlines; - node->end_column = since_newline; - subj->column_offset = -subj->pos + since_newline + extra; - } -} - -// Try to process a backtick code span that began with a -// span of ticks of length openticklength length (already -// parsed). Return 0 if you don't find matching closing -// backticks, otherwise return the position in the subject -// after the closing backticks. -static bufsize_t scan_to_closing_backticks(subject *subj, - bufsize_t openticklength) { - - bool found = false; - if (openticklength > MAXBACKTICKS) { - // we limit backtick string length because of the array subj->backticks: - return 0; - } - if (subj->scanned_for_backticks && - subj->backticks[openticklength] <= subj->pos) { - // return if we already know there's no closer - return 0; - } - while (!found) { - // read non backticks - unsigned char c; - while ((c = peek_char(subj)) && c != '`') { - advance(subj); - } - if (is_eof(subj)) { - break; - } - bufsize_t numticks = 0; - while (peek_char(subj) == '`') { - advance(subj); - numticks++; - } - // store position of ender - if (numticks <= MAXBACKTICKS) { - subj->backticks[numticks] = subj->pos - numticks; - } - if (numticks == openticklength) { - return (subj->pos); - } - } - // got through whole input without finding closer - subj->scanned_for_backticks = true; - return 0; -} - -// Destructively modify string, converting newlines to -// spaces, then removing a single leading + trailing space, -// unless the code span consists entirely of space characters. -static void S_normalize_code(cmark_strbuf *s) { - bufsize_t r, w; - bool contains_nonspace = false; - - for (r = 0, w = 0; r < s->size; ++r) { - switch (s->ptr[r]) { - case '\r': - if (s->ptr[r + 1] != '\n') { - s->ptr[w++] = ' '; - } - break; - case '\n': - s->ptr[w++] = ' '; - break; - default: - s->ptr[w++] = s->ptr[r]; - } - if (s->ptr[r] != ' ') { - contains_nonspace = true; - } - } - - // begins and ends with space? - if (contains_nonspace && - s->ptr[0] == ' ' && s->ptr[w - 1] == ' ') { - cmark_strbuf_drop(s, 1); - cmark_strbuf_truncate(s, w - 2); - } else { - cmark_strbuf_truncate(s, w); - } - -} - - -// Parse backtick code section or raw backticks, return an inline. -// Assumes that the subject has a backtick at the current position. -static cmark_node *handle_backticks(subject *subj, int options) { - cmark_chunk openticks = take_while(subj, isbacktick); - bufsize_t startpos = subj->pos; - bufsize_t endpos = scan_to_closing_backticks(subj, openticks.len); - - if (endpos == 0) { // not found - subj->pos = startpos; // rewind - return make_str(subj, subj->pos, subj->pos, openticks); - } else { - cmark_strbuf buf = CMARK_BUF_INIT(subj->mem); - - cmark_strbuf_set(&buf, subj->input.data + startpos, - endpos - startpos - openticks.len); - S_normalize_code(&buf); - - cmark_node *node = make_code(subj, startpos, endpos - openticks.len - 1, cmark_chunk_buf_detach(&buf)); - adjust_subj_node_newlines(subj, node, endpos - startpos, openticks.len, options); - return node; - } -} - - -// Scan ***, **, or * and return number scanned, or 0. -// Advances position. -static int scan_delims(subject *subj, unsigned char c, bool *can_open, - bool *can_close) { - int numdelims = 0; - bufsize_t before_char_pos, after_char_pos; - int32_t after_char = 0; - int32_t before_char = 0; - int len; - bool left_flanking, right_flanking; - - if (subj->pos == 0) { - before_char = 10; - } else { - before_char_pos = subj->pos - 1; - // walk back to the beginning of the UTF_8 sequence: - while ((peek_at(subj, before_char_pos) >> 6 == 2 || 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 || (before_char < 256 && SKIP_CHARS[(unsigned char) before_char])) { - before_char = 10; - } - } - - if (c == '\'' || c == '"') { - numdelims++; - advance(subj); // limit to 1 delim for quotes - } else { - while (peek_char(subj) == c) { - numdelims++; - advance(subj); - } - } - - if (subj->pos == subj->input.len) { - after_char = 10; - } else { - after_char_pos = subj->pos; - while (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 && 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) || - cmark_utf8proc_is_punctuation(before_char)); - right_flanking = numdelims > 0 && !cmark_utf8proc_is_space(before_char) && - (!cmark_utf8proc_is_punctuation(before_char) || - cmark_utf8proc_is_space(after_char) || - cmark_utf8proc_is_punctuation(after_char)); - if (c == '_') { - *can_open = left_flanking && - (!right_flanking || cmark_utf8proc_is_punctuation(before_char)); - *can_close = right_flanking && - (!left_flanking || cmark_utf8proc_is_punctuation(after_char)); - } else if (c == '\'' || c == '"') { - *can_open = left_flanking && !right_flanking && - before_char != ']' && before_char != ')'; - *can_close = right_flanking; - } else { - *can_open = left_flanking; - *can_close = right_flanking; - } - return numdelims; -} - -/* -static void print_delimiters(subject *subj) -{ - delimiter *delim; - delim = subj->last_delim; - while (delim != NULL) { - printf("Item at stack pos %p: %d %d %d next(%p) prev(%p)\n", - (void*)delim, delim->delim_char, - delim->can_open, delim->can_close, - (void*)delim->next, (void*)delim->previous); - delim = delim->previous; - } -} -*/ - -static void remove_delimiter(subject *subj, delimiter *delim) { - if (delim == NULL) - return; - if (delim->next == NULL) { - // end of list: - assert(delim == subj->last_delim); - subj->last_delim = delim->previous; - } else { - delim->next->previous = delim->previous; - } - if (delim->previous != NULL) { - delim->previous->next = delim->next; - } - subj->mem->free(delim); -} - -static void pop_bracket(subject *subj) { - bracket *b; - if (subj->last_bracket == NULL) - return; - b = subj->last_bracket; - subj->last_bracket = subj->last_bracket->previous; - subj->mem->free(b); -} - -static void push_delimiter(subject *subj, unsigned char c, bool can_open, - bool can_close, cmark_node *inl_text) { - delimiter *delim = (delimiter *)subj->mem->calloc(1, sizeof(delimiter)); - delim->delim_char = c; - delim->can_open = can_open; - delim->can_close = can_close; - delim->inl_text = inl_text; - delim->position = subj->pos; - delim->length = inl_text->as.literal.len; - delim->previous = subj->last_delim; - delim->next = NULL; - if (delim->previous != NULL) { - delim->previous->next = delim; - } - subj->last_delim = delim; -} - -static void push_bracket(subject *subj, bool image, cmark_node *inl_text) { - bracket *b = (bracket *)subj->mem->calloc(1, sizeof(bracket)); - if (subj->last_bracket != NULL) { - subj->last_bracket->bracket_after = true; - b->in_bracket_image0 = subj->last_bracket->in_bracket_image0; - b->in_bracket_image1 = subj->last_bracket->in_bracket_image1; - } - b->image = image; - b->active = true; - b->inl_text = inl_text; - b->previous = subj->last_bracket; - b->position = subj->pos; - b->bracket_after = false; - if (image) { - b->in_bracket_image1 = true; - } else { - b->in_bracket_image0 = true; - } - subj->last_bracket = b; - if (!image) { - subj->no_link_openers = false; - } -} - -// Assumes the subject has a c at the current position. -static cmark_node *handle_delim(subject *subj, unsigned char c, bool smart) { - bufsize_t numdelims; - cmark_node *inl_text; - bool can_open, can_close; - cmark_chunk contents; - - numdelims = scan_delims(subj, c, &can_open, &can_close); - - if (c == '\'' && smart) { - contents = cmark_chunk_literal(RIGHTSINGLEQUOTE); - } else if (c == '"' && smart) { - contents = - cmark_chunk_literal(can_close ? RIGHTDOUBLEQUOTE : LEFTDOUBLEQUOTE); - } else { - contents = cmark_chunk_dup(&subj->input, subj->pos - numdelims, numdelims); - } - - inl_text = make_str(subj, subj->pos - numdelims, subj->pos - 1, contents); - - if ((can_open || can_close) && (!(c == '\'' || c == '"') || smart)) { - push_delimiter(subj, c, can_open, can_close, inl_text); - } - - return inl_text; -} - -// Assumes we have a hyphen at the current position. -static cmark_node *handle_hyphen(subject *subj, bool smart) { - int startpos = subj->pos; - - advance(subj); - - if (!smart || peek_char(subj) != '-') { - return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("-")); - } - - while (smart && peek_char(subj) == '-') { - advance(subj); - } - - int numhyphens = subj->pos - startpos; - int en_count = 0; - int em_count = 0; - int i; - cmark_strbuf buf = CMARK_BUF_INIT(subj->mem); - - if (numhyphens % 3 == 0) { // if divisible by 3, use all em dashes - em_count = numhyphens / 3; - } else if (numhyphens % 2 == 0) { // if divisible by 2, use all en dashes - en_count = numhyphens / 2; - } else if (numhyphens % 3 == 2) { // use one en dash at end - en_count = 1; - em_count = (numhyphens - 2) / 3; - } else { // use two en dashes at the end - en_count = 2; - em_count = (numhyphens - 4) / 3; - } - - for (i = em_count; i > 0; i--) { - cmark_strbuf_puts(&buf, EMDASH); - } - - for (i = en_count; i > 0; i--) { - cmark_strbuf_puts(&buf, ENDASH); - } - - return make_str(subj, startpos, subj->pos - 1, cmark_chunk_buf_detach(&buf)); -} - -// Assumes we have a period at the current position. -static cmark_node *handle_period(subject *subj, bool smart) { - advance(subj); - if (smart && peek_char(subj) == '.') { - advance(subj); - if (peek_char(subj) == '.') { - advance(subj); - return make_str(subj, subj->pos - 3, subj->pos - 1, cmark_chunk_literal(ELLIPSES)); - } else { - return make_str(subj, subj->pos - 2, subj->pos - 1, cmark_chunk_literal("..")); - } - } else { - return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal(".")); - } -} - -static 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, bufsize_t stack_bottom) { - delimiter *candidate; - delimiter *closer = NULL; - delimiter *opener; - delimiter *old_closer; - bool opener_found; - bufsize_t 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. - candidate = subj->last_delim; - while (candidate != NULL && candidate->position >= stack_bottom) { - closer = candidate; - candidate = candidate->previous; - } - - // 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) { - // Now look backwards for first matching opener: - opener = closer->previous; - opener_found = false; - while (opener != NULL && opener->position >= stack_bottom && - opener->position >= 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 - if (!(closer->can_open || opener->can_close) || - closer->length % 3 == 0 || - (opener->length + closer->length) % 3 != 0) { - opener_found = true; - break; - } - } - opener = opener->previous; - } - old_closer = closer; - - 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 { - closer = closer->next; - } - } else if (closer->delim_char == '\'' || closer->delim_char == '"') { - cmark_chunk_free(subj->mem, &closer->inl_text->as.literal); - if (closer->delim_char == '\'') { - closer->inl_text->as.literal = cmark_chunk_literal(RIGHTSINGLEQUOTE); - } else { - closer->inl_text->as.literal = cmark_chunk_literal(RIGHTDOUBLEQUOTE); - } - closer = closer->next; - if (opener_found) { - cmark_chunk_free(subj->mem, &opener->inl_text->as.literal); - if (old_closer->delim_char == '\'') { - opener->inl_text->as.literal = cmark_chunk_literal(LEFTSINGLEQUOTE); - } else { - opener->inl_text->as.literal = cmark_chunk_literal(LEFTDOUBLEQUOTE); - } - remove_delimiter(subj, opener); - remove_delimiter(subj, old_closer); - } - } - if (!opener_found) { - // set lower bound for future searches for openers - openers_bottom[old_closer->length % 3][old_closer->delim_char] = - old_closer->position; - if (!old_closer->can_open) { - // we can remove a closer that can't be an - // opener, once we've seen there's no - // matching opener: - remove_delimiter(subj, old_closer); - } - } - } else { - closer = closer->next; - } - } - // free all delimiters in list until stack_bottom: - while (subj->last_delim != NULL && - subj->last_delim->position >= stack_bottom) { - remove_delimiter(subj, subj->last_delim); - } -} - -static delimiter *S_insert_emph(subject *subj, delimiter *opener, - delimiter *closer) { - delimiter *delim, *tmp_delim; - bufsize_t use_delims; - cmark_node *opener_inl = opener->inl_text; - cmark_node *closer_inl = closer->inl_text; - bufsize_t opener_num_chars = opener_inl->as.literal.len; - bufsize_t closer_num_chars = closer_inl->as.literal.len; - cmark_node *tmp, *tmpnext, *emph; - - // calculate the actual number of characters used from this closer - use_delims = (closer_num_chars >= 2 && opener_num_chars >= 2) ? 2 : 1; - - // remove used characters from associated inlines. - opener_num_chars -= use_delims; - closer_num_chars -= use_delims; - opener_inl->as.literal.len = opener_num_chars; - closer_inl->as.literal.len = closer_num_chars; - - // free delimiters between opener and closer - delim = closer->previous; - while (delim != NULL && delim != opener) { - tmp_delim = delim->previous; - remove_delimiter(subj, delim); - delim = tmp_delim; - } - - // create new emph or strong, and splice it in to our inlines - // between the opener and closer - emph = use_delims == 1 ? make_emph(subj->mem) : make_strong(subj->mem); - - tmp = opener_inl->next; - while (tmp && tmp != closer_inl) { - tmpnext = tmp->next; - cmark_node_unlink(tmp); - append_child(emph, tmp); - tmp = tmpnext; - } - cmark_node_insert_after(opener_inl, emph); - - emph->start_line = opener_inl->start_line; - emph->end_line = closer_inl->end_line; - emph->start_column = opener_inl->start_column; - emph->end_column = closer_inl->end_column; - - // if opener has 0 characters, remove it and its associated inline - if (opener_num_chars == 0) { - cmark_node_free(opener_inl); - remove_delimiter(subj, opener); - } - - // if closer has 0 characters, remove it and its associated inline - if (closer_num_chars == 0) { - // remove empty closer inline - cmark_node_free(closer_inl); - // remove closer from list - tmp_delim = closer->next; - remove_delimiter(subj, closer); - closer = tmp_delim; - } - - return closer; -} - -// Parse backslash-escape or just a backslash, returning an inline. -static cmark_node *handle_backslash(cmark_parser *parser, subject *subj) { - advance(subj); - unsigned char nextchar = peek_char(subj); - 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)) { - return make_linebreak(subj->mem); - } else { - return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("\\")); - } -} - -// Parse an entity or a regular "&" string. -// Assumes the subject has an '&' character at the current position. -static cmark_node *handle_entity(subject *subj) { - cmark_strbuf ent = CMARK_BUF_INIT(subj->mem); - bufsize_t len; - - advance(subj); - - len = houdini_unescape_ent(&ent, subj->input.data + subj->pos, - subj->input.len - subj->pos); - - if (len == 0) - return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("&")); - - subj->pos += len; - return make_str(subj, subj->pos - 1 - len, subj->pos - 1, cmark_chunk_buf_detach(&ent)); -} - -// Clean a URL: remove surrounding whitespace, and remove \ that escape -// punctuation. -cmark_chunk cmark_clean_url(cmark_mem *mem, cmark_chunk *url) { - cmark_strbuf buf = CMARK_BUF_INIT(mem); - - cmark_chunk_trim(url); - - if (url->len == 0) { - cmark_chunk result = CMARK_CHUNK_EMPTY; - return result; - } - - houdini_unescape_html_f(&buf, url->data, url->len); - - cmark_strbuf_unescape(&buf); - return cmark_chunk_buf_detach(&buf); -} - -cmark_chunk cmark_clean_title(cmark_mem *mem, cmark_chunk *title) { - cmark_strbuf buf = CMARK_BUF_INIT(mem); - unsigned char first, last; - - if (title->len == 0) { - cmark_chunk result = CMARK_CHUNK_EMPTY; - return result; - } - - first = title->data[0]; - last = title->data[title->len - 1]; - - // remove surrounding quotes if any: - if ((first == '\'' && last == '\'') || (first == '(' && last == ')') || - (first == '"' && last == '"')) { - houdini_unescape_html_f(&buf, title->data + 1, title->len - 2); - } else { - houdini_unescape_html_f(&buf, title->data, title->len); - } - - cmark_strbuf_unescape(&buf); - return cmark_chunk_buf_detach(&buf); -} - -// Parse an autolink or HTML tag. -// Assumes the subject has a '<' character at the current position. -static cmark_node *handle_pointy_brace(subject *subj, int options) { - bufsize_t matchlen = 0; - cmark_chunk contents; - - advance(subj); // advance past first < - - // first try to match a URL autolink - matchlen = scan_autolink_uri(&subj->input, subj->pos); - if (matchlen > 0) { - contents = cmark_chunk_dup(&subj->input, subj->pos, matchlen - 1); - subj->pos += matchlen; - - return make_autolink(subj, subj->pos - 1 - matchlen, subj->pos - 1, contents, 0); - } - - // next try to match an email autolink - matchlen = scan_autolink_email(&subj->input, subj->pos); - if (matchlen > 0) { - contents = cmark_chunk_dup(&subj->input, subj->pos, matchlen - 1); - subj->pos += matchlen; - - return make_autolink(subj, subj->pos - 1 - matchlen, subj->pos - 1, contents, 1); - } - - // finally, try to match an html tag - if (subj->pos + 2 <= subj->input.len) { - int c = subj->input.data[subj->pos]; - if (c == '!' && (subj->flags & FLAG_SKIP_HTML_COMMENT) == 0) { - c = subj->input.data[subj->pos+1]; - if (c == '-' && subj->input.data[subj->pos+2] == '-') { - if (subj->input.data[subj->pos+3] == '>') { - matchlen = 4; - } else if (subj->input.data[subj->pos+3] == '-' && - subj->input.data[subj->pos+4] == '>') { - matchlen = 5; - } else { - matchlen = scan_html_comment(&subj->input, subj->pos + 1); - if (matchlen > 0) { - matchlen += 1; // prefix "<" - } else { // no match through end of input: set a flag so - // we don't reparse looking for -->: - subj->flags |= FLAG_SKIP_HTML_COMMENT; - } - } - } else if (c == '[') { - if ((subj->flags & FLAG_SKIP_HTML_CDATA) == 0) { - matchlen = scan_html_cdata(&subj->input, subj->pos + 2); - if (matchlen > 0) { - // The regex doesn't require the final "]]>". But if we're not at - // the end of input, it must come after the match. Otherwise, - // disable subsequent scans to avoid quadratic behavior. - matchlen += 5; // prefix "![", suffix "]]>" - if (subj->pos + matchlen > subj->input.len) { - subj->flags |= FLAG_SKIP_HTML_CDATA; - matchlen = 0; - } - } - } - } else if ((subj->flags & FLAG_SKIP_HTML_DECLARATION) == 0) { - matchlen = scan_html_declaration(&subj->input, subj->pos + 1); - if (matchlen > 0) { - matchlen += 2; // prefix "!", suffix ">" - if (subj->pos + matchlen > subj->input.len) { - subj->flags |= FLAG_SKIP_HTML_DECLARATION; - matchlen = 0; - } - } - } - } else if (c == '?') { - if ((subj->flags & FLAG_SKIP_HTML_PI) == 0) { - // Note that we allow an empty match. - matchlen = scan_html_pi(&subj->input, subj->pos + 1); - matchlen += 3; // prefix "?", suffix "?>" - if (subj->pos + matchlen > subj->input.len) { - subj->flags |= FLAG_SKIP_HTML_PI; - matchlen = 0; - } - } - } else { - matchlen = scan_html_tag(&subj->input, subj->pos); - } - } - if (matchlen > 0) { - contents = cmark_chunk_dup(&subj->input, subj->pos - 1, matchlen + 1); - subj->pos += matchlen; - cmark_node *node = make_raw_html(subj, subj->pos - matchlen - 1, subj->pos - 1, contents); - adjust_subj_node_newlines(subj, node, matchlen, 1, options); - return node; - } - - if (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("<")); -} - -// Parse a link label. Returns 1 if successful. -// Note: unescaped brackets are not allowed in labels. -// The label begins with `[` and ends with the first `]` character -// encountered. Backticks in labels do not start code spans. -static int link_label(subject *subj, cmark_chunk *raw_label) { - bufsize_t startpos = subj->pos; - int length = 0; - unsigned char c; - - // advance past [ - if (peek_char(subj) == '[') { - advance(subj); - } else { - return 0; - } - - while ((c = peek_char(subj)) && c != '[' && c != ']') { - if (c == '\\') { - advance(subj); - length++; - if (cmark_ispunct(peek_char(subj))) { - advance(subj); - length++; - } - } else { - advance(subj); - length++; - } - if (length > MAX_LINK_LABEL_LENGTH) { - goto noMatch; - } - } - - if (c == ']') { // match found - *raw_label = - cmark_chunk_dup(&subj->input, startpos + 1, subj->pos - (startpos + 1)); - cmark_chunk_trim(raw_label); - advance(subj); // advance past ] - return 1; - } - -noMatch: - subj->pos = startpos; // rewind - return 0; -} - -static bufsize_t manual_scan_link_url_2(cmark_chunk *input, bufsize_t offset, - cmark_chunk *output) { - bufsize_t i = offset; - size_t nb_p = 0; - - while (i < input->len) { - if (input->data[i] == '\\' && - i + 1 < input-> len && - cmark_ispunct(input->data[i+1])) - i += 2; - else if (input->data[i] == '(') { - ++nb_p; - ++i; - if (nb_p > 32) - return -1; - } else if (input->data[i] == ')') { - if (nb_p == 0) - break; - --nb_p; - ++i; - } else if (cmark_isspace(input->data[i])) { - if (i == offset) { - return -1; - } - break; - } else { - ++i; - } - } - - if (i >= input->len) - return -1; - - { - cmark_chunk result = {input->data + offset, i - offset, 0}; - *output = result; - } - return i - offset; -} - -static bufsize_t manual_scan_link_url(cmark_chunk *input, bufsize_t offset, - cmark_chunk *output) { - bufsize_t i = offset; - - if (i < input->len && input->data[i] == '<') { - ++i; - while (i < input->len) { - if (input->data[i] == '>') { - ++i; - break; - } else if (input->data[i] == '\\') - i += 2; - else if (input->data[i] == '\n' || input->data[i] == '<') - return -1; - else - ++i; - } - } else { - return manual_scan_link_url_2(input, offset, output); - } - - if (i >= input->len) - return -1; - - { - cmark_chunk result = {input->data + offset + 1, i - 2 - offset, 0}; - *output = result; - } - return i - offset; -} - -// Return a link, an image, or a literal close bracket. -static cmark_node *handle_close_bracket(cmark_parser *parser, subject *subj) { - bufsize_t initial_pos, after_link_text_pos; - bufsize_t endurl, starttitle, endtitle, endall; - bufsize_t sps, n; - cmark_reference *ref = NULL; - cmark_chunk url_chunk, title_chunk; - cmark_chunk url, title; - bracket *opener; - cmark_node *inl; - cmark_chunk raw_label; - int found_label; - cmark_node *tmp, *tmpnext; - bool is_image; - - advance(subj); // advance past ] - initial_pos = subj->pos; - - // get last [ or ![ - opener = subj->last_bracket; - - if (opener == NULL) { - return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]")); - } - - // If 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; - - if (!is_image && subj->no_link_openers) { - // take delimiter off stack - pop_bracket(subj); - return make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("]")); - } - - after_link_text_pos = subj->pos; - - // First, look for an inline link. - if (peek_char(subj) == '(' && - ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) && - ((n = manual_scan_link_url(&subj->input, subj->pos + 1 + sps, - &url_chunk)) > -1)) { - - // try to parse an explicit link: - endurl = subj->pos + 1 + sps + n; - starttitle = endurl + scan_spacechars(&subj->input, endurl); - - // ensure there are spaces btw url and title - endtitle = (starttitle == endurl) - ? starttitle - : starttitle + scan_link_title(&subj->input, starttitle); - - endall = endtitle + scan_spacechars(&subj->input, endtitle); - - if (peek_at(subj, endall) == ')') { - subj->pos = endall + 1; - - title_chunk = - cmark_chunk_dup(&subj->input, starttitle, endtitle - starttitle); - url = cmark_clean_url(subj->mem, &url_chunk); - title = cmark_clean_title(subj->mem, &title_chunk); - cmark_chunk_free(subj->mem, &url_chunk); - cmark_chunk_free(subj->mem, &title_chunk); - goto match; - - } else { - // it could still be a shortcut reference link - subj->pos = after_link_text_pos; - } - } - - // Next, look for a following [link label] that matches in refmap. - // skip spaces - raw_label = cmark_chunk_literal(""); - found_label = link_label(subj, &raw_label); - if (!found_label) { - // If we have a shortcut reference link, back up - // to before the spacse we skipped. - subj->pos = initial_pos; - } - - if ((!found_label || raw_label.len == 0) && !opener->bracket_after) { - cmark_chunk_free(subj->mem, &raw_label); - raw_label = cmark_chunk_dup(&subj->input, opener->position, - initial_pos - opener->position - 1); - found_label = true; - } - - if (found_label) { - ref = (cmark_reference *)cmark_map_lookup(subj->refmap, &raw_label); - cmark_chunk_free(subj->mem, &raw_label); - } - - if (ref != NULL) { // found - url = chunk_clone(subj->mem, &ref->url); - title = chunk_clone(subj->mem, &ref->title); - goto match; - } else { - goto noMatch; - } - -noMatch: - // If we fall through to here, it means we didn't match a link. - // 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) { - - cmark_chunk *literal = &opener->inl_text->next->as.literal; - - // look back to the opening '[', and skip ahead to the next character - // if we're looking at a '[^' sequence, and there is other text or nodes - // after the ^, let's call it a footnote reference. - if ((literal->len > 0 && literal->data[0] == '^') && (literal->len > 1 || opener->inl_text->next->next)) { - - // Before we got this far, the `handle_close_bracket` function may have - // advanced the current state beyond our footnote's actual closing - // bracket, ie if it went looking for a `link_label`. - // Let's just rewind the subject's position: - subj->pos = initial_pos; - - cmark_node *fnref = make_simple(subj->mem, CMARK_NODE_FOOTNOTE_REFERENCE); - - // the start and end of the footnote ref is the opening and closing brace - // i.e. the subject's current position, and the opener's start_column - int fnref_end_column = subj->pos + subj->column_offset + subj->block_offset; - int fnref_start_column = opener->inl_text->start_column; - - // any given node delineates a substring of the line being processed, - // with the remainder of the line being pointed to thru its 'literal' - // struct member. - // here, we copy the literal's pointer, moving it past the '^' character - // for a length equal to the size of footnote reference text. - // i.e. end_col minus start_col, minus the [ and the ^ characters - // - // this copies the footnote reference string, even if between the - // `opener` and the subject's current position there are other nodes - // - // (first, check for underflows) - if ((fnref_start_column + 2) <= fnref_end_column) { - fnref->as.literal = cmark_chunk_dup(literal, 1, (fnref_end_column - fnref_start_column) - 2); - } else { - fnref->as.literal = cmark_chunk_dup(literal, 1, 0); - } - - fnref->start_line = fnref->end_line = subj->line; - fnref->start_column = fnref_start_column; - fnref->end_column = fnref_end_column; - - // we then replace the opener with this new fnref node, the net effect - // being replacing the opening '[' text node with a `^footnote-ref]` node. - cmark_node_insert_before(opener->inl_text, fnref); - - process_emphasis(parser, subj, opener->position); - // sometimes, the footnote reference text gets parsed into multiple nodes - // i.e. '[^example]' parsed into '[', '^exam', 'ple]'. - // this happens for ex with the autolink extension. when the autolinker - // finds the 'w' character, it will split the text into multiple nodes - // in hopes of being able to match a 'www.' substring. - // - // because this function is called one character at a time via the - // `parse_inlines` function, and the current subj->pos is pointing at the - // closing ] brace, and because we copy all the text between the [ ] - // braces, we should be able to safely ignore and delete any nodes after - // the opener->inl_text->next. - // - // therefore, here we walk thru the list and free them all up - cmark_node *next_node; - cmark_node *current_node = opener->inl_text->next; - while(current_node) { - next_node = current_node->next; - cmark_node_free(current_node); - current_node = next_node; - } - - cmark_node_free(opener->inl_text); - - 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("]")); - -match: - inl = make_simple(subj->mem, is_image ? CMARK_NODE_IMAGE : CMARK_NODE_LINK); - inl->as.link.url = url; - inl->as.link.title = title; - inl->start_line = inl->end_line = subj->line; - inl->start_column = opener->inl_text->start_column; - inl->end_column = subj->pos + subj->column_offset + subj->block_offset; - cmark_node_insert_before(opener->inl_text, inl); - // Add link text: - tmp = opener->inl_text->next; - while (tmp) { - tmpnext = tmp->next; - cmark_node_unlink(tmp); - append_child(inl, tmp); - tmp = tmpnext; - } - - // Free the bracket [: - cmark_node_free(opener->inl_text); - - process_emphasis(parser, subj, opener->position); - pop_bracket(subj); - - // Now, if we have a link, we also want to deactivate links until - // we get a new opener. (This code can be removed if we decide to allow links - // inside links.) - if (!is_image) { - subj->no_link_openers = true; - } - - return NULL; -} - -// Parse a hard or soft linebreak, returning an inline. -// Assumes the subject has a cr or newline at the current position. -static cmark_node *handle_newline(subject *subj) { - bufsize_t nlpos = subj->pos; - // skip over cr, crlf, or lf: - if (peek_at(subj, subj->pos) == '\r') { - advance(subj); - } - if (peek_at(subj, subj->pos) == '\n') { - advance(subj); - } - ++subj->line; - subj->column_offset = -subj->pos; - // skip spaces at beginning of line - skip_spaces(subj); - if (nlpos > 1 && peek_at(subj, nlpos - 1) == ' ' && - peek_at(subj, nlpos - 2) == ' ') { - return make_linebreak(subj->mem); - } else { - return make_softbreak(subj->mem); - } -} - -// "\r\n\\`&_*[]pos + 1; - - while (n < subj->input.len) { - if (SPECIAL_CHARS[subj->input.data[n]]) - return n; - if (options & CMARK_OPT_SMART && SMART_PUNCT_CHARS[subj->input.data[n]]) - return n; - n++; - } - - return subj->input.len; -} - -void cmark_inlines_add_special_character(unsigned char c, bool emphasis) { - SPECIAL_CHARS[c] = 1; - if (emphasis) - SKIP_CHARS[c] = 1; -} - -void cmark_inlines_remove_special_character(unsigned char c, bool emphasis) { - SPECIAL_CHARS[c] = 0; - if (emphasis) - 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(cmark_parser *parser, subject *subj, cmark_node *parent, int options) { - cmark_node *new_inl = NULL; - cmark_chunk contents; - unsigned char c; - bufsize_t startpos, endpos; - c = peek_char(subj); - if (c == 0) { - return 0; - } - switch (c) { - case '\r': - case '\n': - new_inl = handle_newline(subj); - break; - case '`': - new_inl = handle_backticks(subj, options); - break; - case '\\': - new_inl = handle_backslash(parser, subj); - break; - case '&': - new_inl = handle_entity(subj); - break; - case '<': - new_inl = handle_pointy_brace(subj, options); - break; - case '*': - case '_': - case '\'': - case '"': - new_inl = handle_delim(subj, c, (options & CMARK_OPT_SMART) != 0); - break; - case '-': - new_inl = handle_hyphen(subj, (options & CMARK_OPT_SMART) != 0); - break; - case '.': - new_inl = handle_period(subj, (options & CMARK_OPT_SMART) != 0); - break; - case '[': - advance(subj); - new_inl = make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("[")); - push_bracket(subj, false, new_inl); - break; - case ']': - new_inl = handle_close_bracket(parser, subj); - break; - case '!': - advance(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); - } else { - new_inl = make_str(subj, subj->pos - 1, subj->pos - 1, cmark_chunk_literal("!")); - } - break; - default: - new_inl = try_extensions(parser, parent, c, subj); - if (new_inl != NULL) - break; - - endpos = subject_find_special_char(subj, options); - contents = cmark_chunk_dup(&subj->input, subj->pos, endpos - subj->pos); - startpos = subj->pos; - subj->pos = endpos; - - // if we're at a newline, strip trailing spaces. - if (S_is_line_end_char(peek_char(subj))) { - cmark_chunk_rtrim(&contents); - } - - new_inl = make_str(subj, startpos, endpos - 1, contents); - } - if (new_inl != NULL) { - append_child(parent, new_inl); - } - - return 1; -} - -// Parse inlines from parent's string_content, adding as children of parent. -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(parser->mem, parent->start_line, parent->start_column - 1 + parent->internal_offset, &subj, &content, refmap); - cmark_chunk_rtrim(&subj.input); - - while (!is_eof(&subj) && parse_inline(parser, &subj, parent, options)) - ; - - process_emphasis(parser, &subj, 0); - // free bracket and delim stack - while (subj.last_delim) { - remove_delimiter(&subj, subj.last_delim); - } - while (subj.last_bracket) { - pop_bracket(&subj); - } -} - -// Parse zero or more space characters, including at most one newline. -static void spnl(subject *subj) { - skip_spaces(subj); - if (skip_line_end(subj)) { - skip_spaces(subj); - } -} - -// Parse reference. Assumes string begins with '[' character. -// Modify refmap if a reference is encountered. -// Return 0 if no reference found, otherwise position of subject -// after reference is parsed. -bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input, - cmark_map *refmap) { - subject subj; - - cmark_chunk lab; - cmark_chunk url; - cmark_chunk title; - - bufsize_t matchlen = 0; - bufsize_t beforetitle; - - subject_from_buf(mem, -1, 0, &subj, input, NULL); - - // parse label: - if (!link_label(&subj, &lab) || lab.len == 0) - return 0; - - // colon: - if (peek_char(&subj) == ':') { - advance(&subj); - } else { - return 0; - } - - // parse link url: - spnl(&subj); - if ((matchlen = manual_scan_link_url(&subj.input, subj.pos, &url)) > -1) { - subj.pos += matchlen; - } else { - return 0; - } - - // parse optional link_title - beforetitle = subj.pos; - spnl(&subj); - matchlen = subj.pos == beforetitle ? 0 : scan_link_title(&subj.input, subj.pos); - if (matchlen) { - title = cmark_chunk_dup(&subj.input, subj.pos, matchlen); - subj.pos += matchlen; - } else { - subj.pos = beforetitle; - title = cmark_chunk_literal(""); - } - - // parse final spaces and newline: - skip_spaces(&subj); - if (!skip_line_end(&subj)) { - if (matchlen) { // try rewinding before title - subj.pos = beforetitle; - skip_spaces(&subj); - if (!skip_line_end(&subj)) { - return 0; - } - } else { - return 0; - } - } - // insert reference into refmap - cmark_reference_create(refmap, &lab, &url, &title); - return subj.pos; -} - -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 image) { - bracket *b = parser->last_bracket; - if (!b) { - return 0; - } - if (image != 0) { - return b->in_bracket_image1; - } else { - return b->in_bracket_image0; - } -} - -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/vendor/core/vendor/cmark-gfm/src/inlines.h b/vendor/core/vendor/cmark-gfm/src/inlines.h deleted file mode 100644 index 7dd91bf52..000000000 --- a/vendor/core/vendor/cmark-gfm/src/inlines.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef CMARK_INLINES_H -#define CMARK_INLINES_H - -#ifdef __cplusplus -extern "C" { -#endif - -#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_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); - -void cmark_inlines_add_special_character(unsigned char c, bool emphasis); -void cmark_inlines_remove_special_character(unsigned char c, bool emphasis); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/core/vendor/cmark-gfm/src/iterator.c b/vendor/core/vendor/cmark-gfm/src/iterator.c deleted file mode 100644 index 13fdb7616..000000000 --- a/vendor/core/vendor/cmark-gfm/src/iterator.c +++ /dev/null @@ -1,159 +0,0 @@ -#include -#include - -#include "config.h" -#include "node.h" -#include "cmark-gfm.h" -#include "iterator.h" - -cmark_iter *cmark_iter_new(cmark_node *root) { - if (root == NULL) { - return NULL; - } - cmark_mem *mem = root->content.mem; - cmark_iter *iter = (cmark_iter *)mem->calloc(1, sizeof(cmark_iter)); - iter->mem = mem; - iter->root = root; - iter->cur.ev_type = CMARK_EVENT_NONE; - iter->cur.node = NULL; - iter->next.ev_type = CMARK_EVENT_ENTER; - iter->next.node = root; - return iter; -} - -void cmark_iter_free(cmark_iter *iter) { iter->mem->free(iter); } - -static bool S_is_leaf(cmark_node *node) { - 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) { - cmark_event_type ev_type = iter->next.ev_type; - cmark_node *node = iter->next.node; - - iter->cur.ev_type = ev_type; - iter->cur.node = node; - - if (ev_type == CMARK_EVENT_DONE) { - return ev_type; - } - - /* roll forward to next item, setting both fields */ - if (ev_type == CMARK_EVENT_ENTER && !S_is_leaf(node)) { - if (node->first_child == NULL) { - /* stay on this node but exit */ - iter->next.ev_type = CMARK_EVENT_EXIT; - } else { - iter->next.ev_type = CMARK_EVENT_ENTER; - iter->next.node = node->first_child; - } - } else if (node == iter->root) { - /* don't move past root */ - iter->next.ev_type = CMARK_EVENT_DONE; - iter->next.node = NULL; - } else if (node->next) { - iter->next.ev_type = CMARK_EVENT_ENTER; - iter->next.node = node->next; - } else if (node->parent) { - iter->next.ev_type = CMARK_EVENT_EXIT; - iter->next.node = node->parent; - } else { - assert(false); - iter->next.ev_type = CMARK_EVENT_DONE; - iter->next.node = NULL; - } - - return ev_type; -} - -void cmark_iter_reset(cmark_iter *iter, cmark_node *current, - cmark_event_type event_type) { - iter->next.ev_type = event_type; - iter->next.node = current; - cmark_iter_next(iter); -} - -cmark_node *cmark_iter_get_node(cmark_iter *iter) { return iter->cur.node; } - -cmark_event_type cmark_iter_get_event_type(cmark_iter *iter) { - return iter->cur.ev_type; -} - -cmark_node *cmark_iter_get_root(cmark_iter *iter) { return iter->root; } - -void cmark_consolidate_text_nodes(cmark_node *root) { - if (root == NULL) { - return; - } - cmark_iter *iter = cmark_iter_new(root); - cmark_strbuf buf = CMARK_BUF_INIT(iter->mem); - cmark_event_type ev_type; - cmark_node *cur, *tmp, *next; - - while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) { - cur = cmark_iter_get_node(iter); - if (ev_type == CMARK_EVENT_ENTER && cur->type == CMARK_NODE_TEXT && - cur->next && cur->next->type == CMARK_NODE_TEXT) { - cmark_strbuf_clear(&buf); - cmark_strbuf_put(&buf, cur->as.literal.data, cur->as.literal.len); - tmp = cur->next; - while (tmp && tmp->type == CMARK_NODE_TEXT) { - cmark_iter_next(iter); // advance pointer - cmark_strbuf_put(&buf, tmp->as.literal.data, tmp->as.literal.len); - cur->end_column = tmp->end_column; - next = tmp->next; - cmark_node_free(tmp); - tmp = next; - } - cmark_chunk_free(iter->mem, &cur->as.literal); - cur->as.literal = cmark_chunk_buf_detach(&buf); - } - } - - cmark_strbuf_free(&buf); - cmark_iter_free(iter); -} - -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/vendor/core/vendor/cmark-gfm/src/iterator.h b/vendor/core/vendor/cmark-gfm/src/iterator.h deleted file mode 100644 index 47e10e57b..000000000 --- a/vendor/core/vendor/cmark-gfm/src/iterator.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef CMARK_ITERATOR_H -#define CMARK_ITERATOR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "cmark-gfm.h" - -typedef struct { - cmark_event_type ev_type; - cmark_node *node; -} cmark_iter_state; - -struct cmark_iter { - cmark_mem *mem; - cmark_node *root; - cmark_iter_state cur; - cmark_iter_state next; -}; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/vendor/core/vendor/cmark-gfm/src/latex.c b/vendor/core/vendor/cmark-gfm/src/latex.c deleted file mode 100644 index 1a6367a4e..000000000 --- a/vendor/core/vendor/cmark-gfm/src/latex.c +++ /dev/null @@ -1,468 +0,0 @@ -#include -#include -#include -#include - -#include "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, 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_node *node, - cmark_escaping escape, - int32_t c, unsigned char nextc) { - if (escape == LITERAL) { - cmark_render_code_point(renderer, c); - return; - } - - switch (c) { - case 123: // '{' - case 125: // '}' - case 35: // '#' - case 37: // '%' - case 38: // '&' - cmark_render_ascii(renderer, "\\"); - cmark_render_code_point(renderer, c); - break; - case 36: // '$' - case 95: // '_' - if (escape == NORMAL) { - cmark_render_ascii(renderer, "\\"); - } - cmark_render_code_point(renderer, c); - break; - case 45: // '-' - if (nextc == 45) { // prevent ligature - cmark_render_ascii(renderer, "-{}"); - } else { - cmark_render_ascii(renderer, "-"); - } - break; - case 126: // '~' - if (escape == NORMAL) { - cmark_render_ascii(renderer, "\\textasciitilde{}"); - } else { - cmark_render_code_point(renderer, c); - } - break; - case 94: // '^' - cmark_render_ascii(renderer, "\\^{}"); - break; - case 92: // '\\' - if (escape == URL) { - // / acts as path sep even on windows: - cmark_render_ascii(renderer, "/"); - } else { - cmark_render_ascii(renderer, "\\textbackslash{}"); - } - break; - case 124: // '|' - cmark_render_ascii(renderer, "\\textbar{}"); - break; - case 60: // '<' - cmark_render_ascii(renderer, "\\textless{}"); - break; - case 62: // '>' - cmark_render_ascii(renderer, "\\textgreater{}"); - break; - case 91: // '[' - case 93: // ']' - cmark_render_ascii(renderer, "{"); - cmark_render_code_point(renderer, c); - cmark_render_ascii(renderer, "}"); - break; - case 34: // '"' - cmark_render_ascii(renderer, "\\textquotedbl{}"); - // requires \usepackage[T1]{fontenc} - break; - case 39: // '\'' - cmark_render_ascii(renderer, "\\textquotesingle{}"); - // requires \usepackage{textcomp} - break; - case 160: // nbsp - cmark_render_ascii(renderer, "~"); - break; - case 8230: // hellip - cmark_render_ascii(renderer, "\\ldots{}"); - break; - case 8216: // lsquo - if (escape == NORMAL) { - cmark_render_ascii(renderer, "`"); - } else { - cmark_render_code_point(renderer, c); - } - break; - case 8217: // rsquo - if (escape == NORMAL) { - cmark_render_ascii(renderer, "\'"); - } else { - cmark_render_code_point(renderer, c); - } - break; - case 8220: // ldquo - if (escape == NORMAL) { - cmark_render_ascii(renderer, "``"); - } else { - cmark_render_code_point(renderer, c); - } - break; - case 8221: // rdquo - if (escape == NORMAL) { - cmark_render_ascii(renderer, "''"); - } else { - cmark_render_code_point(renderer, c); - } - break; - case 8212: // emdash - if (escape == NORMAL) { - cmark_render_ascii(renderer, "---"); - } else { - cmark_render_code_point(renderer, c); - } - break; - case 8211: // endash - if (escape == NORMAL) { - cmark_render_ascii(renderer, "--"); - } else { - cmark_render_code_point(renderer, c); - } - break; - default: - cmark_render_code_point(renderer, c); - } -} - -typedef enum { - NO_LINK, - URL_AUTOLINK, - EMAIL_AUTOLINK, - NORMAL_LINK, - INTERNAL_LINK -} link_type; - -static link_type get_link_type(cmark_node *node) { - size_t title_len, url_len; - cmark_node *link_text; - char *realurl; - int realurllen; - bool isemail = false; - - if (node->type != CMARK_NODE_LINK) { - return NO_LINK; - } - - const char *url = cmark_node_get_url(node); - cmark_chunk url_chunk = cmark_chunk_literal(url); - - if (url && *url == '#') { - return INTERNAL_LINK; - } - - url_len = strlen(url); - if (url_len == 0 || scan_scheme(&url_chunk, 0) == 0) { - return NO_LINK; - } - - const char *title = cmark_node_get_title(node); - title_len = strlen(title); - // if it has a title, we can't treat it as an autolink: - if (title_len == 0) { - - link_text = node->first_child; - cmark_consolidate_text_nodes(link_text); - - if (!link_text) - return NO_LINK; - - realurl = (char *)url; - realurllen = (int)url_len; - if (strncmp(realurl, "mailto:", 7) == 0) { - realurl += 7; - realurllen -= 7; - isemail = true; - } - if (realurllen == link_text->as.literal.len && - strncmp(realurl, (char *)link_text->as.literal.data, - link_text->as.literal.len) == 0) { - if (isemail) { - return EMAIL_AUTOLINK; - } else { - return URL_AUTOLINK; - } - } - } - - return NORMAL_LINK; -} - -static int S_get_enumlevel(cmark_node *node) { - int enumlevel = 0; - cmark_node *tmp = node; - while (tmp) { - if (tmp->type == CMARK_NODE_LIST && - cmark_node_get_list_type(node) == CMARK_ORDERED_LIST) { - enumlevel++; - } - tmp = tmp->parent; - } - return enumlevel; -} - -static int S_render_node(cmark_renderer *renderer, cmark_node *node, - cmark_event_type ev_type, int options) { - int list_number; - int enumlevel; - char list_number_string[LIST_NUMBER_STRING_SIZE]; - bool entering = (ev_type == CMARK_EVENT_ENTER); - cmark_list_type list_type; - bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options); - - 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: - break; - - case CMARK_NODE_BLOCK_QUOTE: - if (entering) { - LIT("\\begin{quote}"); - CR(); - } else { - LIT("\\end{quote}"); - BLANKLINE(); - } - break; - - case CMARK_NODE_LIST: - list_type = cmark_node_get_list_type(node); - if (entering) { - LIT("\\begin{"); - LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize"); - LIT("}"); - CR(); - list_number = cmark_node_get_list_start(node); - if (list_number > 1) { - enumlevel = S_get_enumlevel(node); - // latex normally supports only five levels - if (enumlevel >= 1 && enumlevel <= 5) { - snprintf(list_number_string, LIST_NUMBER_STRING_SIZE, "%d", - list_number); - LIT("\\setcounter{enum"); - switch (enumlevel) { - case 1: LIT("i"); break; - case 2: LIT("ii"); break; - case 3: LIT("iii"); break; - case 4: LIT("iv"); break; - case 5: LIT("v"); break; - default: LIT("i"); break; - } - LIT("}{"); - OUT(list_number_string, false, NORMAL); - LIT("}"); - } - CR(); - } - } else { - LIT("\\end{"); - LIT(list_type == CMARK_ORDERED_LIST ? "enumerate" : "itemize"); - LIT("}"); - BLANKLINE(); - } - break; - - case CMARK_NODE_ITEM: - if (entering) { - LIT("\\item "); - } else { - CR(); - } - break; - - case CMARK_NODE_HEADING: - if (entering) { - switch (cmark_node_get_heading_level(node)) { - case 1: - LIT("\\section"); - break; - case 2: - LIT("\\subsection"); - break; - case 3: - LIT("\\subsubsection"); - break; - case 4: - LIT("\\paragraph"); - break; - case 5: - LIT("\\subparagraph"); - break; - } - LIT("{"); - } else { - LIT("}"); - BLANKLINE(); - } - break; - - case CMARK_NODE_CODE_BLOCK: - CR(); - LIT("\\begin{verbatim}"); - CR(); - OUT(cmark_node_get_literal(node), false, LITERAL); - CR(); - LIT("\\end{verbatim}"); - BLANKLINE(); - break; - - case CMARK_NODE_HTML_BLOCK: - break; - - case CMARK_NODE_CUSTOM_BLOCK: - CR(); - OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), - false, LITERAL); - CR(); - break; - - case CMARK_NODE_THEMATIC_BREAK: - BLANKLINE(); - LIT("\\begin{center}\\rule{0.5\\linewidth}{\\linethickness}\\end{center}"); - BLANKLINE(); - break; - - case CMARK_NODE_PARAGRAPH: - if (!entering) { - BLANKLINE(); - } - break; - - case CMARK_NODE_TEXT: - OUT(cmark_node_get_literal(node), allow_wrap, NORMAL); - break; - - case CMARK_NODE_LINEBREAK: - LIT("\\\\"); - CR(); - break; - - case CMARK_NODE_SOFTBREAK: - if (options & CMARK_OPT_HARDBREAKS) { - LIT("\\\\"); - CR(); - } else if (renderer->width == 0 && !(CMARK_OPT_NOBREAKS & options)) { - CR(); - } else { - OUT(" ", allow_wrap, NORMAL); - } - break; - - case CMARK_NODE_CODE: - LIT("\\texttt{"); - OUT(cmark_node_get_literal(node), false, NORMAL); - LIT("}"); - break; - - case CMARK_NODE_HTML_INLINE: - break; - - case CMARK_NODE_CUSTOM_INLINE: - OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node), - false, LITERAL); - break; - - case CMARK_NODE_STRONG: - if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) { - if (entering) { - LIT("\\textbf{"); - } else { - LIT("}"); - } - } - break; - - case CMARK_NODE_EMPH: - if (entering) { - LIT("\\emph{"); - } else { - LIT("}"); - } - break; - - case CMARK_NODE_LINK: - if (entering) { - const char *url = cmark_node_get_url(node); - // requires \usepackage{hyperref} - switch (get_link_type(node)) { - case URL_AUTOLINK: - LIT("\\url{"); - OUT(url, false, URL); - LIT("}"); - return 0; // Don't process further nodes to avoid double-rendering artefacts - case EMAIL_AUTOLINK: - LIT("\\href{"); - OUT(url, false, URL); - LIT("}\\nolinkurl{"); - break; - case NORMAL_LINK: - LIT("\\href{"); - OUT(url, false, URL); - LIT("}{"); - break; - case INTERNAL_LINK: - LIT("\\protect\\hyperlink{"); - OUT(url + 1, false, URL); - LIT("}{"); - break; - case NO_LINK: - LIT("{"); // error? - } - } else { - LIT("}"); - } - - break; - - case CMARK_NODE_IMAGE: - if (entering) { - LIT("\\protect\\includegraphics{"); - // requires \include{graphicx} - OUT(cmark_node_get_url(node), false, URL); - LIT("}"); - return 0; - } - break; - - case CMARK_NODE_FOOTNOTE_DEFINITION: - case CMARK_NODE_FOOTNOTE_REFERENCE: - // TODO - break; - - default: - assert(false); - break; - } - - return 1; -} - -char *cmark_render_latex(cmark_node *root, int options, int width) { - 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/vendor/core/vendor/cmark-gfm/src/linked_list.c b/vendor/core/vendor/cmark-gfm/src/linked_list.c deleted file mode 100644 index 8c26dc557..000000000 --- a/vendor/core/vendor/cmark-gfm/src/linked_list.c +++ /dev/null @@ -1,37 +0,0 @@ -#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/vendor/core/vendor/cmark-gfm/src/main.c b/vendor/core/vendor/cmark-gfm/src/main.c deleted file mode 100644 index a62c4f2ca..000000000 --- a/vendor/core/vendor/cmark-gfm/src/main.c +++ /dev/null @@ -1,328 +0,0 @@ -#include -#include -#include -#include -#include "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 "../extensions/cmark-gfm-core-extensions.h" - -#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/vendor/core/vendor/cmark-gfm/src/man.c b/vendor/core/vendor/cmark-gfm/src/man.c
deleted file mode 100644
index 634fd9d0f..000000000
--- a/vendor/core/vendor/cmark-gfm/src/man.c
+++ /dev/null
@@ -1,274 +0,0 @@
-#include 
-#include 
-#include 
-#include 
-
-#include "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, 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_node *node, 
-                   cmark_escaping escape, int32_t c,
-                   unsigned char nextc) {
-  (void)(nextc);
-
-  if (escape == LITERAL) {
-    cmark_render_code_point(renderer, c);
-    return;
-  }
-
-  switch (c) {
-  case 46:
-    if (renderer->begin_line) {
-      cmark_render_ascii(renderer, "\\&.");
-    } else {
-      cmark_render_code_point(renderer, c);
-    }
-    break;
-  case 39:
-    if (renderer->begin_line) {
-      cmark_render_ascii(renderer, "\\&'");
-    } else {
-      cmark_render_code_point(renderer, c);
-    }
-    break;
-  case 45:
-    cmark_render_ascii(renderer, "\\-");
-    break;
-  case 92:
-    cmark_render_ascii(renderer, "\\e");
-    break;
-  case 8216: // left single quote
-    cmark_render_ascii(renderer, "\\[oq]");
-    break;
-  case 8217: // right single quote
-    cmark_render_ascii(renderer, "\\[cq]");
-    break;
-  case 8220: // left double quote
-    cmark_render_ascii(renderer, "\\[lq]");
-    break;
-  case 8221: // right double quote
-    cmark_render_ascii(renderer, "\\[rq]");
-    break;
-  case 8212: // em dash
-    cmark_render_ascii(renderer, "\\[em]");
-    break;
-  case 8211: // en dash
-    cmark_render_ascii(renderer, "\\[en]");
-    break;
-  default:
-    cmark_render_code_point(renderer, c);
-  }
-}
-
-static int S_render_node(cmark_renderer *renderer, cmark_node *node,
-                         cmark_event_type ev_type, int options) {
-  int list_number;
-  bool entering = (ev_type == CMARK_EVENT_ENTER);
-  bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & 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:
-    if (entering) {
-      CR();
-      LIT(".RS");
-      CR();
-    } else {
-      CR();
-      LIT(".RE");
-      CR();
-    }
-    break;
-
-  case CMARK_NODE_LIST:
-    break;
-
-  case CMARK_NODE_ITEM:
-    if (entering) {
-      CR();
-      LIT(".IP ");
-      if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
-        LIT("\\[bu] 2");
-      } else {
-        list_number = cmark_node_get_item_index(node);
-        char list_number_s[LIST_NUMBER_SIZE];
-        snprintf(list_number_s, LIST_NUMBER_SIZE, "\"%d.\" 4", list_number);
-        LIT(list_number_s);
-      }
-      CR();
-    } else {
-      CR();
-    }
-    break;
-
-  case CMARK_NODE_HEADING:
-    if (entering) {
-      CR();
-      LIT(cmark_node_get_heading_level(node) == 1 ? ".SH" : ".SS");
-      CR();
-    } else {
-      CR();
-    }
-    break;
-
-  case CMARK_NODE_CODE_BLOCK:
-    CR();
-    LIT(".IP\n.nf\n\\f[C]\n");
-    OUT(cmark_node_get_literal(node), false, NORMAL);
-    CR();
-    LIT("\\f[]\n.fi");
-    CR();
-    break;
-
-  case CMARK_NODE_HTML_BLOCK:
-    break;
-
-  case CMARK_NODE_CUSTOM_BLOCK:
-    CR();
-    OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
-        false, LITERAL);
-    CR();
-    break;
-
-  case CMARK_NODE_THEMATIC_BREAK:
-    CR();
-    LIT(".PP\n  *  *  *  *  *");
-    CR();
-    break;
-
-  case CMARK_NODE_PARAGRAPH:
-    if (entering) {
-      // no blank line if first paragraph in list:
-      if (node->parent && node->parent->type == CMARK_NODE_ITEM &&
-          node->prev == NULL) {
-        // no blank line or .PP
-      } else {
-        CR();
-        LIT(".PP");
-        CR();
-      }
-    } else {
-      CR();
-    }
-    break;
-
-  case CMARK_NODE_TEXT:
-    OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
-    break;
-
-  case CMARK_NODE_LINEBREAK:
-    LIT(".PD 0\n.P\n.PD");
-    CR();
-    break;
-
-  case CMARK_NODE_SOFTBREAK:
-    if (options & CMARK_OPT_HARDBREAKS) {
-      LIT(".PD 0\n.P\n.PD");
-      CR();
-    } else if (renderer->width == 0 && !(CMARK_OPT_NOBREAKS & options)) {
-      CR();
-    } else {
-      OUT(" ", allow_wrap, LITERAL);
-    }
-    break;
-
-  case CMARK_NODE_CODE:
-    LIT("\\f[C]");
-    OUT(cmark_node_get_literal(node), allow_wrap, NORMAL);
-    LIT("\\f[]");
-    break;
-
-  case CMARK_NODE_HTML_INLINE:
-    break;
-
-  case CMARK_NODE_CUSTOM_INLINE:
-    OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
-        false, LITERAL);
-    break;
-
-  case CMARK_NODE_STRONG:
-    if (node->parent == NULL || node->parent->type != CMARK_NODE_STRONG) {
-      if (entering) {
-        LIT("\\f[B]");
-      } else {
-        LIT("\\f[]");
-      }
-    }
-    break;
-
-  case CMARK_NODE_EMPH:
-    if (entering) {
-      LIT("\\f[I]");
-    } else {
-      LIT("\\f[]");
-    }
-    break;
-
-  case CMARK_NODE_LINK:
-    if (!entering) {
-      LIT(" (");
-      OUT(cmark_node_get_url(node), allow_wrap, URL);
-      LIT(")");
-    }
-    break;
-
-  case CMARK_NODE_IMAGE:
-    if (entering) {
-      LIT("[IMAGE: ");
-    } else {
-      LIT("]");
-    }
-    break;
-
-  case CMARK_NODE_FOOTNOTE_DEFINITION:
-  case CMARK_NODE_FOOTNOTE_REFERENCE:
-    // TODO
-    break;
-
-  default:
-    assert(false);
-    break;
-  }
-
-  return 1;
-}
-
-char *cmark_render_man(cmark_node *root, int options, int width) {
-  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/vendor/core/vendor/cmark-gfm/src/map.c b/vendor/core/vendor/cmark-gfm/src/map.c
deleted file mode 100644
index f60f8fc60..000000000
--- a/vendor/core/vendor/cmark-gfm/src/map.c
+++ /dev/null
@@ -1,129 +0,0 @@
-#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) {
-  size_t 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;
-  cmark_map_entry *r = 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 != NULL) {
-    r = ref[0];
-    /* Check for expansion limit */
-    if (r->size > map->max_ref_size - map->ref_size)
-      return NULL;
-    map->ref_size += r->size;
-  }
-
-  return r;
-}
-
-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;
-  map->max_ref_size = UINT_MAX;
-  return map;
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/map.h b/vendor/core/vendor/cmark-gfm/src/map.h
deleted file mode 100644
index cc9b1f30c..000000000
--- a/vendor/core/vendor/cmark-gfm/src/map.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#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;
-  size_t age;
-  size_t size;
-};
-
-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;
-  size_t size;
-  size_t ref_size;
-  size_t max_ref_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/vendor/core/vendor/cmark-gfm/src/node.c b/vendor/core/vendor/cmark-gfm/src/node.c
deleted file mode 100644
index e7a9606d5..000000000
--- a/vendor/core/vendor/cmark-gfm/src/node.c
+++ /dev/null
@@ -1,1045 +0,0 @@
-#include 
-#include 
-
-#include "config.h"
-#include "node.h"
-#include "syntax_extension.h"
-
-/**
- * Expensive safety checks are off by default, but can be enabled
- * by calling cmark_enable_safety_checks().
- */
-static bool enable_safety_checks = false;
-
-void cmark_enable_safety_checks(bool enable) {
-  enable_safety_checks = enable;
-}
-
-static void S_node_unlink(cmark_node *node);
-
-#define NODE_MEM(node) cmark_node_mem(node)
-
-void cmark_register_node_flag(cmark_node_internal_flags *flags) {
-  static cmark_node_internal_flags nextflag = CMARK_NODE__REGISTER_FIRST;
-
-  // flags should be a pointer to a global variable and this function
-  // should only be called once to initialize its value.
-  if (*flags) {
-    fprintf(stderr, "flag initialization error in cmark_register_node_flag\n");
-    abort();
-  }
-
-  // Check that we haven't run out of bits.
-  if (nextflag == 0) {
-    fprintf(stderr, "too many flags in cmark_register_node_flag\n");
-    abort();
-  }
-
-  *flags = nextflag;
-  nextflag <<= 1;
-}
-
-void cmark_init_standard_node_flags(void) {}
-
-bool cmark_node_can_contain_type(cmark_node *node, cmark_node_type child_type) {
-  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 CMARK_NODE_TYPE_BLOCK_P(child_type) && child_type != CMARK_NODE_ITEM;
-
-  case CMARK_NODE_LIST:
-    return child_type == CMARK_NODE_ITEM;
-
-  case CMARK_NODE_CUSTOM_BLOCK:
-    return true;
-
-  case CMARK_NODE_PARAGRAPH:
-  case CMARK_NODE_HEADING:
-  case CMARK_NODE_EMPH:
-  case CMARK_NODE_STRONG:
-  case CMARK_NODE_LINK:
-  case CMARK_NODE_IMAGE:
-  case CMARK_NODE_CUSTOM_INLINE:
-    return CMARK_NODE_TYPE_INLINE_P(child_type);
-
-  default:
-    break;
-  }
-
-  return false;
-}
-
-static bool S_can_contain(cmark_node *node, cmark_node *child) {
-  if (node == NULL || child == NULL) {
-    return false;
-  }
-  if (NODE_MEM(node) != NODE_MEM(child)) {
-    return 0;
-  }
-
-  if (enable_safety_checks) {
-    // Verify that child is not an ancestor of node or equal to node.
-    cmark_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:
-    node->as.heading.level = 1;
-    break;
-
-  case CMARK_NODE_LIST: {
-    cmark_list *list = &node->as.list;
-    list->list_type = CMARK_BULLET_LIST;
-    list->start = 0;
-    list->tight = false;
-    break;
-  }
-
-  default:
-    break;
-  }
-
-  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) {
-  return cmark_node_new_with_ext(type, NULL);
-}
-
-static void free_node_as(cmark_node *node) {
-  switch (node->type) {
-    case CMARK_NODE_CODE_BLOCK:
-    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:
-    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(node), &node->as.link.url);
-    cmark_chunk_free(NODE_MEM(node), &node->as.link.title);
-      break;
-    case CMARK_NODE_CUSTOM_BLOCK:
-    case CMARK_NODE_CUSTOM_INLINE:
-    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;
-      e->next = e->first_child;
-    }
-    next = e->next;
-    NODE_MEM(e)->free(e);
-    e = next;
-  }
-}
-
-void cmark_node_free(cmark_node *node) {
-  S_node_unlink(node);
-  node->next = NULL;
-  S_free_nodes(node);
-}
-
-cmark_node_type cmark_node_get_type(cmark_node *node) {
-  if (node == NULL) {
-    return CMARK_NODE_NONE;
-  } else {
-    return (cmark_node_type)node->type;
-  }
-}
-
-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";
-  case CMARK_NODE_DOCUMENT:
-    return "document";
-  case CMARK_NODE_BLOCK_QUOTE:
-    return "block_quote";
-  case CMARK_NODE_LIST:
-    return "list";
-  case CMARK_NODE_ITEM:
-    return "item";
-  case CMARK_NODE_CODE_BLOCK:
-    return "code_block";
-  case CMARK_NODE_HTML_BLOCK:
-    return "html_block";
-  case CMARK_NODE_CUSTOM_BLOCK:
-    return "custom_block";
-  case CMARK_NODE_PARAGRAPH:
-    return "paragraph";
-  case CMARK_NODE_HEADING:
-    return "heading";
-  case CMARK_NODE_THEMATIC_BREAK:
-    return "thematic_break";
-  case CMARK_NODE_TEXT:
-    return "text";
-  case CMARK_NODE_SOFTBREAK:
-    return "softbreak";
-  case CMARK_NODE_LINEBREAK:
-    return "linebreak";
-  case CMARK_NODE_CODE:
-    return "code";
-  case CMARK_NODE_HTML_INLINE:
-    return "html_inline";
-  case CMARK_NODE_CUSTOM_INLINE:
-    return "custom_inline";
-  case CMARK_NODE_EMPH:
-    return "emph";
-  case CMARK_NODE_STRONG:
-    return "strong";
-  case CMARK_NODE_LINK:
-    return "link";
-  case CMARK_NODE_IMAGE:
-    return "image";
-  }
-
-  return "";
-}
-
-cmark_node *cmark_node_next(cmark_node *node) {
-  if (node == NULL) {
-    return NULL;
-  } else {
-    return node->next;
-  }
-}
-
-cmark_node *cmark_node_previous(cmark_node *node) {
-  if (node == NULL) {
-    return NULL;
-  } else {
-    return node->prev;
-  }
-}
-
-cmark_node *cmark_node_parent(cmark_node *node) {
-  if (node == NULL) {
-    return NULL;
-  } else {
-    return node->parent;
-  }
-}
-
-cmark_node *cmark_node_first_child(cmark_node *node) {
-  if (node == NULL) {
-    return NULL;
-  } else {
-    return node->first_child;
-  }
-}
-
-cmark_node *cmark_node_last_child(cmark_node *node) {
-  if (node == NULL) {
-    return NULL;
-  } else {
-    return node->last_child;
-  }
-}
-
-cmark_node *cmark_node_parent_footnote_def(cmark_node *node) {
-  if (node == NULL) {
-    return NULL;
-  } else {
-    return node->parent_footnote_def;
-  }
-}
-
-void *cmark_node_get_user_data(cmark_node *node) {
-  if (node == NULL) {
-    return NULL;
-  } else {
-    return node->user_data;
-  }
-}
-
-int cmark_node_set_user_data(cmark_node *node, void *user_data) {
-  if (node == NULL) {
-    return 0;
-  }
-  node->user_data = user_data;
-  return 1;
-}
-
-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;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_HTML_BLOCK:
-  case CMARK_NODE_TEXT:
-  case CMARK_NODE_HTML_INLINE:
-  case CMARK_NODE_CODE:
-  case CMARK_NODE_FOOTNOTE_REFERENCE:
-  case CMARK_NODE_FOOTNOTE_DEFINITION:
-    return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.literal);
-
-  case CMARK_NODE_CODE_BLOCK:
-    return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.code.literal);
-
-  default:
-    break;
-  }
-
-  return NULL;
-}
-
-int cmark_node_set_literal(cmark_node *node, const char *content) {
-  if (node == NULL) {
-    return 0;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_HTML_BLOCK:
-  case CMARK_NODE_TEXT:
-  case CMARK_NODE_HTML_INLINE:
-  case CMARK_NODE_CODE:
-  case CMARK_NODE_FOOTNOTE_REFERENCE:
-    cmark_chunk_set_cstr(NODE_MEM(node), &node->as.literal, content);
-    return 1;
-
-  case CMARK_NODE_CODE_BLOCK:
-    cmark_chunk_set_cstr(NODE_MEM(node), &node->as.code.literal, content);
-    return 1;
-
-  default:
-    break;
-  }
-
-  return 0;
-}
-
-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;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_HEADING:
-    return node->as.heading.level;
-
-  default:
-    break;
-  }
-
-  return 0;
-}
-
-int cmark_node_set_heading_level(cmark_node *node, int level) {
-  if (node == NULL || level < 1 || level > 6) {
-    return 0;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_HEADING:
-    node->as.heading.level = level;
-    return 1;
-
-  default:
-    break;
-  }
-
-  return 0;
-}
-
-cmark_list_type cmark_node_get_list_type(cmark_node *node) {
-  if (node == NULL) {
-    return CMARK_NO_LIST;
-  }
-
-  if (node->type == CMARK_NODE_LIST) {
-    return node->as.list.list_type;
-  } else {
-    return CMARK_NO_LIST;
-  }
-}
-
-int cmark_node_set_list_type(cmark_node *node, cmark_list_type type) {
-  if (!(type == CMARK_BULLET_LIST || type == CMARK_ORDERED_LIST)) {
-    return 0;
-  }
-
-  if (node == NULL) {
-    return 0;
-  }
-
-  if (node->type == CMARK_NODE_LIST) {
-    node->as.list.list_type = type;
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-cmark_delim_type cmark_node_get_list_delim(cmark_node *node) {
-  if (node == NULL) {
-    return CMARK_NO_DELIM;
-  }
-
-  if (node->type == CMARK_NODE_LIST) {
-    return node->as.list.delimiter;
-  } else {
-    return CMARK_NO_DELIM;
-  }
-}
-
-int cmark_node_set_list_delim(cmark_node *node, cmark_delim_type delim) {
-  if (!(delim == CMARK_PERIOD_DELIM || delim == CMARK_PAREN_DELIM)) {
-    return 0;
-  }
-
-  if (node == NULL) {
-    return 0;
-  }
-
-  if (node->type == CMARK_NODE_LIST) {
-    node->as.list.delimiter = delim;
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-int cmark_node_get_list_start(cmark_node *node) {
-  if (node == NULL) {
-    return 0;
-  }
-
-  if (node->type == CMARK_NODE_LIST) {
-    return node->as.list.start;
-  } else {
-    return 0;
-  }
-}
-
-int cmark_node_set_list_start(cmark_node *node, int start) {
-  if (node == NULL || start < 0) {
-    return 0;
-  }
-
-  if (node->type == CMARK_NODE_LIST) {
-    node->as.list.start = start;
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-int cmark_node_get_list_tight(cmark_node *node) {
-  if (node == NULL) {
-    return 0;
-  }
-
-  if (node->type == CMARK_NODE_LIST) {
-    return node->as.list.tight;
-  } else {
-    return 0;
-  }
-}
-
-int cmark_node_set_list_tight(cmark_node *node, int tight) {
-  if (node == NULL) {
-    return 0;
-  }
-
-  if (node->type == CMARK_NODE_LIST) {
-    node->as.list.tight = tight == 1;
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-int cmark_node_get_item_index(cmark_node *node) {
-  if (node == NULL) {
-    return 0;
-  }
-
-  if (node->type == CMARK_NODE_ITEM) {
-    return node->as.list.start;
-  } else {
-    return 0;
-  }
-}
-
-int cmark_node_set_item_index(cmark_node *node, int idx) {
-  if (node == NULL || idx < 0) {
-    return 0;
-  }
-
-  if (node->type == CMARK_NODE_ITEM) {
-    node->as.list.start = idx;
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-const char *cmark_node_get_fence_info(cmark_node *node) {
-  if (node == NULL) {
-    return NULL;
-  }
-
-  if (node->type == CMARK_NODE_CODE_BLOCK) {
-    return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.code.info);
-  } else {
-    return NULL;
-  }
-}
-
-int cmark_node_set_fence_info(cmark_node *node, const char *info) {
-  if (node == NULL) {
-    return 0;
-  }
-
-  if (node->type == CMARK_NODE_CODE_BLOCK) {
-    cmark_chunk_set_cstr(NODE_MEM(node), &node->as.code.info, info);
-    return 1;
-  } else {
-    return 0;
-  }
-}
-
-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;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_LINK:
-  case CMARK_NODE_IMAGE:
-    return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.link.url);
-  default:
-    break;
-  }
-
-  return NULL;
-}
-
-int cmark_node_set_url(cmark_node *node, const char *url) {
-  if (node == NULL) {
-    return 0;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_LINK:
-  case CMARK_NODE_IMAGE:
-    cmark_chunk_set_cstr(NODE_MEM(node), &node->as.link.url, url);
-    return 1;
-  default:
-    break;
-  }
-
-  return 0;
-}
-
-const char *cmark_node_get_title(cmark_node *node) {
-  if (node == NULL) {
-    return NULL;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_LINK:
-  case CMARK_NODE_IMAGE:
-    return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.link.title);
-  default:
-    break;
-  }
-
-  return NULL;
-}
-
-int cmark_node_set_title(cmark_node *node, const char *title) {
-  if (node == NULL) {
-    return 0;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_LINK:
-  case CMARK_NODE_IMAGE:
-    cmark_chunk_set_cstr(NODE_MEM(node), &node->as.link.title, title);
-    return 1;
-  default:
-    break;
-  }
-
-  return 0;
-}
-
-const char *cmark_node_get_on_enter(cmark_node *node) {
-  if (node == NULL) {
-    return NULL;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_CUSTOM_INLINE:
-  case CMARK_NODE_CUSTOM_BLOCK:
-    return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.custom.on_enter);
-  default:
-    break;
-  }
-
-  return NULL;
-}
-
-int cmark_node_set_on_enter(cmark_node *node, const char *on_enter) {
-  if (node == NULL) {
-    return 0;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_CUSTOM_INLINE:
-  case CMARK_NODE_CUSTOM_BLOCK:
-    cmark_chunk_set_cstr(NODE_MEM(node), &node->as.custom.on_enter, on_enter);
-    return 1;
-  default:
-    break;
-  }
-
-  return 0;
-}
-
-const char *cmark_node_get_on_exit(cmark_node *node) {
-  if (node == NULL) {
-    return NULL;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_CUSTOM_INLINE:
-  case CMARK_NODE_CUSTOM_BLOCK:
-    return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.custom.on_exit);
-  default:
-    break;
-  }
-
-  return NULL;
-}
-
-int cmark_node_set_on_exit(cmark_node *node, const char *on_exit) {
-  if (node == NULL) {
-    return 0;
-  }
-
-  switch (node->type) {
-  case CMARK_NODE_CUSTOM_INLINE:
-  case CMARK_NODE_CUSTOM_BLOCK:
-    cmark_chunk_set_cstr(NODE_MEM(node), &node->as.custom.on_exit, on_exit);
-    return 1;
-  default:
-    break;
-  }
-
-  return 0;
-}
-
-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;
-  }
-  return node->start_line;
-}
-
-int cmark_node_get_start_column(cmark_node *node) {
-  if (node == NULL) {
-    return 0;
-  }
-  return node->start_column;
-}
-
-int cmark_node_get_end_line(cmark_node *node) {
-  if (node == NULL) {
-    return 0;
-  }
-  return node->end_line;
-}
-
-int cmark_node_get_end_column(cmark_node *node) {
-  if (node == NULL) {
-    return 0;
-  }
-  return node->end_column;
-}
-
-// Unlink a node without adjusting its next, prev, and parent pointers.
-static void S_node_unlink(cmark_node *node) {
-  if (node == NULL) {
-    return;
-  }
-
-  if (node->prev) {
-    node->prev->next = node->next;
-  }
-  if (node->next) {
-    node->next->prev = node->prev;
-  }
-
-  // Adjust first_child and last_child of parent.
-  cmark_node *parent = node->parent;
-  if (parent) {
-    if (parent->first_child == node) {
-      parent->first_child = node->next;
-    }
-    if (parent->last_child == node) {
-      parent->last_child = node->prev;
-    }
-  }
-}
-
-void cmark_node_unlink(cmark_node *node) {
-  S_node_unlink(node);
-
-  node->next = NULL;
-  node->prev = NULL;
-  node->parent = NULL;
-}
-
-int cmark_node_insert_before(cmark_node *node, cmark_node *sibling) {
-  if (node == NULL || sibling == NULL) {
-    return 0;
-  }
-
-  if (!node->parent || !S_can_contain(node->parent, sibling)) {
-    return 0;
-  }
-
-  S_node_unlink(sibling);
-
-  cmark_node *old_prev = node->prev;
-
-  // Insert 'sibling' between 'old_prev' and 'node'.
-  if (old_prev) {
-    old_prev->next = sibling;
-  }
-  sibling->prev = old_prev;
-  sibling->next = node;
-  node->prev = sibling;
-
-  // Set new parent.
-  cmark_node *parent = node->parent;
-  sibling->parent = parent;
-
-  // Adjust first_child of parent if inserted as first child.
-  if (parent && !old_prev) {
-    parent->first_child = sibling;
-  }
-
-  return 1;
-}
-
-int cmark_node_insert_after(cmark_node *node, cmark_node *sibling) {
-  if (node == NULL || sibling == NULL) {
-    return 0;
-  }
-
-  if (!node->parent || !S_can_contain(node->parent, sibling)) {
-    return 0;
-  }
-
-  S_node_unlink(sibling);
-
-  cmark_node *old_next = node->next;
-
-  // Insert 'sibling' between 'node' and 'old_next'.
-  if (old_next) {
-    old_next->prev = sibling;
-  }
-  sibling->next = old_next;
-  sibling->prev = node;
-  node->next = sibling;
-
-  // Set new parent.
-  cmark_node *parent = node->parent;
-  sibling->parent = parent;
-
-  // Adjust last_child of parent if inserted as last child.
-  if (parent && !old_next) {
-    parent->last_child = sibling;
-  }
-
-  return 1;
-}
-
-int cmark_node_replace(cmark_node *oldnode, cmark_node *newnode) {
-  if (!cmark_node_insert_before(oldnode, newnode)) {
-    return 0;
-  }
-  cmark_node_unlink(oldnode);
-  return 1;
-}
-
-int cmark_node_prepend_child(cmark_node *node, cmark_node *child) {
-  if (!S_can_contain(node, child)) {
-    return 0;
-  }
-
-  S_node_unlink(child);
-
-  cmark_node *old_first_child = node->first_child;
-
-  child->next = old_first_child;
-  child->prev = NULL;
-  child->parent = node;
-  node->first_child = child;
-
-  if (old_first_child) {
-    old_first_child->prev = child;
-  } else {
-    // Also set last_child if node previously had no children.
-    node->last_child = child;
-  }
-
-  return 1;
-}
-
-int cmark_node_append_child(cmark_node *node, cmark_node *child) {
-  if (!S_can_contain(node, child)) {
-    return 0;
-  }
-
-  S_node_unlink(child);
-
-  cmark_node *old_last_child = node->last_child;
-
-  child->next = NULL;
-  child->prev = old_last_child;
-  child->parent = node;
-  node->last_child = child;
-
-  if (old_last_child) {
-    old_last_child->next = child;
-  } else {
-    // Also set first_child if node previously had no children.
-    node->first_child = child;
-  }
-
-  return 1;
-}
-
-static void S_print_error(FILE *out, cmark_node *node, const char *elem) {
-  if (out == NULL) {
-    return;
-  }
-  fprintf(out, "Invalid '%s' in node type %s at %d:%d\n", elem,
-          cmark_node_get_type_string(node), node->start_line,
-          node->start_column);
-}
-
-int cmark_node_check(cmark_node *node, FILE *out) {
-  cmark_node *cur;
-  int errors = 0;
-
-  if (!node) {
-    return 0;
-  }
-
-  cur = node;
-  for (;;) {
-    if (cur->first_child) {
-      if (cur->first_child->prev != NULL) {
-        S_print_error(out, cur->first_child, "prev");
-        cur->first_child->prev = NULL;
-        ++errors;
-      }
-      if (cur->first_child->parent != cur) {
-        S_print_error(out, cur->first_child, "parent");
-        cur->first_child->parent = cur;
-        ++errors;
-      }
-      cur = cur->first_child;
-      continue;
-    }
-
-  next_sibling:
-    if (cur == node) {
-      break;
-    }
-    if (cur->next) {
-      if (cur->next->prev != cur) {
-        S_print_error(out, cur->next, "prev");
-        cur->next->prev = cur;
-        ++errors;
-      }
-      if (cur->next->parent != cur->parent) {
-        S_print_error(out, cur->next, "parent");
-        cur->next->parent = cur->parent;
-        ++errors;
-      }
-      cur = cur->next;
-      continue;
-    }
-
-    if (cur->parent->last_child != cur) {
-      S_print_error(out, cur->parent, "last_child");
-      cur->parent->last_child = cur;
-      ++errors;
-    }
-    cur = cur->parent;
-    goto next_sibling;
-  }
-
-  return errors;
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/node.h b/vendor/core/vendor/cmark-gfm/src/node.h
deleted file mode 100644
index 73ca76053..000000000
--- a/vendor/core/vendor/cmark-gfm/src/node.h
+++ /dev/null
@@ -1,167 +0,0 @@
-#ifndef CMARK_NODE_H
-#define CMARK_NODE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include 
-#include 
-
-#include "cmark-gfm.h"
-#include "cmark-gfm-extension_api.h"
-#include "buffer.h"
-#include "chunk.h"
-
-typedef struct {
-  cmark_list_type list_type;
-  int marker_offset;
-  int padding;
-  int start;
-  cmark_delim_type delimiter;
-  unsigned char bullet_char;
-  bool tight;
-  bool checked; // For task list extension
-} cmark_list;
-
-typedef struct {
-  cmark_chunk info;
-  cmark_chunk literal;
-  uint8_t fence_length;
-  uint8_t fence_offset;
-  unsigned char fence_char;
-  int8_t fenced;
-} cmark_code;
-
-typedef struct {
-  int level;
-  bool setext;
-} cmark_heading;
-
-typedef struct {
-  cmark_chunk url;
-  cmark_chunk title;
-} cmark_link;
-
-typedef struct {
-  cmark_chunk on_enter;
-  cmark_chunk on_exit;
-} cmark_custom;
-
-enum cmark_node__internal_flags {
-  CMARK_NODE__OPEN = (1 << 0),
-  CMARK_NODE__LAST_LINE_BLANK = (1 << 1),
-  CMARK_NODE__LAST_LINE_CHECKED = (1 << 2),
-
-  // Extensions can register custom flags by calling `cmark_register_node_flag`.
-  // This is the starting value for the custom flags.
-  CMARK_NODE__REGISTER_FIRST = (1 << 3),
-};
-
-typedef uint16_t cmark_node_internal_flags;
-
-struct cmark_node {
-  cmark_strbuf content;
-
-  struct cmark_node *next;
-  struct cmark_node *prev;
-  struct cmark_node *parent;
-  struct cmark_node *first_child;
-  struct cmark_node *last_child;
-
-  void *user_data;
-  cmark_free_func user_data_free_func;
-
-  int start_line;
-  int start_column;
-  int end_line;
-  int end_column;
-  int internal_offset;
-  uint16_t type;
-  cmark_node_internal_flags flags;
-
-  cmark_syntax_extension *extension;
-
-  /**
-   * Used during cmark_render() to cache the most recent non-NULL
-   * extension, if you go up the parent chain like this:
-   *
-   * node->parent->...parent->extension
-   */
-  cmark_syntax_extension *ancestor_extension;
-
-  union {
-    int ref_ix;
-    int def_count;
-  } footnote;
-
-  cmark_node *parent_footnote_def;
-
-  union {
-    cmark_chunk literal;
-    cmark_list list;
-    cmark_code code;
-    cmark_heading heading;
-    cmark_link link;
-    cmark_custom custom;
-    int html_block_type;
-    int cell_index; // For keeping track of TABLE_CELL table alignments
-    void *opaque;
-  } as;
-};
-
-/**
- * Syntax extensions can use this function to register a custom node
- * flag. The flags are stored in the `flags` field of the `cmark_node`
- * struct. The `flags` parameter should be the address of a global variable
- * which will store the flag value.
- */
-CMARK_GFM_EXPORT
-void cmark_register_node_flag(cmark_node_internal_flags *flags);
-
-/**
- * DEPRECATED.
- *
- * This function was added in cmark-gfm version 0.29.0.gfm.7, and was
- * required to be called at program start time, which caused
- * backwards-compatibility issues in applications that use cmark-gfm as a
- * library. It is now a no-op.
- */
-CMARK_GFM_EXPORT
-void cmark_init_standard_node_flags(void);
-
-static CMARK_INLINE cmark_mem *cmark_node_mem(cmark_node *node) {
-  return node->content.mem;
-}
-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);
-
-/**
- * Enable (or disable) extra safety checks. These extra checks cause
- * extra performance overhead (in some cases quadratic), so they are only
- * intended to be used during testing.
- */
-CMARK_GFM_EXPORT void cmark_enable_safety_checks(bool enable);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/vendor/core/vendor/cmark-gfm/src/parser.h b/vendor/core/vendor/cmark-gfm/src/parser.h
deleted file mode 100644
index 436c53f5b..000000000
--- a/vendor/core/vendor/cmark-gfm/src/parser.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef CMARK_PARSER_H
-#define CMARK_PARSER_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;
-  /* 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;
-  size_t total_size;
-  cmark_llist *syntax_extensions;
-  cmark_llist *inline_syntax_extensions;
-  cmark_ispunct_func backslash_ispunct;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/vendor/core/vendor/cmark-gfm/src/plaintext.c b/vendor/core/vendor/cmark-gfm/src/plaintext.c
deleted file mode 100644
index 0c7d257b3..000000000
--- a/vendor/core/vendor/cmark-gfm/src/plaintext.c
+++ /dev/null
@@ -1,218 +0,0 @@
-#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);
-}
-
-static int S_render_node(cmark_renderer *renderer, cmark_node *node,
-                         cmark_event_type ev_type, int options) {
-  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 (entering) {
-    if (node->parent && node->parent->type == CMARK_NODE_ITEM) {
-      renderer->in_tight_list_item = node->parent->parent->as.list.tight;
-    }
-  } else {
-    if (node->type == CMARK_NODE_LIST) {
-      renderer->in_tight_list_item =
-        node->parent &&
-        node->parent->type == CMARK_NODE_ITEM &&
-        node->parent->parent->as.list.tight;
-    }
-  }
-
-  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_item_index(node);
-      list_delim = cmark_node_get_list_delim(node->parent);
-      // 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_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/vendor/core/vendor/cmark-gfm/src/plugin.c b/vendor/core/vendor/cmark-gfm/src/plugin.c
deleted file mode 100644
index 3992fe197..000000000
--- a/vendor/core/vendor/cmark-gfm/src/plugin.c
+++ /dev/null
@@ -1,36 +0,0 @@
-#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/vendor/core/vendor/cmark-gfm/src/plugin.h b/vendor/core/vendor/cmark-gfm/src/plugin.h
deleted file mode 100644
index 7bcbd19a2..000000000
--- a/vendor/core/vendor/cmark-gfm/src/plugin.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#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/vendor/core/vendor/cmark-gfm/src/references.c b/vendor/core/vendor/cmark-gfm/src/references.c
deleted file mode 100644
index 0c9d3995c..000000000
--- a/vendor/core/vendor/cmark-gfm/src/references.c
+++ /dev/null
@@ -1,43 +0,0 @@
-#include "cmark-gfm.h"
-#include "parser.h"
-#include "references.h"
-#include "inlines.h"
-#include "chunk.h"
-
-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->entry.label);
-    cmark_chunk_free(mem, &ref->url);
-    cmark_chunk_free(mem, &ref->title);
-    mem->free(ref);
-  }
-}
-
-void cmark_reference_create(cmark_map *map, cmark_chunk *label,
-                            cmark_chunk *url, cmark_chunk *title) {
-  cmark_reference *ref;
-  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->entry.label = reflabel;
-  ref->url = cmark_clean_url(map->mem, url);
-  ref->title = cmark_clean_title(map->mem, title);
-  ref->entry.age = map->size;
-  ref->entry.next = map->refs;
-  ref->entry.size = ref->url.len + ref->title.len;
-
-  map->refs = (cmark_map_entry *)ref;
-  map->size++;
-}
-
-cmark_map *cmark_reference_map_new(cmark_mem *mem) {
-  return cmark_map_new(mem, reference_free);
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/references.h b/vendor/core/vendor/cmark-gfm/src/references.h
deleted file mode 100644
index def944dc7..000000000
--- a/vendor/core/vendor/cmark-gfm/src/references.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef CMARK_REFERENCES_H
-#define CMARK_REFERENCES_H
-
-#include "map.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct cmark_reference {
-  cmark_map_entry entry;
-  cmark_chunk url;
-  cmark_chunk title;
-};
-
-typedef struct cmark_reference cmark_reference;
-
-void cmark_reference_create(cmark_map *map, cmark_chunk *label,
-                            cmark_chunk *url, cmark_chunk *title);
-cmark_map *cmark_reference_map_new(cmark_mem *mem);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/vendor/core/vendor/cmark-gfm/src/registry.c b/vendor/core/vendor/cmark-gfm/src/registry.c
deleted file mode 100644
index f4f2040d6..000000000
--- a/vendor/core/vendor/cmark-gfm/src/registry.c
+++ /dev/null
@@ -1,63 +0,0 @@
-#include 
-#include 
-#include 
-
-#include "config.h"
-#include "cmark-gfm.h"
-#include "syntax_extension.h"
-#include "registry.h"
-#include "plugin.h"
-
-extern cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR;
-
-static cmark_llist *syntax_extensions = NULL;
-
-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;
-
-  for (it = syntax_extensions_list; it; it = it->next) {
-    syntax_extensions = cmark_llist_append(&CMARK_DEFAULT_MEM_ALLOCATOR, syntax_extensions, it->data);
-  }
-
-  cmark_llist_free(&CMARK_DEFAULT_MEM_ALLOCATOR, syntax_extensions_list);
-  cmark_plugin_free(plugin);
-}
-
-void cmark_release_plugins(void) {
-  if (syntax_extensions) {
-    cmark_llist_free_full(
-        &CMARK_DEFAULT_MEM_ALLOCATOR,
-        syntax_extensions,
-        (cmark_free_func) cmark_syntax_extension_free);
-    syntax_extensions = NULL;
-  }
-}
-
-cmark_llist *cmark_list_syntax_extensions(cmark_mem *mem) {
-  cmark_llist *it;
-  cmark_llist *res = NULL;
-
-  for (it = syntax_extensions; it; it = it->next) {
-    res = cmark_llist_append(mem, res, it->data);
-  }
-  return res;
-}
-
-cmark_syntax_extension *cmark_find_syntax_extension(const char *name) {
-  cmark_llist *tmp;
-
-  for (tmp = syntax_extensions; tmp; tmp = tmp->next) {
-    cmark_syntax_extension *ext = (cmark_syntax_extension *) tmp->data;
-    if (!strcmp(ext->name, name))
-      return ext;
-  }
-  return NULL;
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/registry.h b/vendor/core/vendor/cmark-gfm/src/registry.h
deleted file mode 100644
index fece2b63f..000000000
--- a/vendor/core/vendor/cmark-gfm/src/registry.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef CMARK_REGISTRY_H
-#define CMARK_REGISTRY_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "cmark-gfm.h"
-#include "plugin.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/vendor/core/vendor/cmark-gfm/src/render.c b/vendor/core/vendor/cmark-gfm/src/render.c
deleted file mode 100644
index 1a0d2ae8d..000000000
--- a/vendor/core/vendor/cmark-gfm/src/render.c
+++ /dev/null
@@ -1,213 +0,0 @@
-#include 
-#include "buffer.h"
-#include "chunk.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) {
-    renderer->need_cr = 1;
-  }
-}
-
-static CMARK_INLINE void S_blankline(cmark_renderer *renderer) {
-  if (renderer->need_cr < 2) {
-    renderer->need_cr = 2;
-  }
-}
-
-static void S_out(cmark_renderer *renderer, cmark_node *node,
-                  const char *source, bool wrap,
-                  cmark_escaping escape) {
-  int length = (int)strlen(source);
-  unsigned char nextc;
-  int32_t c;
-  int i = 0;
-  int last_nonspace;
-  int len;
-  cmark_chunk remainder = cmark_chunk_literal("");
-  int k = renderer->buffer->size - 1;
-
-  cmark_syntax_extension *ext = node->ancestor_extension;
-  if (ext && !ext->commonmark_escape_func)
-    ext = NULL;
-
-  wrap = wrap && !renderer->no_linebreaks;
-
-  if (renderer->in_tight_list_item && renderer->need_cr > 1) {
-    renderer->need_cr = 1;
-  }
-  while (renderer->need_cr) {
-    if (k < 0 || renderer->buffer->ptr[k] == '\n') {
-      k -= 1;
-    } else {
-      cmark_strbuf_putc(renderer->buffer, '\n');
-      if (renderer->need_cr > 1) {
-        cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
-                         renderer->prefix->size);
-      }
-    }
-    renderer->column = 0;
-    renderer->last_breakable = 0;
-    renderer->begin_line = true;
-    renderer->begin_content = true;
-    renderer->need_cr -= 1;
-  }
-
-  while (i < length) {
-    if (renderer->begin_line) {
-      cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
-                       renderer->prefix->size);
-      // note: this assumes prefix is ascii:
-      renderer->column = renderer->prefix->size;
-    }
-
-    len = cmark_utf8proc_iterate((const uint8_t *)source + i, length - i, &c);
-    if (len == -1) { // error condition
-      return;        // return without rendering rest of string
-    }
-
-    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) {
-        last_nonspace = renderer->buffer->size;
-        cmark_strbuf_putc(renderer->buffer, ' ');
-        renderer->column += 1;
-        renderer->begin_line = false;
-        renderer->begin_content = false;
-        // skip following spaces
-        while (source[i + 1] == ' ') {
-          i++;
-        }
-        // We don't allow breaks that make a digit the first character
-        // because this causes problems with commonmark output.
-        if (!cmark_isdigit(source[i + 1])) {
-          renderer->last_breakable = last_nonspace;
-        }
-      }
-
-    } else if (escape == LITERAL) {
-      if (c == 10) {
-        cmark_strbuf_putc(renderer->buffer, '\n');
-        renderer->column = 0;
-        renderer->begin_line = true;
-        renderer->begin_content = true;
-        renderer->last_breakable = 0;
-      } else {
-        cmark_render_code_point(renderer, c);
-        renderer->begin_line = false;
-        // we don't set 'begin_content' to false til we've
-        // finished parsing a digit.  Reason:  in commonmark
-        // we need to escape a potential list marker after
-        // a digit:
-        renderer->begin_content =
-            renderer->begin_content && cmark_isdigit((char)c) == 1;
-      }
-    } else {
-      (renderer->outc)(renderer, node, escape, c, nextc);
-      renderer->begin_line = false;
-      renderer->begin_content =
-          renderer->begin_content && cmark_isdigit((char)c) == 1;
-    }
-
-    // If adding the character went beyond width, look for an
-    // earlier place where the line could be broken:
-    if (renderer->width > 0 && renderer->column > renderer->width &&
-        !renderer->begin_line && renderer->last_breakable > 0) {
-
-      // copy from last_breakable to remainder
-      cmark_chunk_set_cstr(renderer->mem, &remainder,
-                           (char *)renderer->buffer->ptr +
-                               renderer->last_breakable + 1);
-      // truncate at last_breakable
-      cmark_strbuf_truncate(renderer->buffer, renderer->last_breakable);
-      // add newline, prefix, and remainder
-      cmark_strbuf_putc(renderer->buffer, '\n');
-      cmark_strbuf_put(renderer->buffer, renderer->prefix->ptr,
-                       renderer->prefix->size);
-      cmark_strbuf_put(renderer->buffer, remainder.data, remainder.len);
-      renderer->column = renderer->prefix->size + remainder.len;
-      cmark_chunk_free(renderer->mem, &remainder);
-      renderer->last_breakable = 0;
-      renderer->begin_line = false;
-      renderer->begin_content = false;
-    }
-
-    i += len;
-  }
-}
-
-// Assumes no newlines, assumes ascii content:
-void cmark_render_ascii(cmark_renderer *renderer, const char *s) {
-  int origsize = renderer->buffer->size;
-  cmark_strbuf_puts(renderer->buffer, s);
-  renderer->column += renderer->buffer->size - origsize;
-}
-
-void cmark_render_code_point(cmark_renderer *renderer, uint32_t c) {
-  cmark_utf8proc_encode_char(c, renderer->buffer);
-  renderer->column += 1;
-}
-
-char *cmark_render(cmark_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_strbuf pref = CMARK_BUF_INIT(mem);
-  cmark_strbuf buf = CMARK_BUF_INIT(mem);
-  cmark_node *cur;
-  cmark_event_type ev_type;
-  char *result;
-  cmark_iter *iter = cmark_iter_new(root);
-
-  cmark_renderer renderer = {mem,   &buf, &pref, 0,           width,
-                             0,     0,    true,  true,        false,
-                             false, outc, S_cr,  S_blankline, S_out,
-                             0};
-
-  while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
-    cur = cmark_iter_get_node(iter);
-    if (cur->extension) {
-      cur->ancestor_extension = cur->extension;
-    } else if (cur->parent) {
-      cur->ancestor_extension = cur->parent->ancestor_extension;
-    }
-    if (cur->type == CMARK_NODE_ITEM) {
-      // Calculate the list item's index, for the benefit of output formats
-      // like commonmark and plaintext.
-      if (cur->prev) {
-        cmark_node_set_item_index(cur, 1 + cmark_node_get_item_index(cur->prev));
-      } else {
-        cmark_node_set_item_index(cur, cmark_node_get_list_start(cur->parent));
-      }
-    }
-    if (!render_node(&renderer, cur, ev_type, options)) {
-      // a false value causes us to skip processing
-      // the node's contents.  this is used for
-      // autolinks.
-      cmark_iter_reset(iter, cur, CMARK_EVENT_EXIT);
-    }
-  }
-
-  // ensure final newline
-  if (renderer.buffer->size == 0 || renderer.buffer->ptr[renderer.buffer->size - 1] != '\n') {
-    cmark_strbuf_putc(renderer.buffer, '\n');
-  }
-
-  result = (char *)cmark_strbuf_detach(renderer.buffer);
-
-  cmark_iter_free(iter);
-  cmark_strbuf_free(renderer.prefix);
-  cmark_strbuf_free(renderer.buffer);
-
-  return result;
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/render.h b/vendor/core/vendor/cmark-gfm/src/render.h
deleted file mode 100644
index 4a68d1e07..000000000
--- a/vendor/core/vendor/cmark-gfm/src/render.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef CMARK_RENDER_H
-#define CMARK_RENDER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include 
-#include "buffer.h"
-#include "chunk.h"
-
-typedef enum { LITERAL, NORMAL, TITLE, URL } cmark_escaping;
-
-struct cmark_renderer {
-  cmark_mem *mem;
-  cmark_strbuf *buffer;
-  cmark_strbuf *prefix;
-  int column;
-  int width;
-  int need_cr;
-  bufsize_t last_breakable;
-  bool begin_line;
-  bool begin_content;
-  bool no_linebreaks;
-  bool in_tight_list_item;
-  void (*outc)(struct cmark_renderer *, cmark_node *, cmark_escaping, int32_t, unsigned char);
-  void (*cr)(struct cmark_renderer *);
-  void (*blankline)(struct cmark_renderer *);
-  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_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));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/vendor/core/vendor/cmark-gfm/src/scanners.c b/vendor/core/vendor/cmark-gfm/src/scanners.c
deleted file mode 100644
index 19720601d..000000000
--- a/vendor/core/vendor/cmark-gfm/src/scanners.c
+++ /dev/null
@@ -1,14056 +0,0 @@
-/* Generated by re2c 3.0 */
-#include "scanners.h"
-#include "chunk.h"
-#include 
-
-bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c,
-                   bufsize_t offset) {
-  bufsize_t res;
-  unsigned char *ptr = (unsigned char *)c->data;
-
-  if (ptr == NULL || offset > c->len) {
-    return 0;
-  } else {
-    unsigned char lim = ptr[c->len];
-
-    ptr[c->len] = '\0';
-    res = scanner(ptr + offset);
-    ptr[c->len] = lim;
-  }
-
-  return res;
-}
-
-// Try to match a scheme including colon.
-bufsize_t _scan_scheme(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    yych = *p;
-    if (yych <= '@')
-      goto yy1;
-    if (yych <= 'Z')
-      goto yy3;
-    if (yych <= '`')
-      goto yy1;
-    if (yych <= 'z')
-      goto yy3;
-  yy1:
-    ++p;
-  yy2 : { return 0; }
-  yy3:
-    yych = *(marker = ++p);
-    if (yych <= '/') {
-      if (yych <= '+') {
-        if (yych <= '*')
-          goto yy2;
-      } else {
-        if (yych <= ',')
-          goto yy2;
-        if (yych >= '/')
-          goto yy2;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '9')
-          goto yy4;
-        if (yych <= '@')
-          goto yy2;
-      } else {
-        if (yych <= '`')
-          goto yy2;
-        if (yych >= '{')
-          goto yy2;
-      }
-    }
-  yy4:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych == '+')
-          goto yy6;
-      } else {
-        if (yych != '/')
-          goto yy6;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych >= 'A')
-          goto yy6;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych <= 'z')
-          goto yy6;
-      }
-    }
-  yy5:
-    p = marker;
-    goto yy2;
-  yy6:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych == '+')
-          goto yy8;
-        goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-        goto yy8;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-        goto yy8;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych <= 'z')
-          goto yy8;
-        goto yy5;
-      }
-    }
-  yy7:
-    ++p;
-    { return (bufsize_t)(p - start); }
-  yy8:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy5;
-      } else {
-        if (yych == '/')
-          goto yy5;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy7;
-        if (yych <= '@')
-          goto yy5;
-      } else {
-        if (yych <= '`')
-          goto yy5;
-        if (yych >= '{')
-          goto yy5;
-      }
-    }
-    yych = *++p;
-    if (yych == ':')
-      goto yy7;
-    goto yy5;
-  }
-}
-
-// Try to match URI autolink after first <, returning number of chars matched.
-bufsize_t _scan_autolink_uri(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    static const unsigned char yybm[] = {
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 0,   128, 0,   128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,
-    };
-    yych = *p;
-    if (yych <= '@')
-      goto yy10;
-    if (yych <= 'Z')
-      goto yy12;
-    if (yych <= '`')
-      goto yy10;
-    if (yych <= 'z')
-      goto yy12;
-  yy10:
-    ++p;
-  yy11 : { return 0; }
-  yy12:
-    yych = *(marker = ++p);
-    if (yych <= '/') {
-      if (yych <= '+') {
-        if (yych <= '*')
-          goto yy11;
-      } else {
-        if (yych <= ',')
-          goto yy11;
-        if (yych >= '/')
-          goto yy11;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '9')
-          goto yy13;
-        if (yych <= '@')
-          goto yy11;
-      } else {
-        if (yych <= '`')
-          goto yy11;
-        if (yych >= '{')
-          goto yy11;
-      }
-    }
-  yy13:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych == '+')
-          goto yy15;
-      } else {
-        if (yych != '/')
-          goto yy15;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych >= 'A')
-          goto yy15;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych <= 'z')
-          goto yy15;
-      }
-    }
-  yy14:
-    p = marker;
-    goto yy11;
-  yy15:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych == '+')
-          goto yy17;
-        goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-        goto yy17;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-        goto yy17;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych <= 'z')
-          goto yy17;
-        goto yy14;
-      }
-    }
-  yy16:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy16;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '<')
-          goto yy14;
-        if (yych <= '>')
-          goto yy18;
-        goto yy14;
-      } else {
-        if (yych <= 0xDF)
-          goto yy19;
-        if (yych <= 0xE0)
-          goto yy20;
-        goto yy21;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy22;
-        if (yych <= 0xEF)
-          goto yy21;
-        goto yy23;
-      } else {
-        if (yych <= 0xF3)
-          goto yy24;
-        if (yych <= 0xF4)
-          goto yy25;
-        goto yy14;
-      }
-    }
-  yy17:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych == '+')
-          goto yy26;
-        goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-        goto yy26;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-        goto yy26;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych <= 'z')
-          goto yy26;
-        goto yy14;
-      }
-    }
-  yy18:
-    ++p;
-    { return (bufsize_t)(p - start); }
-  yy19:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy14;
-    if (yych <= 0xBF)
-      goto yy16;
-    goto yy14;
-  yy20:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy14;
-    if (yych <= 0xBF)
-      goto yy19;
-    goto yy14;
-  yy21:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy14;
-    if (yych <= 0xBF)
-      goto yy19;
-    goto yy14;
-  yy22:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy14;
-    if (yych <= 0x9F)
-      goto yy19;
-    goto yy14;
-  yy23:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy14;
-    if (yych <= 0xBF)
-      goto yy21;
-    goto yy14;
-  yy24:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy14;
-    if (yych <= 0xBF)
-      goto yy21;
-    goto yy14;
-  yy25:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy14;
-    if (yych <= 0x8F)
-      goto yy21;
-    goto yy14;
-  yy26:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych <= ',') {
-        if (yych != '+')
-          goto yy14;
-      } else {
-        if (yych == '/')
-          goto yy14;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= ':')
-          goto yy16;
-        if (yych <= '@')
-          goto yy14;
-      } else {
-        if (yych <= '`')
-          goto yy14;
-        if (yych >= '{')
-          goto yy14;
-      }
-    }
-    yych = *++p;
-    if (yych == ':')
-      goto yy16;
-    goto yy14;
-  }
-}
-
-// Try to match email autolink after first <, returning num of chars matched.
-bufsize_t _scan_autolink_email(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    static const unsigned char yybm[] = {
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   128, 0,   128, 128, 128, 128, 128, 0,   0,
-        128, 128, 0,   128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 0,   0,   0,   128, 0,   128, 0,   128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 0,   0,   0,   128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,
-    };
-    yych = *p;
-    if (yych <= '9') {
-      if (yych <= '\'') {
-        if (yych == '!')
-          goto yy30;
-        if (yych >= '#')
-          goto yy30;
-      } else {
-        if (yych <= ')')
-          goto yy28;
-        if (yych != ',')
-          goto yy30;
-      }
-    } else {
-      if (yych <= '?') {
-        if (yych == '=')
-          goto yy30;
-        if (yych >= '?')
-          goto yy30;
-      } else {
-        if (yych <= 'Z') {
-          if (yych >= 'A')
-            goto yy30;
-        } else {
-          if (yych <= ']')
-            goto yy28;
-          if (yych <= '~')
-            goto yy30;
-        }
-      }
-    }
-  yy28:
-    ++p;
-  yy29 : { return 0; }
-  yy30:
-    yych = *(marker = ++p);
-    if (yych <= ',') {
-      if (yych <= '"') {
-        if (yych == '!')
-          goto yy32;
-        goto yy29;
-      } else {
-        if (yych <= '\'')
-          goto yy32;
-        if (yych <= ')')
-          goto yy29;
-        if (yych <= '+')
-          goto yy32;
-        goto yy29;
-      }
-    } else {
-      if (yych <= '>') {
-        if (yych <= '9')
-          goto yy32;
-        if (yych == '=')
-          goto yy32;
-        goto yy29;
-      } else {
-        if (yych <= 'Z')
-          goto yy32;
-        if (yych <= ']')
-          goto yy29;
-        if (yych <= '~')
-          goto yy32;
-        goto yy29;
-      }
-    }
-  yy31:
-    yych = *++p;
-  yy32:
-    if (yybm[0 + yych] & 128) {
-      goto yy31;
-    }
-    if (yych <= '>')
-      goto yy33;
-    if (yych <= '@')
-      goto yy34;
-  yy33:
-    p = marker;
-    goto yy29;
-  yy34:
-    yych = *++p;
-    if (yych <= '@') {
-      if (yych <= '/')
-        goto yy33;
-      if (yych >= ':')
-        goto yy33;
-    } else {
-      if (yych <= 'Z')
-        goto yy35;
-      if (yych <= '`')
-        goto yy33;
-      if (yych >= '{')
-        goto yy33;
-    }
-  yy35:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy36;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy36;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy36;
-        goto yy33;
-      }
-    }
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy38;
-      if (yych <= '/')
-        goto yy33;
-      goto yy39;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy39;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy39;
-        goto yy33;
-      }
-    }
-  yy36:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych <= '-')
-          goto yy38;
-        goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy39;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy39;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy39;
-        goto yy33;
-      }
-    }
-  yy37:
-    ++p;
-    { return (bufsize_t)(p - start); }
-  yy38:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy40;
-      if (yych <= '/')
-        goto yy33;
-      goto yy41;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy41;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy41;
-        goto yy33;
-      }
-    }
-  yy39:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy41;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy41;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy41;
-        goto yy33;
-      }
-    }
-  yy40:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy42;
-      if (yych <= '/')
-        goto yy33;
-      goto yy43;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy43;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy43;
-        goto yy33;
-      }
-    }
-  yy41:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy43;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy43;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy43;
-        goto yy33;
-      }
-    }
-  yy42:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy44;
-      if (yych <= '/')
-        goto yy33;
-      goto yy45;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy45;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy45;
-        goto yy33;
-      }
-    }
-  yy43:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy45;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy45;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy45;
-        goto yy33;
-      }
-    }
-  yy44:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy46;
-      if (yych <= '/')
-        goto yy33;
-      goto yy47;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy47;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy47;
-        goto yy33;
-      }
-    }
-  yy45:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy47;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy47;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy47;
-        goto yy33;
-      }
-    }
-  yy46:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy48;
-      if (yych <= '/')
-        goto yy33;
-      goto yy49;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy49;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy49;
-        goto yy33;
-      }
-    }
-  yy47:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy49;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy49;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy49;
-        goto yy33;
-      }
-    }
-  yy48:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy50;
-      if (yych <= '/')
-        goto yy33;
-      goto yy51;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy51;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy51;
-        goto yy33;
-      }
-    }
-  yy49:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy51;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy51;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy51;
-        goto yy33;
-      }
-    }
-  yy50:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy52;
-      if (yych <= '/')
-        goto yy33;
-      goto yy53;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy53;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy53;
-        goto yy33;
-      }
-    }
-  yy51:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy53;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy53;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy53;
-        goto yy33;
-      }
-    }
-  yy52:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy54;
-      if (yych <= '/')
-        goto yy33;
-      goto yy55;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy55;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy55;
-        goto yy33;
-      }
-    }
-  yy53:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy55;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy55;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy55;
-        goto yy33;
-      }
-    }
-  yy54:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy56;
-      if (yych <= '/')
-        goto yy33;
-      goto yy57;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy57;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy57;
-        goto yy33;
-      }
-    }
-  yy55:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy57;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy57;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy57;
-        goto yy33;
-      }
-    }
-  yy56:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy58;
-      if (yych <= '/')
-        goto yy33;
-      goto yy59;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy59;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy59;
-        goto yy33;
-      }
-    }
-  yy57:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy59;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy59;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy59;
-        goto yy33;
-      }
-    }
-  yy58:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy60;
-      if (yych <= '/')
-        goto yy33;
-      goto yy61;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy61;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy61;
-        goto yy33;
-      }
-    }
-  yy59:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy61;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy61;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy61;
-        goto yy33;
-      }
-    }
-  yy60:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy62;
-      if (yych <= '/')
-        goto yy33;
-      goto yy63;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy63;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy63;
-        goto yy33;
-      }
-    }
-  yy61:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy63;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy63;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy63;
-        goto yy33;
-      }
-    }
-  yy62:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy64;
-      if (yych <= '/')
-        goto yy33;
-      goto yy65;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy65;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy65;
-        goto yy33;
-      }
-    }
-  yy63:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy65;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy65;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy65;
-        goto yy33;
-      }
-    }
-  yy64:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy66;
-      if (yych <= '/')
-        goto yy33;
-      goto yy67;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy67;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy67;
-        goto yy33;
-      }
-    }
-  yy65:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy67;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy67;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy67;
-        goto yy33;
-      }
-    }
-  yy66:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy68;
-      if (yych <= '/')
-        goto yy33;
-      goto yy69;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy69;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy69;
-        goto yy33;
-      }
-    }
-  yy67:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy69;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy69;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy69;
-        goto yy33;
-      }
-    }
-  yy68:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy70;
-      if (yych <= '/')
-        goto yy33;
-      goto yy71;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy71;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy71;
-        goto yy33;
-      }
-    }
-  yy69:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy71;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy71;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy71;
-        goto yy33;
-      }
-    }
-  yy70:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy72;
-      if (yych <= '/')
-        goto yy33;
-      goto yy73;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy73;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy73;
-        goto yy33;
-      }
-    }
-  yy71:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy73;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy73;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy73;
-        goto yy33;
-      }
-    }
-  yy72:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy74;
-      if (yych <= '/')
-        goto yy33;
-      goto yy75;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy75;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy75;
-        goto yy33;
-      }
-    }
-  yy73:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy75;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy75;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy75;
-        goto yy33;
-      }
-    }
-  yy74:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy76;
-      if (yych <= '/')
-        goto yy33;
-      goto yy77;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy77;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy77;
-        goto yy33;
-      }
-    }
-  yy75:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy77;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy77;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy77;
-        goto yy33;
-      }
-    }
-  yy76:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy78;
-      if (yych <= '/')
-        goto yy33;
-      goto yy79;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy79;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy79;
-        goto yy33;
-      }
-    }
-  yy77:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy79;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy79;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy79;
-        goto yy33;
-      }
-    }
-  yy78:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy80;
-      if (yych <= '/')
-        goto yy33;
-      goto yy81;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy81;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy81;
-        goto yy33;
-      }
-    }
-  yy79:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy81;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy81;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy81;
-        goto yy33;
-      }
-    }
-  yy80:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy82;
-      if (yych <= '/')
-        goto yy33;
-      goto yy83;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy83;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy83;
-        goto yy33;
-      }
-    }
-  yy81:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy83;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy83;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy83;
-        goto yy33;
-      }
-    }
-  yy82:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy84;
-      if (yych <= '/')
-        goto yy33;
-      goto yy85;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy85;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy85;
-        goto yy33;
-      }
-    }
-  yy83:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy85;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy85;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy85;
-        goto yy33;
-      }
-    }
-  yy84:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy86;
-      if (yych <= '/')
-        goto yy33;
-      goto yy87;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy87;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy87;
-        goto yy33;
-      }
-    }
-  yy85:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy87;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy87;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy87;
-        goto yy33;
-      }
-    }
-  yy86:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy88;
-      if (yych <= '/')
-        goto yy33;
-      goto yy89;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy89;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy89;
-        goto yy33;
-      }
-    }
-  yy87:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy89;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy89;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy89;
-        goto yy33;
-      }
-    }
-  yy88:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy90;
-      if (yych <= '/')
-        goto yy33;
-      goto yy91;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy91;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy91;
-        goto yy33;
-      }
-    }
-  yy89:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy91;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy91;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy91;
-        goto yy33;
-      }
-    }
-  yy90:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy92;
-      if (yych <= '/')
-        goto yy33;
-      goto yy93;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy93;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy93;
-        goto yy33;
-      }
-    }
-  yy91:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy93;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy93;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy93;
-        goto yy33;
-      }
-    }
-  yy92:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy94;
-      if (yych <= '/')
-        goto yy33;
-      goto yy95;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy95;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy95;
-        goto yy33;
-      }
-    }
-  yy93:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy95;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy95;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy95;
-        goto yy33;
-      }
-    }
-  yy94:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy96;
-      if (yych <= '/')
-        goto yy33;
-      goto yy97;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy97;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy97;
-        goto yy33;
-      }
-    }
-  yy95:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy97;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy97;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy97;
-        goto yy33;
-      }
-    }
-  yy96:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy98;
-      if (yych <= '/')
-        goto yy33;
-      goto yy99;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy99;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy99;
-        goto yy33;
-      }
-    }
-  yy97:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy99;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy99;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy99;
-        goto yy33;
-      }
-    }
-  yy98:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy100;
-      if (yych <= '/')
-        goto yy33;
-      goto yy101;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy101;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy101;
-        goto yy33;
-      }
-    }
-  yy99:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy101;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy101;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy101;
-        goto yy33;
-      }
-    }
-  yy100:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy102;
-      if (yych <= '/')
-        goto yy33;
-      goto yy103;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy103;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy103;
-        goto yy33;
-      }
-    }
-  yy101:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy103;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy103;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy103;
-        goto yy33;
-      }
-    }
-  yy102:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy104;
-      if (yych <= '/')
-        goto yy33;
-      goto yy105;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy105;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy105;
-        goto yy33;
-      }
-    }
-  yy103:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy105;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy105;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy105;
-        goto yy33;
-      }
-    }
-  yy104:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy106;
-      if (yych <= '/')
-        goto yy33;
-      goto yy107;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy107;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy107;
-        goto yy33;
-      }
-    }
-  yy105:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy107;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy107;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy107;
-        goto yy33;
-      }
-    }
-  yy106:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy108;
-      if (yych <= '/')
-        goto yy33;
-      goto yy109;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy109;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy109;
-        goto yy33;
-      }
-    }
-  yy107:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy109;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy109;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy109;
-        goto yy33;
-      }
-    }
-  yy108:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy110;
-      if (yych <= '/')
-        goto yy33;
-      goto yy111;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy111;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy111;
-        goto yy33;
-      }
-    }
-  yy109:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy111;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy111;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy111;
-        goto yy33;
-      }
-    }
-  yy110:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy112;
-      if (yych <= '/')
-        goto yy33;
-      goto yy113;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy113;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy113;
-        goto yy33;
-      }
-    }
-  yy111:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy113;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy113;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy113;
-        goto yy33;
-      }
-    }
-  yy112:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy114;
-      if (yych <= '/')
-        goto yy33;
-      goto yy115;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy115;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy115;
-        goto yy33;
-      }
-    }
-  yy113:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy115;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy115;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy115;
-        goto yy33;
-      }
-    }
-  yy114:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy116;
-      if (yych <= '/')
-        goto yy33;
-      goto yy117;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy117;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy117;
-        goto yy33;
-      }
-    }
-  yy115:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy117;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy117;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy117;
-        goto yy33;
-      }
-    }
-  yy116:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy118;
-      if (yych <= '/')
-        goto yy33;
-      goto yy119;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy119;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy119;
-        goto yy33;
-      }
-    }
-  yy117:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy119;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy119;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy119;
-        goto yy33;
-      }
-    }
-  yy118:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy120;
-      if (yych <= '/')
-        goto yy33;
-      goto yy121;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy121;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy121;
-        goto yy33;
-      }
-    }
-  yy119:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy121;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy121;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy121;
-        goto yy33;
-      }
-    }
-  yy120:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy122;
-      if (yych <= '/')
-        goto yy33;
-      goto yy123;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy123;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy123;
-        goto yy33;
-      }
-    }
-  yy121:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy123;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy123;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy123;
-        goto yy33;
-      }
-    }
-  yy122:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy124;
-      if (yych <= '/')
-        goto yy33;
-      goto yy125;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy125;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy125;
-        goto yy33;
-      }
-    }
-  yy123:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy125;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy125;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy125;
-        goto yy33;
-      }
-    }
-  yy124:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy126;
-      if (yych <= '/')
-        goto yy33;
-      goto yy127;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy127;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy127;
-        goto yy33;
-      }
-    }
-  yy125:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy127;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy127;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy127;
-        goto yy33;
-      }
-    }
-  yy126:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy128;
-      if (yych <= '/')
-        goto yy33;
-      goto yy129;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy129;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy129;
-        goto yy33;
-      }
-    }
-  yy127:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy129;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy129;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy129;
-        goto yy33;
-      }
-    }
-  yy128:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy130;
-      if (yych <= '/')
-        goto yy33;
-      goto yy131;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy131;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy131;
-        goto yy33;
-      }
-    }
-  yy129:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy131;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy131;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy131;
-        goto yy33;
-      }
-    }
-  yy130:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy132;
-      if (yych <= '/')
-        goto yy33;
-      goto yy133;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy133;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy133;
-        goto yy33;
-      }
-    }
-  yy131:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy133;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy133;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy133;
-        goto yy33;
-      }
-    }
-  yy132:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy134;
-      if (yych <= '/')
-        goto yy33;
-      goto yy135;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy135;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy135;
-        goto yy33;
-      }
-    }
-  yy133:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy135;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy135;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy135;
-        goto yy33;
-      }
-    }
-  yy134:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy136;
-      if (yych <= '/')
-        goto yy33;
-      goto yy137;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy137;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy137;
-        goto yy33;
-      }
-    }
-  yy135:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy137;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy137;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy137;
-        goto yy33;
-      }
-    }
-  yy136:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy138;
-      if (yych <= '/')
-        goto yy33;
-      goto yy139;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy139;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy139;
-        goto yy33;
-      }
-    }
-  yy137:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy139;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy139;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy139;
-        goto yy33;
-      }
-    }
-  yy138:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy140;
-      if (yych <= '/')
-        goto yy33;
-      goto yy141;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy141;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy141;
-        goto yy33;
-      }
-    }
-  yy139:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy141;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy141;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy141;
-        goto yy33;
-      }
-    }
-  yy140:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy142;
-      if (yych <= '/')
-        goto yy33;
-      goto yy143;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy143;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy143;
-        goto yy33;
-      }
-    }
-  yy141:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy143;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy143;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy143;
-        goto yy33;
-      }
-    }
-  yy142:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy144;
-      if (yych <= '/')
-        goto yy33;
-      goto yy145;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy145;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy145;
-        goto yy33;
-      }
-    }
-  yy143:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy145;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy145;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy145;
-        goto yy33;
-      }
-    }
-  yy144:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy146;
-      if (yych <= '/')
-        goto yy33;
-      goto yy147;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy147;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy147;
-        goto yy33;
-      }
-    }
-  yy145:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy147;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy147;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy147;
-        goto yy33;
-      }
-    }
-  yy146:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy148;
-      if (yych <= '/')
-        goto yy33;
-      goto yy149;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy149;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy149;
-        goto yy33;
-      }
-    }
-  yy147:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy149;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy149;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy149;
-        goto yy33;
-      }
-    }
-  yy148:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy150;
-      if (yych <= '/')
-        goto yy33;
-      goto yy151;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy151;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy151;
-        goto yy33;
-      }
-    }
-  yy149:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy151;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy151;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy151;
-        goto yy33;
-      }
-    }
-  yy150:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy152;
-      if (yych <= '/')
-        goto yy33;
-      goto yy153;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy153;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy153;
-        goto yy33;
-      }
-    }
-  yy151:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy153;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy153;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy153;
-        goto yy33;
-      }
-    }
-  yy152:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy154;
-      if (yych <= '/')
-        goto yy33;
-      goto yy155;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy155;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy155;
-        goto yy33;
-      }
-    }
-  yy153:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy155;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy155;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy155;
-        goto yy33;
-      }
-    }
-  yy154:
-    yych = *++p;
-    if (yych <= '9') {
-      if (yych == '-')
-        goto yy156;
-      if (yych <= '/')
-        goto yy33;
-      goto yy157;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy33;
-        goto yy157;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy157;
-        goto yy33;
-      }
-    }
-  yy155:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= ',')
-          goto yy33;
-        if (yych >= '.')
-          goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych <= '9')
-          goto yy157;
-        goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-        goto yy157;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych <= 'z')
-          goto yy157;
-        goto yy33;
-      }
-    }
-  yy156:
-    yych = *++p;
-    if (yych <= '@') {
-      if (yych <= '/')
-        goto yy33;
-      if (yych <= '9')
-        goto yy158;
-      goto yy33;
-    } else {
-      if (yych <= 'Z')
-        goto yy158;
-      if (yych <= '`')
-        goto yy33;
-      if (yych <= 'z')
-        goto yy158;
-      goto yy33;
-    }
-  yy157:
-    yych = *++p;
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych <= '-')
-          goto yy33;
-        goto yy34;
-      } else {
-        if (yych <= '/')
-          goto yy33;
-        if (yych >= ':')
-          goto yy33;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy37;
-        if (yych <= '@')
-          goto yy33;
-      } else {
-        if (yych <= '`')
-          goto yy33;
-        if (yych >= '{')
-          goto yy33;
-      }
-    }
-  yy158:
-    yych = *++p;
-    if (yych == '.')
-      goto yy34;
-    if (yych == '>')
-      goto yy37;
-    goto yy33;
-  }
-}
-
-// Try to match an HTML tag after first <, returning num of chars matched.
-bufsize_t _scan_html_tag(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    static const unsigned char yybm[] = {
-        0,   224, 224, 224, 224, 224, 224, 224, 224, 200, 200, 200, 200, 200,
-        224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
-        224, 224, 224, 224, 200, 224, 128, 224, 224, 224, 224, 64,  224, 224,
-        224, 224, 224, 244, 240, 224, 244, 244, 244, 244, 244, 244, 244, 244,
-        244, 244, 240, 224, 192, 192, 192, 224, 224, 244, 244, 244, 244, 244,
-        244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244,
-        244, 244, 244, 244, 244, 244, 244, 224, 224, 224, 224, 240, 192, 244,
-        244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244,
-        244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 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 <= '@') {
-      if (yych == '/')
-        goto yy162;
-    } else {
-      if (yych <= 'Z')
-        goto yy163;
-      if (yych <= '`')
-        goto yy160;
-      if (yych <= 'z')
-        goto yy163;
-    }
-  yy160:
-    ++p;
-  yy161 : { return 0; }
-  yy162:
-    yych = *(marker = ++p);
-    if (yych <= '@')
-      goto yy161;
-    if (yych <= 'Z')
-      goto yy164;
-    if (yych <= '`')
-      goto yy161;
-    if (yych <= 'z')
-      goto yy164;
-    goto yy161;
-  yy163:
-    yych = *(marker = ++p);
-    if (yych <= '.') {
-      if (yych <= 0x1F) {
-        if (yych <= 0x08)
-          goto yy161;
-        if (yych <= '\r')
-          goto yy168;
-        goto yy161;
-      } else {
-        if (yych <= ' ')
-          goto yy168;
-        if (yych == '-')
-          goto yy168;
-        goto yy161;
-      }
-    } else {
-      if (yych <= '@') {
-        if (yych <= '9')
-          goto yy168;
-        if (yych == '>')
-          goto yy168;
-        goto yy161;
-      } else {
-        if (yych <= 'Z')
-          goto yy168;
-        if (yych <= '`')
-          goto yy161;
-        if (yych <= 'z')
-          goto yy168;
-        goto yy161;
-      }
-    }
-  yy164:
-    yych = *++p;
-    if (yybm[0 + yych] & 4) {
-      goto yy164;
-    }
-    if (yych <= 0x1F) {
-      if (yych <= 0x08)
-        goto yy165;
-      if (yych <= '\r')
-        goto yy171;
-    } else {
-      if (yych <= ' ')
-        goto yy171;
-      if (yych == '>')
-        goto yy170;
-    }
-  yy165:
-    p = marker;
-    goto yy161;
-  yy166:
-    yych = *++p;
-    if (yybm[0 + yych] & 8) {
-      goto yy166;
-    }
-    if (yych <= '>') {
-      if (yych <= '9') {
-        if (yych == '/')
-          goto yy169;
-        goto yy165;
-      } else {
-        if (yych <= ':')
-          goto yy172;
-        if (yych <= '=')
-          goto yy165;
-        goto yy170;
-      }
-    } else {
-      if (yych <= '^') {
-        if (yych <= '@')
-          goto yy165;
-        if (yych <= 'Z')
-          goto yy172;
-        goto yy165;
-      } else {
-        if (yych == '`')
-          goto yy165;
-        if (yych <= 'z')
-          goto yy172;
-        goto yy165;
-      }
-    }
-  yy167:
-    yych = *++p;
-  yy168:
-    if (yybm[0 + yych] & 8) {
-      goto yy166;
-    }
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych == '-')
-          goto yy167;
-        goto yy165;
-      } else {
-        if (yych <= '/')
-          goto yy169;
-        if (yych <= '9')
-          goto yy167;
-        goto yy165;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy170;
-        if (yych <= '@')
-          goto yy165;
-        goto yy167;
-      } else {
-        if (yych <= '`')
-          goto yy165;
-        if (yych <= 'z')
-          goto yy167;
-        goto yy165;
-      }
-    }
-  yy169:
-    yych = *++p;
-    if (yych != '>')
-      goto yy165;
-  yy170:
-    ++p;
-    { return (bufsize_t)(p - start); }
-  yy171:
-    yych = *++p;
-    if (yych <= 0x1F) {
-      if (yych <= 0x08)
-        goto yy165;
-      if (yych <= '\r')
-        goto yy171;
-      goto yy165;
-    } else {
-      if (yych <= ' ')
-        goto yy171;
-      if (yych == '>')
-        goto yy170;
-      goto yy165;
-    }
-  yy172:
-    yych = *++p;
-    if (yybm[0 + yych] & 16) {
-      goto yy172;
-    }
-    if (yych <= ',') {
-      if (yych <= '\r') {
-        if (yych <= 0x08)
-          goto yy165;
-      } else {
-        if (yych != ' ')
-          goto yy165;
-      }
-    } else {
-      if (yych <= '<') {
-        if (yych <= '/')
-          goto yy169;
-        goto yy165;
-      } else {
-        if (yych <= '=')
-          goto yy174;
-        if (yych <= '>')
-          goto yy170;
-        goto yy165;
-      }
-    }
-  yy173:
-    yych = *++p;
-    if (yych <= '<') {
-      if (yych <= ' ') {
-        if (yych <= 0x08)
-          goto yy165;
-        if (yych <= '\r')
-          goto yy173;
-        if (yych <= 0x1F)
-          goto yy165;
-        goto yy173;
-      } else {
-        if (yych <= '/') {
-          if (yych <= '.')
-            goto yy165;
-          goto yy169;
-        } else {
-          if (yych == ':')
-            goto yy172;
-          goto yy165;
-        }
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '=')
-          goto yy174;
-        if (yych <= '>')
-          goto yy170;
-        if (yych <= '@')
-          goto yy165;
-        goto yy172;
-      } else {
-        if (yych <= '_') {
-          if (yych <= '^')
-            goto yy165;
-          goto yy172;
-        } else {
-          if (yych <= '`')
-            goto yy165;
-          if (yych <= 'z')
-            goto yy172;
-          goto yy165;
-        }
-      }
-    }
-  yy174:
-    yych = *++p;
-    if (yybm[0 + yych] & 32) {
-      goto yy175;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '"') {
-        if (yych <= 0x00)
-          goto yy165;
-        if (yych <= ' ')
-          goto yy174;
-        goto yy176;
-      } else {
-        if (yych <= '\'')
-          goto yy177;
-        if (yych <= 0xC1)
-          goto yy165;
-        if (yych <= 0xDF)
-          goto yy178;
-        goto yy179;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy181;
-        goto yy180;
-      } else {
-        if (yych <= 0xF0)
-          goto yy182;
-        if (yych <= 0xF3)
-          goto yy183;
-        if (yych <= 0xF4)
-          goto yy184;
-        goto yy165;
-      }
-    }
-  yy175:
-    yych = *++p;
-    if (yybm[0 + yych] & 32) {
-      goto yy175;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '=') {
-        if (yych <= 0x00)
-          goto yy165;
-        if (yych <= ' ')
-          goto yy166;
-        goto yy165;
-      } else {
-        if (yych <= '>')
-          goto yy170;
-        if (yych <= 0xC1)
-          goto yy165;
-        if (yych <= 0xDF)
-          goto yy178;
-        goto yy179;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy181;
-        goto yy180;
-      } else {
-        if (yych <= 0xF0)
-          goto yy182;
-        if (yych <= 0xF3)
-          goto yy183;
-        if (yych <= 0xF4)
-          goto yy184;
-        goto yy165;
-      }
-    }
-  yy176:
-    yych = *++p;
-    if (yybm[0 + yych] & 64) {
-      goto yy176;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy165;
-        if (yych <= '"')
-          goto yy185;
-        goto yy165;
-      } else {
-        if (yych <= 0xDF)
-          goto yy186;
-        if (yych <= 0xE0)
-          goto yy187;
-        goto yy188;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy189;
-        if (yych <= 0xEF)
-          goto yy188;
-        goto yy190;
-      } else {
-        if (yych <= 0xF3)
-          goto yy191;
-        if (yych <= 0xF4)
-          goto yy192;
-        goto yy165;
-      }
-    }
-  yy177:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy177;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy165;
-        if (yych <= '\'')
-          goto yy185;
-        goto yy165;
-      } else {
-        if (yych <= 0xDF)
-          goto yy193;
-        if (yych <= 0xE0)
-          goto yy194;
-        goto yy195;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy196;
-        if (yych <= 0xEF)
-          goto yy195;
-        goto yy197;
-      } else {
-        if (yych <= 0xF3)
-          goto yy198;
-        if (yych <= 0xF4)
-          goto yy199;
-        goto yy165;
-      }
-    }
-  yy178:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy175;
-    goto yy165;
-  yy179:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy178;
-    goto yy165;
-  yy180:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy178;
-    goto yy165;
-  yy181:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0x9F)
-      goto yy178;
-    goto yy165;
-  yy182:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy180;
-    goto yy165;
-  yy183:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy180;
-    goto yy165;
-  yy184:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0x8F)
-      goto yy180;
-    goto yy165;
-  yy185:
-    yych = *++p;
-    if (yybm[0 + yych] & 8) {
-      goto yy166;
-    }
-    if (yych == '/')
-      goto yy169;
-    if (yych == '>')
-      goto yy170;
-    goto yy165;
-  yy186:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy176;
-    goto yy165;
-  yy187:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy186;
-    goto yy165;
-  yy188:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy186;
-    goto yy165;
-  yy189:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0x9F)
-      goto yy186;
-    goto yy165;
-  yy190:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy188;
-    goto yy165;
-  yy191:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy188;
-    goto yy165;
-  yy192:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0x8F)
-      goto yy188;
-    goto yy165;
-  yy193:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy177;
-    goto yy165;
-  yy194:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy193;
-    goto yy165;
-  yy195:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy193;
-    goto yy165;
-  yy196:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0x9F)
-      goto yy193;
-    goto yy165;
-  yy197:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy195;
-    goto yy165;
-  yy198:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0xBF)
-      goto yy195;
-    goto yy165;
-  yy199:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy165;
-    if (yych <= 0x8F)
-      goto yy195;
-    goto yy165;
-  }
-}
-
-// 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 yy201;
-        if (yych <= '\t')
-          goto yy203;
-      } else {
-        if (yych <= 0x7F)
-          goto yy203;
-        if (yych <= 0xC1)
-          goto yy201;
-        if (yych <= 0xDF)
-          goto yy204;
-        goto yy205;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy207;
-        goto yy206;
-      } else {
-        if (yych <= 0xF0)
-          goto yy208;
-        if (yych <= 0xF3)
-          goto yy209;
-        if (yych <= 0xF4)
-          goto yy210;
-      }
-    }
-  yy201:
-    ++p;
-  yy202 : { return 0; }
-  yy203:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= '\n') {
-      if (yych <= 0x00)
-        goto yy202;
-      if (yych <= '\t')
-        goto yy212;
-      goto yy202;
-    } else {
-      if (yych <= 0x7F)
-        goto yy212;
-      if (yych <= 0xC1)
-        goto yy202;
-      if (yych <= 0xF4)
-        goto yy212;
-      goto yy202;
-    }
-  yy204:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy202;
-    if (yych <= 0xBF)
-      goto yy211;
-    goto yy202;
-  yy205:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x9F)
-      goto yy202;
-    if (yych <= 0xBF)
-      goto yy216;
-    goto yy202;
-  yy206:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy202;
-    if (yych <= 0xBF)
-      goto yy216;
-    goto yy202;
-  yy207:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy202;
-    if (yych <= 0x9F)
-      goto yy216;
-    goto yy202;
-  yy208:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x8F)
-      goto yy202;
-    if (yych <= 0xBF)
-      goto yy218;
-    goto yy202;
-  yy209:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy202;
-    if (yych <= 0xBF)
-      goto yy218;
-    goto yy202;
-  yy210:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy202;
-    if (yych <= 0x8F)
-      goto yy218;
-    goto yy202;
-  yy211:
-    yych = *++p;
-  yy212:
-    if (yybm[0 + yych] & 64) {
-      goto yy211;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy213;
-        if (yych <= '>')
-          goto yy214;
-      } else {
-        if (yych <= 0xDF)
-          goto yy216;
-        if (yych <= 0xE0)
-          goto yy217;
-        goto yy218;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy219;
-        if (yych <= 0xEF)
-          goto yy218;
-        goto yy220;
-      } else {
-        if (yych <= 0xF3)
-          goto yy221;
-        if (yych <= 0xF4)
-          goto yy222;
-      }
-    }
-  yy213:
-    p = marker;
-    if (yyaccept == 0) {
-      goto yy202;
-    } else {
-      goto yy215;
-    }
-  yy214:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 64) {
-      goto yy211;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy215;
-        if (yych <= '>')
-          goto yy214;
-      } else {
-        if (yych <= 0xDF)
-          goto yy216;
-        if (yych <= 0xE0)
-          goto yy217;
-        goto yy218;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy219;
-        if (yych <= 0xEF)
-          goto yy218;
-        goto yy220;
-      } else {
-        if (yych <= 0xF3)
-          goto yy221;
-        if (yych <= 0xF4)
-          goto yy222;
-      }
-    }
-  yy215 : { return (bufsize_t)(p - start); }
-  yy216:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy213;
-    if (yych <= 0xBF)
-      goto yy211;
-    goto yy213;
-  yy217:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy213;
-    if (yych <= 0xBF)
-      goto yy216;
-    goto yy213;
-  yy218:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy213;
-    if (yych <= 0xBF)
-      goto yy216;
-    goto yy213;
-  yy219:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy213;
-    if (yych <= 0x9F)
-      goto yy216;
-    goto yy213;
-  yy220:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy213;
-    if (yych <= 0xBF)
-      goto yy218;
-    goto yy213;
-  yy221:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy213;
-    if (yych <= 0xBF)
-      goto yy218;
-    goto yy213;
-  yy222:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy213;
-    if (yych <= 0x8F)
-      goto yy218;
-    goto yy213;
-  }
-}
-
-bufsize_t _scan_html_comment(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    static const unsigned char yybm[] = {
-        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, 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, 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 yy225;
-    ++p;
-  yy224 : { return 0; }
-  yy225:
-    yych = *(marker = ++p);
-    if (yych != '-')
-      goto yy224;
-  yy226:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy226;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy227;
-        if (yych <= '-')
-          goto yy228;
-      } else {
-        if (yych <= 0xDF)
-          goto yy229;
-        if (yych <= 0xE0)
-          goto yy230;
-        goto yy231;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy232;
-        if (yych <= 0xEF)
-          goto yy231;
-        goto yy233;
-      } else {
-        if (yych <= 0xF3)
-          goto yy234;
-        if (yych <= 0xF4)
-          goto yy235;
-      }
-    }
-  yy227:
-    p = marker;
-    goto yy224;
-  yy228:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy226;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy227;
-        if (yych <= '-')
-          goto yy236;
-        goto yy227;
-      } else {
-        if (yych <= 0xDF)
-          goto yy229;
-        if (yych <= 0xE0)
-          goto yy230;
-        goto yy231;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy232;
-        if (yych <= 0xEF)
-          goto yy231;
-        goto yy233;
-      } else {
-        if (yych <= 0xF3)
-          goto yy234;
-        if (yych <= 0xF4)
-          goto yy235;
-        goto yy227;
-      }
-    }
-  yy229:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy227;
-    if (yych <= 0xBF)
-      goto yy226;
-    goto yy227;
-  yy230:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy227;
-    if (yych <= 0xBF)
-      goto yy229;
-    goto yy227;
-  yy231:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy227;
-    if (yych <= 0xBF)
-      goto yy229;
-    goto yy227;
-  yy232:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy227;
-    if (yych <= 0x9F)
-      goto yy229;
-    goto yy227;
-  yy233:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy227;
-    if (yych <= 0xBF)
-      goto yy231;
-    goto yy227;
-  yy234:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy227;
-    if (yych <= 0xBF)
-      goto yy231;
-    goto yy227;
-  yy235:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy227;
-    if (yych <= 0x8F)
-      goto yy231;
-    goto yy227;
-  yy236:
-    yych = *++p;
-    if (yych <= 0xE0) {
-      if (yych <= '>') {
-        if (yych <= 0x00)
-          goto yy227;
-        if (yych <= '=')
-          goto yy226;
-      } else {
-        if (yych <= 0x7F)
-          goto yy226;
-        if (yych <= 0xC1)
-          goto yy227;
-        if (yych <= 0xDF)
-          goto yy229;
-        goto yy230;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy232;
-        goto yy231;
-      } else {
-        if (yych <= 0xF0)
-          goto yy233;
-        if (yych <= 0xF3)
-          goto yy234;
-        if (yych <= 0xF4)
-          goto yy235;
-        goto yy227;
-      }
-    }
-    ++p;
-    { return (bufsize_t)(p - start); }
-  }
-}
-
-bufsize_t _scan_html_pi(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, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 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, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 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] & 128) {
-      goto yy240;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy238;
-        if (yych <= '?')
-          goto yy243;
-      } else {
-        if (yych <= 0xDF)
-          goto yy244;
-        if (yych <= 0xE0)
-          goto yy245;
-        goto yy246;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy247;
-        if (yych <= 0xEF)
-          goto yy246;
-        goto yy248;
-      } else {
-        if (yych <= 0xF3)
-          goto yy249;
-        if (yych <= 0xF4)
-          goto yy250;
-      }
-    }
-  yy238:
-    ++p;
-  yy239 : { return 0; }
-  yy240:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-  yy241:
-    if (yybm[0 + yych] & 128) {
-      goto yy240;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy242;
-        if (yych <= '?')
-          goto yy251;
-      } else {
-        if (yych <= 0xDF)
-          goto yy253;
-        if (yych <= 0xE0)
-          goto yy254;
-        goto yy255;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy256;
-        if (yych <= 0xEF)
-          goto yy255;
-        goto yy257;
-      } else {
-        if (yych <= 0xF3)
-          goto yy258;
-        if (yych <= 0xF4)
-          goto yy259;
-      }
-    }
-  yy242 : { return (bufsize_t)(p - start); }
-  yy243:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yych <= '?') {
-      if (yych <= 0x00)
-        goto yy239;
-      if (yych <= '=')
-        goto yy241;
-      if (yych <= '>')
-        goto yy239;
-      goto yy240;
-    } else {
-      if (yych <= 0x7F)
-        goto yy241;
-      if (yych <= 0xC1)
-        goto yy239;
-      if (yych <= 0xF4)
-        goto yy241;
-      goto yy239;
-    }
-  yy244:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy239;
-    if (yych <= 0xBF)
-      goto yy240;
-    goto yy239;
-  yy245:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yych <= 0x9F)
-      goto yy239;
-    if (yych <= 0xBF)
-      goto yy253;
-    goto yy239;
-  yy246:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy239;
-    if (yych <= 0xBF)
-      goto yy253;
-    goto yy239;
-  yy247:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy239;
-    if (yych <= 0x9F)
-      goto yy253;
-    goto yy239;
-  yy248:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yych <= 0x8F)
-      goto yy239;
-    if (yych <= 0xBF)
-      goto yy255;
-    goto yy239;
-  yy249:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy239;
-    if (yych <= 0xBF)
-      goto yy255;
-    goto yy239;
-  yy250:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy239;
-    if (yych <= 0x8F)
-      goto yy255;
-    goto yy239;
-  yy251:
-    yych = *++p;
-    if (yych <= 0xE0) {
-      if (yych <= '>') {
-        if (yych <= 0x00)
-          goto yy252;
-        if (yych <= '=')
-          goto yy240;
-      } else {
-        if (yych <= 0x7F)
-          goto yy240;
-        if (yych <= 0xC1)
-          goto yy252;
-        if (yych <= 0xDF)
-          goto yy253;
-        goto yy254;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy256;
-        goto yy255;
-      } else {
-        if (yych <= 0xF0)
-          goto yy257;
-        if (yych <= 0xF3)
-          goto yy258;
-        if (yych <= 0xF4)
-          goto yy259;
-      }
-    }
-  yy252:
-    p = marker;
-    if (yyaccept == 0) {
-      goto yy242;
-    } else {
-      goto yy239;
-    }
-  yy253:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy252;
-    if (yych <= 0xBF)
-      goto yy240;
-    goto yy252;
-  yy254:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy252;
-    if (yych <= 0xBF)
-      goto yy253;
-    goto yy252;
-  yy255:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy252;
-    if (yych <= 0xBF)
-      goto yy253;
-    goto yy252;
-  yy256:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy252;
-    if (yych <= 0x9F)
-      goto yy253;
-    goto yy252;
-  yy257:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy252;
-    if (yych <= 0xBF)
-      goto yy255;
-    goto yy252;
-  yy258:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy252;
-    if (yych <= 0xBF)
-      goto yy255;
-    goto yy252;
-  yy259:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy252;
-    if (yych <= 0x8F)
-      goto yy255;
-    goto yy252;
-  }
-}
-
-bufsize_t _scan_html_declaration(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,  64,  64,  64,  64,
-        64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,
-        64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  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,  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, 64,  64,  64,  64,  64,  64,  64,
-        64,  64,  64,  64,  64,  64,  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 yy261;
-    if (yych <= 'Z')
-      goto yy263;
-  yy261:
-    ++p;
-  yy262 : { return 0; }
-  yy263:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 128) {
-      goto yy266;
-    }
-    if (yych <= 0x08)
-      goto yy262;
-    if (yych <= '\r')
-      goto yy264;
-    if (yych != ' ')
-      goto yy262;
-  yy264:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 64) {
-      goto yy264;
-    }
-    if (yych <= 0xED) {
-      if (yych <= 0xDF) {
-        if (yych >= 0xC2)
-          goto yy268;
-      } else {
-        if (yych <= 0xE0)
-          goto yy269;
-        if (yych <= 0xEC)
-          goto yy270;
-        goto yy271;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xEF)
-          goto yy270;
-        goto yy272;
-      } else {
-        if (yych <= 0xF3)
-          goto yy273;
-        if (yych <= 0xF4)
-          goto yy274;
-      }
-    }
-  yy265 : { return (bufsize_t)(p - start); }
-  yy266:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy266;
-    }
-    if (yych <= 0x08)
-      goto yy267;
-    if (yych <= '\r')
-      goto yy264;
-    if (yych == ' ')
-      goto yy264;
-  yy267:
-    p = marker;
-    if (yyaccept == 0) {
-      goto yy262;
-    } else {
-      goto yy265;
-    }
-  yy268:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy267;
-    if (yych <= 0xBF)
-      goto yy264;
-    goto yy267;
-  yy269:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy267;
-    if (yych <= 0xBF)
-      goto yy268;
-    goto yy267;
-  yy270:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy267;
-    if (yych <= 0xBF)
-      goto yy268;
-    goto yy267;
-  yy271:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy267;
-    if (yych <= 0x9F)
-      goto yy268;
-    goto yy267;
-  yy272:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy267;
-    if (yych <= 0xBF)
-      goto yy270;
-    goto yy267;
-  yy273:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy267;
-    if (yych <= 0xBF)
-      goto yy270;
-    goto yy267;
-  yy274:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy267;
-    if (yych <= 0x8F)
-      goto yy270;
-    goto yy267;
-  }
-}
-
-bufsize_t _scan_html_cdata(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, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 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, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 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 == 'C')
-      goto yy277;
-    if (yych == 'c')
-      goto yy277;
-    ++p;
-  yy276 : { return 0; }
-  yy277:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych == 'D')
-      goto yy278;
-    if (yych != 'd')
-      goto yy276;
-  yy278:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy280;
-    if (yych == 'a')
-      goto yy280;
-  yy279:
-    p = marker;
-    if (yyaccept == 0) {
-      goto yy276;
-    } else {
-      goto yy284;
-    }
-  yy280:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy281;
-    if (yych != 't')
-      goto yy279;
-  yy281:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy282;
-    if (yych != 'a')
-      goto yy279;
-  yy282:
-    yych = *++p;
-    if (yych != '[')
-      goto yy279;
-  yy283:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 128) {
-      goto yy283;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy284;
-        if (yych <= ']')
-          goto yy285;
-      } else {
-        if (yych <= 0xDF)
-          goto yy286;
-        if (yych <= 0xE0)
-          goto yy287;
-        goto yy288;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy289;
-        if (yych <= 0xEF)
-          goto yy288;
-        goto yy290;
-      } else {
-        if (yych <= 0xF3)
-          goto yy291;
-        if (yych <= 0xF4)
-          goto yy292;
-      }
-    }
-  yy284 : { return (bufsize_t)(p - start); }
-  yy285:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy283;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy279;
-        if (yych <= ']')
-          goto yy293;
-        goto yy279;
-      } else {
-        if (yych <= 0xDF)
-          goto yy286;
-        if (yych <= 0xE0)
-          goto yy287;
-        goto yy288;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy289;
-        if (yych <= 0xEF)
-          goto yy288;
-        goto yy290;
-      } else {
-        if (yych <= 0xF3)
-          goto yy291;
-        if (yych <= 0xF4)
-          goto yy292;
-        goto yy279;
-      }
-    }
-  yy286:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy279;
-    if (yych <= 0xBF)
-      goto yy283;
-    goto yy279;
-  yy287:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy279;
-    if (yych <= 0xBF)
-      goto yy286;
-    goto yy279;
-  yy288:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy279;
-    if (yych <= 0xBF)
-      goto yy286;
-    goto yy279;
-  yy289:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy279;
-    if (yych <= 0x9F)
-      goto yy286;
-    goto yy279;
-  yy290:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy279;
-    if (yych <= 0xBF)
-      goto yy288;
-    goto yy279;
-  yy291:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy279;
-    if (yych <= 0xBF)
-      goto yy288;
-    goto yy279;
-  yy292:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy279;
-    if (yych <= 0x8F)
-      goto yy288;
-    goto yy279;
-  yy293:
-    yych = *++p;
-    if (yych <= 0xE0) {
-      if (yych <= '>') {
-        if (yych <= 0x00)
-          goto yy279;
-        if (yych <= '=')
-          goto yy283;
-        goto yy279;
-      } else {
-        if (yych <= 0x7F)
-          goto yy283;
-        if (yych <= 0xC1)
-          goto yy279;
-        if (yych <= 0xDF)
-          goto yy286;
-        goto yy287;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy289;
-        goto yy288;
-      } else {
-        if (yych <= 0xF0)
-          goto yy290;
-        if (yych <= 0xF3)
-          goto yy291;
-        if (yych <= 0xF4)
-          goto yy292;
-        goto yy279;
-      }
-    }
-  }
-}
-
-// Try to match an HTML block tag start line, returning
-// an integer code for the type of block (1-6, matching the spec).
-// #7 is handled by a separate function, below.
-bufsize_t _scan_html_block_start(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-
-  {
-    unsigned char yych;
-    yych = *p;
-    if (yych == '<')
-      goto yy296;
-    ++p;
-  yy295 : { return 0; }
-  yy296:
-    yych = *(marker = ++p);
-    switch (yych) {
-    case '!':
-      goto yy297;
-    case '/':
-      goto yy299;
-    case '?':
-      goto yy300;
-    case 'A':
-    case 'a':
-      goto yy301;
-    case 'B':
-    case 'b':
-      goto yy302;
-    case 'C':
-    case 'c':
-      goto yy303;
-    case 'D':
-    case 'd':
-      goto yy304;
-    case 'F':
-    case 'f':
-      goto yy305;
-    case 'H':
-    case 'h':
-      goto yy306;
-    case 'I':
-    case 'i':
-      goto yy307;
-    case 'L':
-    case 'l':
-      goto yy308;
-    case 'M':
-    case 'm':
-      goto yy309;
-    case 'N':
-    case 'n':
-      goto yy310;
-    case 'O':
-    case 'o':
-      goto yy311;
-    case 'P':
-    case 'p':
-      goto yy312;
-    case 'S':
-    case 's':
-      goto yy313;
-    case 'T':
-    case 't':
-      goto yy314;
-    case 'U':
-    case 'u':
-      goto yy315;
-    default:
-      goto yy295;
-    }
-  yy297:
-    yych = *++p;
-    if (yych <= '@') {
-      if (yych == '-')
-        goto yy316;
-    } else {
-      if (yych <= 'Z')
-        goto yy317;
-      if (yych <= '[')
-        goto yy318;
-    }
-  yy298:
-    p = marker;
-    goto yy295;
-  yy299:
-    yych = *++p;
-    switch (yych) {
-    case 'A':
-    case 'a':
-      goto yy301;
-    case 'B':
-    case 'b':
-      goto yy302;
-    case 'C':
-    case 'c':
-      goto yy303;
-    case 'D':
-    case 'd':
-      goto yy304;
-    case 'F':
-    case 'f':
-      goto yy305;
-    case 'H':
-    case 'h':
-      goto yy306;
-    case 'I':
-    case 'i':
-      goto yy307;
-    case 'L':
-    case 'l':
-      goto yy308;
-    case 'M':
-    case 'm':
-      goto yy309;
-    case 'N':
-    case 'n':
-      goto yy310;
-    case 'O':
-    case 'o':
-      goto yy311;
-    case 'P':
-    case 'p':
-      goto yy319;
-    case 'S':
-    case 's':
-      goto yy320;
-    case 'T':
-    case 't':
-      goto yy321;
-    case 'U':
-    case 'u':
-      goto yy315;
-    default:
-      goto yy298;
-    }
-  yy300:
-    ++p;
-    { return 3; }
-  yy301:
-    yych = *++p;
-    if (yych <= 'S') {
-      if (yych <= 'D') {
-        if (yych <= 'C')
-          goto yy298;
-        goto yy322;
-      } else {
-        if (yych <= 'Q')
-          goto yy298;
-        if (yych <= 'R')
-          goto yy323;
-        goto yy324;
-      }
-    } else {
-      if (yych <= 'q') {
-        if (yych == 'd')
-          goto yy322;
-        goto yy298;
-      } else {
-        if (yych <= 'r')
-          goto yy323;
-        if (yych <= 's')
-          goto yy324;
-        goto yy298;
-      }
-    }
-  yy302:
-    yych = *++p;
-    if (yych <= 'O') {
-      if (yych <= 'K') {
-        if (yych == 'A')
-          goto yy325;
-        goto yy298;
-      } else {
-        if (yych <= 'L')
-          goto yy326;
-        if (yych <= 'N')
-          goto yy298;
-        goto yy327;
-      }
-    } else {
-      if (yych <= 'k') {
-        if (yych == 'a')
-          goto yy325;
-        goto yy298;
-      } else {
-        if (yych <= 'l')
-          goto yy326;
-        if (yych == 'o')
-          goto yy327;
-        goto yy298;
-      }
-    }
-  yy303:
-    yych = *++p;
-    if (yych <= 'O') {
-      if (yych <= 'D') {
-        if (yych == 'A')
-          goto yy328;
-        goto yy298;
-      } else {
-        if (yych <= 'E')
-          goto yy329;
-        if (yych <= 'N')
-          goto yy298;
-        goto yy330;
-      }
-    } else {
-      if (yych <= 'd') {
-        if (yych == 'a')
-          goto yy328;
-        goto yy298;
-      } else {
-        if (yych <= 'e')
-          goto yy329;
-        if (yych == 'o')
-          goto yy330;
-        goto yy298;
-      }
-    }
-  yy304:
-    yych = *++p;
-    switch (yych) {
-    case 'D':
-    case 'L':
-    case 'T':
-    case 'd':
-    case 'l':
-    case 't':
-      goto yy331;
-    case 'E':
-    case 'e':
-      goto yy332;
-    case 'I':
-    case 'i':
-      goto yy333;
-    default:
-      goto yy298;
-    }
-  yy305:
-    yych = *++p;
-    if (yych <= 'R') {
-      if (yych <= 'N') {
-        if (yych == 'I')
-          goto yy334;
-        goto yy298;
-      } else {
-        if (yych <= 'O')
-          goto yy335;
-        if (yych <= 'Q')
-          goto yy298;
-        goto yy336;
-      }
-    } else {
-      if (yych <= 'n') {
-        if (yych == 'i')
-          goto yy334;
-        goto yy298;
-      } else {
-        if (yych <= 'o')
-          goto yy335;
-        if (yych == 'r')
-          goto yy336;
-        goto yy298;
-      }
-    }
-  yy306:
-    yych = *++p;
-    if (yych <= 'S') {
-      if (yych <= 'D') {
-        if (yych <= '0')
-          goto yy298;
-        if (yych <= '6')
-          goto yy331;
-        goto yy298;
-      } else {
-        if (yych <= 'E')
-          goto yy337;
-        if (yych == 'R')
-          goto yy331;
-        goto yy298;
-      }
-    } else {
-      if (yych <= 'q') {
-        if (yych <= 'T')
-          goto yy338;
-        if (yych == 'e')
-          goto yy337;
-        goto yy298;
-      } else {
-        if (yych <= 'r')
-          goto yy331;
-        if (yych == 't')
-          goto yy338;
-        goto yy298;
-      }
-    }
-  yy307:
-    yych = *++p;
-    if (yych == 'F')
-      goto yy339;
-    if (yych == 'f')
-      goto yy339;
-    goto yy298;
-  yy308:
-    yych = *++p;
-    if (yych <= 'I') {
-      if (yych == 'E')
-        goto yy340;
-      if (yych <= 'H')
-        goto yy298;
-      goto yy341;
-    } else {
-      if (yych <= 'e') {
-        if (yych <= 'd')
-          goto yy298;
-        goto yy340;
-      } else {
-        if (yych == 'i')
-          goto yy341;
-        goto yy298;
-      }
-    }
-  yy309:
-    yych = *++p;
-    if (yych <= 'E') {
-      if (yych == 'A')
-        goto yy342;
-      if (yych <= 'D')
-        goto yy298;
-      goto yy343;
-    } else {
-      if (yych <= 'a') {
-        if (yych <= '`')
-          goto yy298;
-        goto yy342;
-      } else {
-        if (yych == 'e')
-          goto yy343;
-        goto yy298;
-      }
-    }
-  yy310:
-    yych = *++p;
-    if (yych <= 'O') {
-      if (yych == 'A')
-        goto yy344;
-      if (yych <= 'N')
-        goto yy298;
-      goto yy345;
-    } else {
-      if (yych <= 'a') {
-        if (yych <= '`')
-          goto yy298;
-        goto yy344;
-      } else {
-        if (yych == 'o')
-          goto yy345;
-        goto yy298;
-      }
-    }
-  yy311:
-    yych = *++p;
-    if (yych <= 'P') {
-      if (yych == 'L')
-        goto yy331;
-      if (yych <= 'O')
-        goto yy298;
-      goto yy346;
-    } else {
-      if (yych <= 'l') {
-        if (yych <= 'k')
-          goto yy298;
-        goto yy331;
-      } else {
-        if (yych == 'p')
-          goto yy346;
-        goto yy298;
-      }
-    }
-  yy312:
-    yych = *++p;
-    if (yych <= '>') {
-      if (yych <= ' ') {
-        if (yych <= 0x08)
-          goto yy298;
-        if (yych <= '\r')
-          goto yy347;
-        if (yych <= 0x1F)
-          goto yy298;
-        goto yy347;
-      } else {
-        if (yych == '/')
-          goto yy348;
-        if (yych <= '=')
-          goto yy298;
-        goto yy347;
-      }
-    } else {
-      if (yych <= 'R') {
-        if (yych == 'A')
-          goto yy349;
-        if (yych <= 'Q')
-          goto yy298;
-        goto yy350;
-      } else {
-        if (yych <= 'a') {
-          if (yych <= '`')
-            goto yy298;
-          goto yy349;
-        } else {
-          if (yych == 'r')
-            goto yy350;
-          goto yy298;
-        }
-      }
-    }
-  yy313:
-    yych = *++p;
-    switch (yych) {
-    case 'C':
-    case 'c':
-      goto yy351;
-    case 'E':
-    case 'e':
-      goto yy352;
-    case 'O':
-    case 'o':
-      goto yy353;
-    case 'T':
-    case 't':
-      goto yy354;
-    case 'U':
-    case 'u':
-      goto yy355;
-    default:
-      goto yy298;
-    }
-  yy314:
-    yych = *++p;
-    switch (yych) {
-    case 'A':
-    case 'a':
-      goto yy356;
-    case 'B':
-    case 'b':
-      goto yy357;
-    case 'D':
-    case 'd':
-      goto yy331;
-    case 'E':
-    case 'e':
-      goto yy358;
-    case 'F':
-    case 'f':
-      goto yy359;
-    case 'H':
-    case 'h':
-      goto yy360;
-    case 'I':
-    case 'i':
-      goto yy361;
-    case 'R':
-    case 'r':
-      goto yy362;
-    default:
-      goto yy298;
-    }
-  yy315:
-    yych = *++p;
-    if (yych == 'L')
-      goto yy331;
-    if (yych == 'l')
-      goto yy331;
-    goto yy298;
-  yy316:
-    yych = *++p;
-    if (yych == '-')
-      goto yy363;
-    goto yy298;
-  yy317:
-    ++p;
-    { return 4; }
-  yy318:
-    yych = *++p;
-    if (yych == 'C')
-      goto yy364;
-    if (yych == 'c')
-      goto yy364;
-    goto yy298;
-  yy319:
-    yych = *++p;
-    if (yych <= '/') {
-      if (yych <= 0x1F) {
-        if (yych <= 0x08)
-          goto yy298;
-        if (yych <= '\r')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= ' ')
-          goto yy347;
-        if (yych <= '.')
-          goto yy298;
-        goto yy348;
-      }
-    } else {
-      if (yych <= '@') {
-        if (yych == '>')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= 'A')
-          goto yy349;
-        if (yych == 'a')
-          goto yy349;
-        goto yy298;
-      }
-    }
-  yy320:
-    yych = *++p;
-    if (yych <= 'U') {
-      if (yych <= 'N') {
-        if (yych == 'E')
-          goto yy352;
-        goto yy298;
-      } else {
-        if (yych <= 'O')
-          goto yy353;
-        if (yych <= 'T')
-          goto yy298;
-        goto yy355;
-      }
-    } else {
-      if (yych <= 'n') {
-        if (yych == 'e')
-          goto yy352;
-        goto yy298;
-      } else {
-        if (yych <= 'o')
-          goto yy353;
-        if (yych == 'u')
-          goto yy355;
-        goto yy298;
-      }
-    }
-  yy321:
-    yych = *++p;
-    switch (yych) {
-    case 'A':
-    case 'a':
-      goto yy356;
-    case 'B':
-    case 'b':
-      goto yy357;
-    case 'D':
-    case 'd':
-      goto yy331;
-    case 'F':
-    case 'f':
-      goto yy359;
-    case 'H':
-    case 'h':
-      goto yy360;
-    case 'I':
-    case 'i':
-      goto yy361;
-    case 'R':
-    case 'r':
-      goto yy362;
-    default:
-      goto yy298;
-    }
-  yy322:
-    yych = *++p;
-    if (yych == 'D')
-      goto yy365;
-    if (yych == 'd')
-      goto yy365;
-    goto yy298;
-  yy323:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy366;
-    if (yych == 't')
-      goto yy366;
-    goto yy298;
-  yy324:
-    yych = *++p;
-    if (yych == 'I')
-      goto yy367;
-    if (yych == 'i')
-      goto yy367;
-    goto yy298;
-  yy325:
-    yych = *++p;
-    if (yych == 'S')
-      goto yy368;
-    if (yych == 's')
-      goto yy368;
-    goto yy298;
-  yy326:
-    yych = *++p;
-    if (yych == 'O')
-      goto yy369;
-    if (yych == 'o')
-      goto yy369;
-    goto yy298;
-  yy327:
-    yych = *++p;
-    if (yych == 'D')
-      goto yy370;
-    if (yych == 'd')
-      goto yy370;
-    goto yy298;
-  yy328:
-    yych = *++p;
-    if (yych == 'P')
-      goto yy371;
-    if (yych == 'p')
-      goto yy371;
-    goto yy298;
-  yy329:
-    yych = *++p;
-    if (yych == 'N')
-      goto yy372;
-    if (yych == 'n')
-      goto yy372;
-    goto yy298;
-  yy330:
-    yych = *++p;
-    if (yych == 'L')
-      goto yy373;
-    if (yych == 'l')
-      goto yy373;
-    goto yy298;
-  yy331:
-    yych = *++p;
-    if (yych <= ' ') {
-      if (yych <= 0x08)
-        goto yy298;
-      if (yych <= '\r')
-        goto yy347;
-      if (yych <= 0x1F)
-        goto yy298;
-      goto yy347;
-    } else {
-      if (yych <= '/') {
-        if (yych <= '.')
-          goto yy298;
-        goto yy348;
-      } else {
-        if (yych == '>')
-          goto yy347;
-        goto yy298;
-      }
-    }
-  yy332:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy374;
-    if (yych == 't')
-      goto yy374;
-    goto yy298;
-  yy333:
-    yych = *++p;
-    if (yych <= 'V') {
-      if (yych <= 'Q') {
-        if (yych == 'A')
-          goto yy375;
-        goto yy298;
-      } else {
-        if (yych <= 'R')
-          goto yy331;
-        if (yych <= 'U')
-          goto yy298;
-        goto yy331;
-      }
-    } else {
-      if (yych <= 'q') {
-        if (yych == 'a')
-          goto yy375;
-        goto yy298;
-      } else {
-        if (yych <= 'r')
-          goto yy331;
-        if (yych == 'v')
-          goto yy331;
-        goto yy298;
-      }
-    }
-  yy334:
-    yych = *++p;
-    if (yych <= 'G') {
-      if (yych == 'E')
-        goto yy376;
-      if (yych <= 'F')
-        goto yy298;
-      goto yy377;
-    } else {
-      if (yych <= 'e') {
-        if (yych <= 'd')
-          goto yy298;
-        goto yy376;
-      } else {
-        if (yych == 'g')
-          goto yy377;
-        goto yy298;
-      }
-    }
-  yy335:
-    yych = *++p;
-    if (yych <= 'R') {
-      if (yych == 'O')
-        goto yy372;
-      if (yych <= 'Q')
-        goto yy298;
-      goto yy378;
-    } else {
-      if (yych <= 'o') {
-        if (yych <= 'n')
-          goto yy298;
-        goto yy372;
-      } else {
-        if (yych == 'r')
-          goto yy378;
-        goto yy298;
-      }
-    }
-  yy336:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy379;
-    if (yych == 'a')
-      goto yy379;
-    goto yy298;
-  yy337:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy380;
-    if (yych == 'a')
-      goto yy380;
-    goto yy298;
-  yy338:
-    yych = *++p;
-    if (yych == 'M')
-      goto yy315;
-    if (yych == 'm')
-      goto yy315;
-    goto yy298;
-  yy339:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy381;
-    if (yych == 'r')
-      goto yy381;
-    goto yy298;
-  yy340:
-    yych = *++p;
-    if (yych == 'G')
-      goto yy382;
-    if (yych == 'g')
-      goto yy382;
-    goto yy298;
-  yy341:
-    yych = *++p;
-    if (yych <= '/') {
-      if (yych <= 0x1F) {
-        if (yych <= 0x08)
-          goto yy298;
-        if (yych <= '\r')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= ' ')
-          goto yy347;
-        if (yych <= '.')
-          goto yy298;
-        goto yy348;
-      }
-    } else {
-      if (yych <= 'M') {
-        if (yych == '>')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= 'N')
-          goto yy383;
-        if (yych == 'n')
-          goto yy383;
-        goto yy298;
-      }
-    }
-  yy342:
-    yych = *++p;
-    if (yych == 'I')
-      goto yy384;
-    if (yych == 'i')
-      goto yy384;
-    goto yy298;
-  yy343:
-    yych = *++p;
-    if (yych == 'N')
-      goto yy385;
-    if (yych == 'n')
-      goto yy385;
-    goto yy298;
-  yy344:
-    yych = *++p;
-    if (yych == 'V')
-      goto yy331;
-    if (yych == 'v')
-      goto yy331;
-    goto yy298;
-  yy345:
-    yych = *++p;
-    if (yych == 'F')
-      goto yy386;
-    if (yych == 'f')
-      goto yy386;
-    goto yy298;
-  yy346:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy387;
-    if (yych == 't')
-      goto yy387;
-    goto yy298;
-  yy347:
-    ++p;
-    { return 6; }
-  yy348:
-    yych = *++p;
-    if (yych == '>')
-      goto yy347;
-    goto yy298;
-  yy349:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy388;
-    if (yych == 'r')
-      goto yy388;
-    goto yy298;
-  yy350:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy389;
-    if (yych == 'e')
-      goto yy389;
-    goto yy298;
-  yy351:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy390;
-    if (yych == 'r')
-      goto yy390;
-    goto yy298;
-  yy352:
-    yych = *++p;
-    if (yych == 'C')
-      goto yy371;
-    if (yych == 'c')
-      goto yy371;
-    goto yy298;
-  yy353:
-    yych = *++p;
-    if (yych == 'U')
-      goto yy391;
-    if (yych == 'u')
-      goto yy391;
-    goto yy298;
-  yy354:
-    yych = *++p;
-    if (yych == 'Y')
-      goto yy392;
-    if (yych == 'y')
-      goto yy392;
-    goto yy298;
-  yy355:
-    yych = *++p;
-    if (yych == 'M')
-      goto yy393;
-    if (yych == 'm')
-      goto yy393;
-    goto yy298;
-  yy356:
-    yych = *++p;
-    if (yych == 'B')
-      goto yy394;
-    if (yych == 'b')
-      goto yy394;
-    goto yy298;
-  yy357:
-    yych = *++p;
-    if (yych == 'O')
-      goto yy327;
-    if (yych == 'o')
-      goto yy327;
-    goto yy298;
-  yy358:
-    yych = *++p;
-    if (yych == 'X')
-      goto yy395;
-    if (yych == 'x')
-      goto yy395;
-    goto yy298;
-  yy359:
-    yych = *++p;
-    if (yych == 'O')
-      goto yy396;
-    if (yych == 'o')
-      goto yy396;
-    goto yy298;
-  yy360:
-    yych = *++p;
-    if (yych <= '/') {
-      if (yych <= 0x1F) {
-        if (yych <= 0x08)
-          goto yy298;
-        if (yych <= '\r')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= ' ')
-          goto yy347;
-        if (yych <= '.')
-          goto yy298;
-        goto yy348;
-      }
-    } else {
-      if (yych <= 'D') {
-        if (yych == '>')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= 'E')
-          goto yy397;
-        if (yych == 'e')
-          goto yy397;
-        goto yy298;
-      }
-    }
-  yy361:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy394;
-    if (yych == 't')
-      goto yy394;
-    goto yy298;
-  yy362:
-    yych = *++p;
-    if (yych <= '/') {
-      if (yych <= 0x1F) {
-        if (yych <= 0x08)
-          goto yy298;
-        if (yych <= '\r')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= ' ')
-          goto yy347;
-        if (yych <= '.')
-          goto yy298;
-        goto yy348;
-      }
-    } else {
-      if (yych <= '@') {
-        if (yych == '>')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= 'A')
-          goto yy398;
-        if (yych == 'a')
-          goto yy398;
-        goto yy298;
-      }
-    }
-  yy363:
-    ++p;
-    { return 2; }
-  yy364:
-    yych = *++p;
-    if (yych == 'D')
-      goto yy399;
-    if (yych == 'd')
-      goto yy399;
-    goto yy298;
-  yy365:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy400;
-    if (yych == 'r')
-      goto yy400;
-    goto yy298;
-  yy366:
-    yych = *++p;
-    if (yych == 'I')
-      goto yy401;
-    if (yych == 'i')
-      goto yy401;
-    goto yy298;
-  yy367:
-    yych = *++p;
-    if (yych == 'D')
-      goto yy402;
-    if (yych == 'd')
-      goto yy402;
-    goto yy298;
-  yy368:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy403;
-    if (yych == 'e')
-      goto yy403;
-    goto yy298;
-  yy369:
-    yych = *++p;
-    if (yych == 'C')
-      goto yy404;
-    if (yych == 'c')
-      goto yy404;
-    goto yy298;
-  yy370:
-    yych = *++p;
-    if (yych == 'Y')
-      goto yy331;
-    if (yych == 'y')
-      goto yy331;
-    goto yy298;
-  yy371:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy405;
-    if (yych == 't')
-      goto yy405;
-    goto yy298;
-  yy372:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy406;
-    if (yych == 't')
-      goto yy406;
-    goto yy298;
-  yy373:
-    yych = *++p;
-    if (yych <= '/') {
-      if (yych <= 0x1F) {
-        if (yych <= 0x08)
-          goto yy298;
-        if (yych <= '\r')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= ' ')
-          goto yy347;
-        if (yych <= '.')
-          goto yy298;
-        goto yy348;
-      }
-    } else {
-      if (yych <= 'F') {
-        if (yych == '>')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= 'G')
-          goto yy407;
-        if (yych == 'g')
-          goto yy407;
-        goto yy298;
-      }
-    }
-  yy374:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy408;
-    if (yych == 'a')
-      goto yy408;
-    goto yy298;
-  yy375:
-    yych = *++p;
-    if (yych == 'L')
-      goto yy409;
-    if (yych == 'l')
-      goto yy409;
-    goto yy298;
-  yy376:
-    yych = *++p;
-    if (yych == 'L')
-      goto yy410;
-    if (yych == 'l')
-      goto yy410;
-    goto yy298;
-  yy377:
-    yych = *++p;
-    if (yych <= 'U') {
-      if (yych == 'C')
-        goto yy411;
-      if (yych <= 'T')
-        goto yy298;
-      goto yy412;
-    } else {
-      if (yych <= 'c') {
-        if (yych <= 'b')
-          goto yy298;
-        goto yy411;
-      } else {
-        if (yych == 'u')
-          goto yy412;
-        goto yy298;
-      }
-    }
-  yy378:
-    yych = *++p;
-    if (yych == 'M')
-      goto yy331;
-    if (yych == 'm')
-      goto yy331;
-    goto yy298;
-  yy379:
-    yych = *++p;
-    if (yych == 'M')
-      goto yy413;
-    if (yych == 'm')
-      goto yy413;
-    goto yy298;
-  yy380:
-    yych = *++p;
-    if (yych == 'D')
-      goto yy414;
-    if (yych == 'd')
-      goto yy414;
-    goto yy298;
-  yy381:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy415;
-    if (yych == 'a')
-      goto yy415;
-    goto yy298;
-  yy382:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy416;
-    if (yych == 'e')
-      goto yy416;
-    goto yy298;
-  yy383:
-    yych = *++p;
-    if (yych == 'K')
-      goto yy331;
-    if (yych == 'k')
-      goto yy331;
-    goto yy298;
-  yy384:
-    yych = *++p;
-    if (yych == 'N')
-      goto yy331;
-    if (yych == 'n')
-      goto yy331;
-    goto yy298;
-  yy385:
-    yych = *++p;
-    if (yych == 'U')
-      goto yy417;
-    if (yych == 'u')
-      goto yy417;
-    goto yy298;
-  yy386:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy418;
-    if (yych == 'r')
-      goto yy418;
-    goto yy298;
-  yy387:
-    yych = *++p;
-    if (yych <= 'I') {
-      if (yych == 'G')
-        goto yy407;
-      if (yych <= 'H')
-        goto yy298;
-      goto yy419;
-    } else {
-      if (yych <= 'g') {
-        if (yych <= 'f')
-          goto yy298;
-        goto yy407;
-      } else {
-        if (yych == 'i')
-          goto yy419;
-        goto yy298;
-      }
-    }
-  yy388:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy378;
-    if (yych == 'a')
-      goto yy378;
-    goto yy298;
-  yy389:
-    yych = *++p;
-    if (yych <= 0x1F) {
-      if (yych <= 0x08)
-        goto yy298;
-      if (yych <= '\r')
-        goto yy420;
-      goto yy298;
-    } else {
-      if (yych <= ' ')
-        goto yy420;
-      if (yych == '>')
-        goto yy420;
-      goto yy298;
-    }
-  yy390:
-    yych = *++p;
-    if (yych == 'I')
-      goto yy421;
-    if (yych == 'i')
-      goto yy421;
-    goto yy298;
-  yy391:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy422;
-    if (yych == 'r')
-      goto yy422;
-    goto yy298;
-  yy392:
-    yych = *++p;
-    if (yych == 'L')
-      goto yy350;
-    if (yych == 'l')
-      goto yy350;
-    goto yy298;
-  yy393:
-    yych = *++p;
-    if (yych == 'M')
-      goto yy423;
-    if (yych == 'm')
-      goto yy423;
-    goto yy298;
-  yy394:
-    yych = *++p;
-    if (yych == 'L')
-      goto yy402;
-    if (yych == 'l')
-      goto yy402;
-    goto yy298;
-  yy395:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy424;
-    if (yych == 't')
-      goto yy424;
-    goto yy298;
-  yy396:
-    yych = *++p;
-    if (yych == 'O')
-      goto yy425;
-    if (yych == 'o')
-      goto yy425;
-    goto yy298;
-  yy397:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy426;
-    if (yych == 'a')
-      goto yy426;
-    goto yy298;
-  yy398:
-    yych = *++p;
-    if (yych == 'C')
-      goto yy383;
-    if (yych == 'c')
-      goto yy383;
-    goto yy298;
-  yy399:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy427;
-    if (yych == 'a')
-      goto yy427;
-    goto yy298;
-  yy400:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy428;
-    if (yych == 'e')
-      goto yy428;
-    goto yy298;
-  yy401:
-    yych = *++p;
-    if (yych == 'C')
-      goto yy394;
-    if (yych == 'c')
-      goto yy394;
-    goto yy298;
-  yy402:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy331;
-    if (yych == 'e')
-      goto yy331;
-    goto yy298;
-  yy403:
-    yych = *++p;
-    if (yych <= '/') {
-      if (yych <= 0x1F) {
-        if (yych <= 0x08)
-          goto yy298;
-        if (yych <= '\r')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= ' ')
-          goto yy347;
-        if (yych <= '.')
-          goto yy298;
-        goto yy348;
-      }
-    } else {
-      if (yych <= 'E') {
-        if (yych == '>')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= 'F')
-          goto yy429;
-        if (yych == 'f')
-          goto yy429;
-        goto yy298;
-      }
-    }
-  yy404:
-    yych = *++p;
-    if (yych == 'K')
-      goto yy430;
-    if (yych == 'k')
-      goto yy430;
-    goto yy298;
-  yy405:
-    yych = *++p;
-    if (yych == 'I')
-      goto yy419;
-    if (yych == 'i')
-      goto yy419;
-    goto yy298;
-  yy406:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy431;
-    if (yych == 'e')
-      goto yy431;
-    goto yy298;
-  yy407:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy432;
-    if (yych == 'r')
-      goto yy432;
-    goto yy298;
-  yy408:
-    yych = *++p;
-    if (yych == 'I')
-      goto yy433;
-    if (yych == 'i')
-      goto yy433;
-    goto yy298;
-  yy409:
-    yych = *++p;
-    if (yych == 'O')
-      goto yy434;
-    if (yych == 'o')
-      goto yy434;
-    goto yy298;
-  yy410:
-    yych = *++p;
-    if (yych == 'D')
-      goto yy435;
-    if (yych == 'd')
-      goto yy435;
-    goto yy298;
-  yy411:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy328;
-    if (yych == 'a')
-      goto yy328;
-    goto yy298;
-  yy412:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy402;
-    if (yych == 'r')
-      goto yy402;
-    goto yy298;
-  yy413:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy436;
-    if (yych == 'e')
-      goto yy436;
-    goto yy298;
-  yy414:
-    yych = *++p;
-    if (yych <= '/') {
-      if (yych <= 0x1F) {
-        if (yych <= 0x08)
-          goto yy298;
-        if (yych <= '\r')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= ' ')
-          goto yy347;
-        if (yych <= '.')
-          goto yy298;
-        goto yy348;
-      }
-    } else {
-      if (yych <= 'D') {
-        if (yych == '>')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= 'E')
-          goto yy431;
-        if (yych == 'e')
-          goto yy431;
-        goto yy298;
-      }
-    }
-  yy415:
-    yych = *++p;
-    if (yych == 'M')
-      goto yy402;
-    if (yych == 'm')
-      goto yy402;
-    goto yy298;
-  yy416:
-    yych = *++p;
-    if (yych == 'N')
-      goto yy426;
-    if (yych == 'n')
-      goto yy426;
-    goto yy298;
-  yy417:
-    yych = *++p;
-    if (yych <= '/') {
-      if (yych <= 0x1F) {
-        if (yych <= 0x08)
-          goto yy298;
-        if (yych <= '\r')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= ' ')
-          goto yy347;
-        if (yych <= '.')
-          goto yy298;
-        goto yy348;
-      }
-    } else {
-      if (yych <= 'H') {
-        if (yych == '>')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= 'I')
-          goto yy437;
-        if (yych == 'i')
-          goto yy437;
-        goto yy298;
-      }
-    }
-  yy418:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy438;
-    if (yych == 'a')
-      goto yy438;
-    goto yy298;
-  yy419:
-    yych = *++p;
-    if (yych == 'O')
-      goto yy384;
-    if (yych == 'o')
-      goto yy384;
-    goto yy298;
-  yy420:
-    ++p;
-    { return 1; }
-  yy421:
-    yych = *++p;
-    if (yych == 'P')
-      goto yy439;
-    if (yych == 'p')
-      goto yy439;
-    goto yy298;
-  yy422:
-    yych = *++p;
-    if (yych == 'C')
-      goto yy402;
-    if (yych == 'c')
-      goto yy402;
-    goto yy298;
-  yy423:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy440;
-    if (yych == 'a')
-      goto yy440;
-    goto yy298;
-  yy424:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy441;
-    if (yych == 'a')
-      goto yy441;
-    goto yy298;
-  yy425:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy331;
-    if (yych == 't')
-      goto yy331;
-    goto yy298;
-  yy426:
-    yych = *++p;
-    if (yych == 'D')
-      goto yy331;
-    if (yych == 'd')
-      goto yy331;
-    goto yy298;
-  yy427:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy442;
-    if (yych == 't')
-      goto yy442;
-    goto yy298;
-  yy428:
-    yych = *++p;
-    if (yych == 'S')
-      goto yy443;
-    if (yych == 's')
-      goto yy443;
-    goto yy298;
-  yy429:
-    yych = *++p;
-    if (yych == 'O')
-      goto yy444;
-    if (yych == 'o')
-      goto yy444;
-    goto yy298;
-  yy430:
-    yych = *++p;
-    if (yych == 'Q')
-      goto yy445;
-    if (yych == 'q')
-      goto yy445;
-    goto yy298;
-  yy431:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy331;
-    if (yych == 'r')
-      goto yy331;
-    goto yy298;
-  yy432:
-    yych = *++p;
-    if (yych == 'O')
-      goto yy446;
-    if (yych == 'o')
-      goto yy446;
-    goto yy298;
-  yy433:
-    yych = *++p;
-    if (yych == 'L')
-      goto yy443;
-    if (yych == 'l')
-      goto yy443;
-    goto yy298;
-  yy434:
-    yych = *++p;
-    if (yych == 'G')
-      goto yy331;
-    if (yych == 'g')
-      goto yy331;
-    goto yy298;
-  yy435:
-    yych = *++p;
-    if (yych == 'S')
-      goto yy447;
-    if (yych == 's')
-      goto yy447;
-    goto yy298;
-  yy436:
-    yych = *++p;
-    if (yych <= '/') {
-      if (yych <= 0x1F) {
-        if (yych <= 0x08)
-          goto yy298;
-        if (yych <= '\r')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= ' ')
-          goto yy347;
-        if (yych <= '.')
-          goto yy298;
-        goto yy348;
-      }
-    } else {
-      if (yych <= 'R') {
-        if (yych == '>')
-          goto yy347;
-        goto yy298;
-      } else {
-        if (yych <= 'S')
-          goto yy447;
-        if (yych == 's')
-          goto yy447;
-        goto yy298;
-      }
-    }
-  yy437:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy448;
-    if (yych == 't')
-      goto yy448;
-    goto yy298;
-  yy438:
-    yych = *++p;
-    if (yych == 'M')
-      goto yy449;
-    if (yych == 'm')
-      goto yy449;
-    goto yy298;
-  yy439:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy389;
-    if (yych == 't')
-      goto yy389;
-    goto yy298;
-  yy440:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy370;
-    if (yych == 'r')
-      goto yy370;
-    goto yy298;
-  yy441:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy450;
-    if (yych == 'r')
-      goto yy450;
-    goto yy298;
-  yy442:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy451;
-    if (yych == 'a')
-      goto yy451;
-    goto yy298;
-  yy443:
-    yych = *++p;
-    if (yych == 'S')
-      goto yy331;
-    if (yych == 's')
-      goto yy331;
-    goto yy298;
-  yy444:
-    yych = *++p;
-    if (yych == 'N')
-      goto yy425;
-    if (yych == 'n')
-      goto yy425;
-    goto yy298;
-  yy445:
-    yych = *++p;
-    if (yych == 'U')
-      goto yy452;
-    if (yych == 'u')
-      goto yy452;
-    goto yy298;
-  yy446:
-    yych = *++p;
-    if (yych == 'U')
-      goto yy453;
-    if (yych == 'u')
-      goto yy453;
-    goto yy298;
-  yy447:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy425;
-    if (yych == 'e')
-      goto yy425;
-    goto yy298;
-  yy448:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy378;
-    if (yych == 'e')
-      goto yy378;
-    goto yy298;
-  yy449:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy443;
-    if (yych == 'e')
-      goto yy443;
-    goto yy298;
-  yy450:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy454;
-    if (yych == 'e')
-      goto yy454;
-    goto yy298;
-  yy451:
-    yych = *++p;
-    if (yych == '[')
-      goto yy455;
-    goto yy298;
-  yy452:
-    yych = *++p;
-    if (yych == 'O')
-      goto yy456;
-    if (yych == 'o')
-      goto yy456;
-    goto yy298;
-  yy453:
-    yych = *++p;
-    if (yych == 'P')
-      goto yy331;
-    if (yych == 'p')
-      goto yy331;
-    goto yy298;
-  yy454:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy389;
-    if (yych == 'a')
-      goto yy389;
-    goto yy298;
-  yy455:
-    ++p;
-    { return 5; }
-  yy456:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy402;
-    if (yych == 't')
-      goto yy402;
-    goto yy298;
-  }
-}
-
-// Try to match an HTML block tag start line of type 7, returning
-// 7 if successful, 0 if not.
-bufsize_t _scan_html_block_start_7(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-
-  {
-    unsigned char yych;
-    unsigned int yyaccept = 0;
-    static const unsigned char yybm[] = {
-        0,   224, 224, 224, 224, 224, 224, 224, 224, 198, 210, 194, 198, 194,
-        224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
-        224, 224, 224, 224, 198, 224, 128, 224, 224, 224, 224, 64,  224, 224,
-        224, 224, 224, 233, 232, 224, 233, 233, 233, 233, 233, 233, 233, 233,
-        233, 233, 232, 224, 192, 192, 192, 224, 224, 233, 233, 233, 233, 233,
-        233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
-        233, 233, 233, 233, 233, 233, 233, 224, 224, 224, 224, 232, 192, 233,
-        233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
-        233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, 224, 224, 224,
-        224, 224, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,
-    };
-    yych = *p;
-    if (yych == '<')
-      goto yy459;
-    ++p;
-  yy458 : { return 0; }
-  yy459:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= '@') {
-      if (yych != '/')
-        goto yy458;
-    } else {
-      if (yych <= 'Z')
-        goto yy461;
-      if (yych <= '`')
-        goto yy458;
-      if (yych <= 'z')
-        goto yy461;
-      goto yy458;
-    }
-    yych = *++p;
-    if (yych <= '@')
-      goto yy460;
-    if (yych <= 'Z')
-      goto yy462;
-    if (yych <= '`')
-      goto yy460;
-    if (yych <= 'z')
-      goto yy462;
-  yy460:
-    p = marker;
-    if (yyaccept == 0) {
-      goto yy458;
-    } else {
-      goto yy469;
-    }
-  yy461:
-    yych = *++p;
-    if (yybm[0 + yych] & 2) {
-      goto yy463;
-    }
-    if (yych <= '=') {
-      if (yych <= '.') {
-        if (yych == '-')
-          goto yy461;
-        goto yy460;
-      } else {
-        if (yych <= '/')
-          goto yy464;
-        if (yych <= '9')
-          goto yy461;
-        goto yy460;
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '>')
-          goto yy465;
-        if (yych <= '@')
-          goto yy460;
-        goto yy461;
-      } else {
-        if (yych <= '`')
-          goto yy460;
-        if (yych <= 'z')
-          goto yy461;
-        goto yy460;
-      }
-    }
-  yy462:
-    yych = *++p;
-    if (yych <= '/') {
-      if (yych <= 0x1F) {
-        if (yych <= 0x08)
-          goto yy460;
-        if (yych <= '\r')
-          goto yy466;
-        goto yy460;
-      } else {
-        if (yych <= ' ')
-          goto yy466;
-        if (yych == '-')
-          goto yy462;
-        goto yy460;
-      }
-    } else {
-      if (yych <= '@') {
-        if (yych <= '9')
-          goto yy462;
-        if (yych == '>')
-          goto yy465;
-        goto yy460;
-      } else {
-        if (yych <= 'Z')
-          goto yy462;
-        if (yych <= '`')
-          goto yy460;
-        if (yych <= 'z')
-          goto yy462;
-        goto yy460;
-      }
-    }
-  yy463:
-    yych = *++p;
-    if (yybm[0 + yych] & 2) {
-      goto yy463;
-    }
-    if (yych <= '>') {
-      if (yych <= '9') {
-        if (yych != '/')
-          goto yy460;
-      } else {
-        if (yych <= ':')
-          goto yy467;
-        if (yych <= '=')
-          goto yy460;
-        goto yy465;
-      }
-    } else {
-      if (yych <= '^') {
-        if (yych <= '@')
-          goto yy460;
-        if (yych <= 'Z')
-          goto yy467;
-        goto yy460;
-      } else {
-        if (yych == '`')
-          goto yy460;
-        if (yych <= 'z')
-          goto yy467;
-        goto yy460;
-      }
-    }
-  yy464:
-    yych = *++p;
-    if (yych != '>')
-      goto yy460;
-  yy465:
-    yych = *++p;
-    if (yybm[0 + yych] & 4) {
-      goto yy465;
-    }
-    if (yych <= 0x08)
-      goto yy460;
-    if (yych <= '\n')
-      goto yy468;
-    if (yych <= '\v')
-      goto yy460;
-    if (yych <= '\r')
-      goto yy470;
-    goto yy460;
-  yy466:
-    yych = *++p;
-    if (yych <= 0x1F) {
-      if (yych <= 0x08)
-        goto yy460;
-      if (yych <= '\r')
-        goto yy466;
-      goto yy460;
-    } else {
-      if (yych <= ' ')
-        goto yy466;
-      if (yych == '>')
-        goto yy465;
-      goto yy460;
-    }
-  yy467:
-    yych = *++p;
-    if (yybm[0 + yych] & 8) {
-      goto yy467;
-    }
-    if (yych <= ',') {
-      if (yych <= '\r') {
-        if (yych <= 0x08)
-          goto yy460;
-        goto yy471;
-      } else {
-        if (yych == ' ')
-          goto yy471;
-        goto yy460;
-      }
-    } else {
-      if (yych <= '<') {
-        if (yych <= '/')
-          goto yy464;
-        goto yy460;
-      } else {
-        if (yych <= '=')
-          goto yy472;
-        if (yych <= '>')
-          goto yy465;
-        goto yy460;
-      }
-    }
-  yy468:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 4) {
-      goto yy465;
-    }
-    if (yych <= 0x08)
-      goto yy469;
-    if (yych <= '\n')
-      goto yy468;
-    if (yych <= '\v')
-      goto yy469;
-    if (yych <= '\r')
-      goto yy470;
-  yy469 : { return 7; }
-  yy470:
-    ++p;
-    goto yy469;
-  yy471:
-    yych = *++p;
-    if (yych <= '<') {
-      if (yych <= ' ') {
-        if (yych <= 0x08)
-          goto yy460;
-        if (yych <= '\r')
-          goto yy471;
-        if (yych <= 0x1F)
-          goto yy460;
-        goto yy471;
-      } else {
-        if (yych <= '/') {
-          if (yych <= '.')
-            goto yy460;
-          goto yy464;
-        } else {
-          if (yych == ':')
-            goto yy467;
-          goto yy460;
-        }
-      }
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '=')
-          goto yy472;
-        if (yych <= '>')
-          goto yy465;
-        if (yych <= '@')
-          goto yy460;
-        goto yy467;
-      } else {
-        if (yych <= '_') {
-          if (yych <= '^')
-            goto yy460;
-          goto yy467;
-        } else {
-          if (yych <= '`')
-            goto yy460;
-          if (yych <= 'z')
-            goto yy467;
-          goto yy460;
-        }
-      }
-    }
-  yy472:
-    yych = *++p;
-    if (yybm[0 + yych] & 32) {
-      goto yy473;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '"') {
-        if (yych <= 0x00)
-          goto yy460;
-        if (yych <= ' ')
-          goto yy472;
-        goto yy474;
-      } else {
-        if (yych <= '\'')
-          goto yy475;
-        if (yych <= 0xC1)
-          goto yy460;
-        if (yych <= 0xDF)
-          goto yy476;
-        goto yy477;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy479;
-        goto yy478;
-      } else {
-        if (yych <= 0xF0)
-          goto yy480;
-        if (yych <= 0xF3)
-          goto yy481;
-        if (yych <= 0xF4)
-          goto yy482;
-        goto yy460;
-      }
-    }
-  yy473:
-    yych = *++p;
-    if (yybm[0 + yych] & 32) {
-      goto yy473;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '=') {
-        if (yych <= 0x00)
-          goto yy460;
-        if (yych <= ' ')
-          goto yy463;
-        goto yy460;
-      } else {
-        if (yych <= '>')
-          goto yy465;
-        if (yych <= 0xC1)
-          goto yy460;
-        if (yych <= 0xDF)
-          goto yy476;
-        goto yy477;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy479;
-        goto yy478;
-      } else {
-        if (yych <= 0xF0)
-          goto yy480;
-        if (yych <= 0xF3)
-          goto yy481;
-        if (yych <= 0xF4)
-          goto yy482;
-        goto yy460;
-      }
-    }
-  yy474:
-    yych = *++p;
-    if (yybm[0 + yych] & 64) {
-      goto yy474;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy460;
-        if (yych <= '"')
-          goto yy483;
-        goto yy460;
-      } else {
-        if (yych <= 0xDF)
-          goto yy484;
-        if (yych <= 0xE0)
-          goto yy485;
-        goto yy486;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy487;
-        if (yych <= 0xEF)
-          goto yy486;
-        goto yy488;
-      } else {
-        if (yych <= 0xF3)
-          goto yy489;
-        if (yych <= 0xF4)
-          goto yy490;
-        goto yy460;
-      }
-    }
-  yy475:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy475;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy460;
-        if (yych <= '\'')
-          goto yy483;
-        goto yy460;
-      } else {
-        if (yych <= 0xDF)
-          goto yy491;
-        if (yych <= 0xE0)
-          goto yy492;
-        goto yy493;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy494;
-        if (yych <= 0xEF)
-          goto yy493;
-        goto yy495;
-      } else {
-        if (yych <= 0xF3)
-          goto yy496;
-        if (yych <= 0xF4)
-          goto yy497;
-        goto yy460;
-      }
-    }
-  yy476:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy473;
-    goto yy460;
-  yy477:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy476;
-    goto yy460;
-  yy478:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy476;
-    goto yy460;
-  yy479:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0x9F)
-      goto yy476;
-    goto yy460;
-  yy480:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy478;
-    goto yy460;
-  yy481:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy478;
-    goto yy460;
-  yy482:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0x8F)
-      goto yy478;
-    goto yy460;
-  yy483:
-    yych = *++p;
-    if (yybm[0 + yych] & 2) {
-      goto yy463;
-    }
-    if (yych == '/')
-      goto yy464;
-    if (yych == '>')
-      goto yy465;
-    goto yy460;
-  yy484:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy474;
-    goto yy460;
-  yy485:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy484;
-    goto yy460;
-  yy486:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy484;
-    goto yy460;
-  yy487:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0x9F)
-      goto yy484;
-    goto yy460;
-  yy488:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy486;
-    goto yy460;
-  yy489:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy486;
-    goto yy460;
-  yy490:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0x8F)
-      goto yy486;
-    goto yy460;
-  yy491:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy475;
-    goto yy460;
-  yy492:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy491;
-    goto yy460;
-  yy493:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy491;
-    goto yy460;
-  yy494:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0x9F)
-      goto yy491;
-    goto yy460;
-  yy495:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy493;
-    goto yy460;
-  yy496:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0xBF)
-      goto yy493;
-    goto yy460;
-  yy497:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy460;
-    if (yych <= 0x8F)
-      goto yy493;
-    goto yy460;
-  }
-}
-
-// Try to match an HTML block end line of type 1
-bufsize_t _scan_html_block_end_1(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    unsigned int yyaccept = 0;
-    static const unsigned char yybm[] = {
-        0,  64, 64, 64, 64, 64, 64,  64, 64, 64, 0,  64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,
-    };
-    yych = *p;
-    if (yych <= 0xDF) {
-      if (yych <= ';') {
-        if (yych <= 0x00)
-          goto yy499;
-        if (yych != '\n')
-          goto yy501;
-      } else {
-        if (yych <= '<')
-          goto yy502;
-        if (yych <= 0x7F)
-          goto yy501;
-        if (yych >= 0xC2)
-          goto yy503;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych <= 0xE0)
-          goto yy504;
-        if (yych == 0xED)
-          goto yy506;
-        goto yy505;
-      } else {
-        if (yych <= 0xF0)
-          goto yy507;
-        if (yych <= 0xF3)
-          goto yy508;
-        if (yych <= 0xF4)
-          goto yy509;
-      }
-    }
-  yy499:
-    ++p;
-  yy500 : { return 0; }
-  yy501:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= '\n') {
-      if (yych <= 0x00)
-        goto yy500;
-      if (yych <= '\t')
-        goto yy511;
-      goto yy500;
-    } else {
-      if (yych <= 0x7F)
-        goto yy511;
-      if (yych <= 0xC1)
-        goto yy500;
-      if (yych <= 0xF4)
-        goto yy511;
-      goto yy500;
-    }
-  yy502:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= '.') {
-      if (yych <= 0x00)
-        goto yy500;
-      if (yych == '\n')
-        goto yy500;
-      goto yy511;
-    } else {
-      if (yych <= 0x7F) {
-        if (yych <= '/')
-          goto yy521;
-        goto yy511;
-      } else {
-        if (yych <= 0xC1)
-          goto yy500;
-        if (yych <= 0xF4)
-          goto yy511;
-        goto yy500;
-      }
-    }
-  yy503:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy500;
-    if (yych <= 0xBF)
-      goto yy510;
-    goto yy500;
-  yy504:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x9F)
-      goto yy500;
-    if (yych <= 0xBF)
-      goto yy514;
-    goto yy500;
-  yy505:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy500;
-    if (yych <= 0xBF)
-      goto yy514;
-    goto yy500;
-  yy506:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy500;
-    if (yych <= 0x9F)
-      goto yy514;
-    goto yy500;
-  yy507:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x8F)
-      goto yy500;
-    if (yych <= 0xBF)
-      goto yy516;
-    goto yy500;
-  yy508:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy500;
-    if (yych <= 0xBF)
-      goto yy516;
-    goto yy500;
-  yy509:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy500;
-    if (yych <= 0x8F)
-      goto yy516;
-    goto yy500;
-  yy510:
-    yych = *++p;
-  yy511:
-    if (yybm[0 + yych] & 64) {
-      goto yy510;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy512;
-        if (yych <= '<')
-          goto yy513;
-      } else {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        goto yy516;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy517;
-        if (yych <= 0xEF)
-          goto yy516;
-        goto yy518;
-      } else {
-        if (yych <= 0xF3)
-          goto yy519;
-        if (yych <= 0xF4)
-          goto yy520;
-      }
-    }
-  yy512:
-    p = marker;
-    if (yyaccept == 0) {
-      goto yy500;
-    } else {
-      goto yy534;
-    }
-  yy513:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xDF) {
-      if (yych <= '.') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= '/')
-          goto yy521;
-        if (yych <= 0x7F)
-          goto yy510;
-        if (yych <= 0xC1)
-          goto yy512;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych == 0xED)
-          goto yy517;
-        goto yy516;
-      } else {
-        if (yych <= 0xF0)
-          goto yy518;
-        if (yych <= 0xF3)
-          goto yy519;
-        if (yych <= 0xF4)
-          goto yy520;
-        goto yy512;
-      }
-    }
-  yy514:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy512;
-    if (yych <= 0xBF)
-      goto yy510;
-    goto yy512;
-  yy515:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy512;
-    if (yych <= 0xBF)
-      goto yy514;
-    goto yy512;
-  yy516:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy512;
-    if (yych <= 0xBF)
-      goto yy514;
-    goto yy512;
-  yy517:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy512;
-    if (yych <= 0x9F)
-      goto yy514;
-    goto yy512;
-  yy518:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy512;
-    if (yych <= 0xBF)
-      goto yy516;
-    goto yy512;
-  yy519:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy512;
-    if (yych <= 0xBF)
-      goto yy516;
-    goto yy512;
-  yy520:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy512;
-    if (yych <= 0x8F)
-      goto yy516;
-    goto yy512;
-  yy521:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 's') {
-      if (yych <= 'R') {
-        if (yych <= '\n') {
-          if (yych <= 0x00)
-            goto yy512;
-          if (yych <= '\t')
-            goto yy510;
-          goto yy512;
-        } else {
-          if (yych != 'P')
-            goto yy510;
-        }
-      } else {
-        if (yych <= 'o') {
-          if (yych <= 'S')
-            goto yy523;
-          if (yych <= 'T')
-            goto yy524;
-          goto yy510;
-        } else {
-          if (yych <= 'p')
-            goto yy522;
-          if (yych <= 'r')
-            goto yy510;
-          goto yy523;
-        }
-      }
-    } else {
-      if (yych <= 0xEC) {
-        if (yych <= 0xC1) {
-          if (yych <= 't')
-            goto yy524;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        } else {
-          if (yych <= 0xDF)
-            goto yy514;
-          if (yych <= 0xE0)
-            goto yy515;
-          goto yy516;
-        }
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xED)
-            goto yy517;
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy522:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'Q') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 'q') {
-          if (yych <= 'R')
-            goto yy525;
-          goto yy510;
-        } else {
-          if (yych <= 'r')
-            goto yy525;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy523:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 't') {
-      if (yych <= 'C') {
-        if (yych <= '\t') {
-          if (yych <= 0x00)
-            goto yy512;
-          goto yy510;
-        } else {
-          if (yych <= '\n')
-            goto yy512;
-          if (yych <= 'B')
-            goto yy510;
-          goto yy526;
-        }
-      } else {
-        if (yych <= 'b') {
-          if (yych == 'T')
-            goto yy527;
-          goto yy510;
-        } else {
-          if (yych <= 'c')
-            goto yy526;
-          if (yych <= 's')
-            goto yy510;
-          goto yy527;
-        }
-      }
-    } else {
-      if (yych <= 0xEC) {
-        if (yych <= 0xC1) {
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        } else {
-          if (yych <= 0xDF)
-            goto yy514;
-          if (yych <= 0xE0)
-            goto yy515;
-          goto yy516;
-        }
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xED)
-            goto yy517;
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy524:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'D') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 'd') {
-          if (yych <= 'E')
-            goto yy528;
-          goto yy510;
-        } else {
-          if (yych <= 'e')
-            goto yy528;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy525:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'D') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 'd') {
-          if (yych <= 'E')
-            goto yy529;
-          goto yy510;
-        } else {
-          if (yych <= 'e')
-            goto yy529;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy526:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'Q') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 'q') {
-          if (yych <= 'R')
-            goto yy530;
-          goto yy510;
-        } else {
-          if (yych <= 'r')
-            goto yy530;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy527:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'X') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 'x') {
-          if (yych <= 'Y')
-            goto yy531;
-          goto yy510;
-        } else {
-          if (yych <= 'y')
-            goto yy531;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy528:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'W') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 'w') {
-          if (yych <= 'X')
-            goto yy532;
-          goto yy510;
-        } else {
-          if (yych <= 'x')
-            goto yy532;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy529:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xDF) {
-      if (yych <= '=') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= '>')
-          goto yy533;
-        if (yych <= 0x7F)
-          goto yy510;
-        if (yych <= 0xC1)
-          goto yy512;
-        goto yy514;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych == 0xED)
-          goto yy517;
-        goto yy516;
-      } else {
-        if (yych <= 0xF0)
-          goto yy518;
-        if (yych <= 0xF3)
-          goto yy519;
-        if (yych <= 0xF4)
-          goto yy520;
-        goto yy512;
-      }
-    }
-  yy530:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'H') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 'h') {
-          if (yych <= 'I')
-            goto yy535;
-          goto yy510;
-        } else {
-          if (yych <= 'i')
-            goto yy535;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy531:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'K') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 'k') {
-          if (yych <= 'L')
-            goto yy525;
-          goto yy510;
-        } else {
-          if (yych <= 'l')
-            goto yy525;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy532:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'S') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 's') {
-          if (yych <= 'T')
-            goto yy536;
-          goto yy510;
-        } else {
-          if (yych <= 't')
-            goto yy536;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy533:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 64) {
-      goto yy510;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy534;
-        if (yych <= '<')
-          goto yy513;
-      } else {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        goto yy516;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy517;
-        if (yych <= 0xEF)
-          goto yy516;
-        goto yy518;
-      } else {
-        if (yych <= 0xF3)
-          goto yy519;
-        if (yych <= 0xF4)
-          goto yy520;
-      }
-    }
-  yy534 : { return (bufsize_t)(p - start); }
-  yy535:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'O') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 'o') {
-          if (yych <= 'P')
-            goto yy537;
-          goto yy510;
-        } else {
-          if (yych <= 'p')
-            goto yy537;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy536:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= '@') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= '`') {
-          if (yych <= 'A')
-            goto yy538;
-          goto yy510;
-        } else {
-          if (yych <= 'a')
-            goto yy538;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy537:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'S') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 's') {
-          if (yych <= 'T')
-            goto yy529;
-          goto yy510;
-        } else {
-          if (yych <= 't')
-            goto yy529;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy538:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'Q') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 'q') {
-          if (yych >= 'S')
-            goto yy510;
-        } else {
-          if (yych <= 'r')
-            goto yy539;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy539:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= 'D') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= 'd') {
-          if (yych >= 'F')
-            goto yy510;
-        } else {
-          if (yych <= 'e')
-            goto yy540;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  yy540:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy513;
-    }
-    if (yych <= 0xC1) {
-      if (yych <= '@') {
-        if (yych <= 0x00)
-          goto yy512;
-        if (yych == '\n')
-          goto yy512;
-        goto yy510;
-      } else {
-        if (yych <= '`') {
-          if (yych <= 'A')
-            goto yy529;
-          goto yy510;
-        } else {
-          if (yych <= 'a')
-            goto yy529;
-          if (yych <= 0x7F)
-            goto yy510;
-          goto yy512;
-        }
-      }
-    } else {
-      if (yych <= 0xED) {
-        if (yych <= 0xDF)
-          goto yy514;
-        if (yych <= 0xE0)
-          goto yy515;
-        if (yych <= 0xEC)
-          goto yy516;
-        goto yy517;
-      } else {
-        if (yych <= 0xF0) {
-          if (yych <= 0xEF)
-            goto yy516;
-          goto yy518;
-        } else {
-          if (yych <= 0xF3)
-            goto yy519;
-          if (yych <= 0xF4)
-            goto yy520;
-          goto yy512;
-        }
-      }
-    }
-  }
-}
-
-// Try to match an HTML block end line of type 2
-bufsize_t _scan_html_block_end_2(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    unsigned int yyaccept = 0;
-    static const unsigned char yybm[] = {
-        0,  64, 64, 64, 64, 64, 64, 64, 64, 64,  0,  64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,
-    };
-    yych = *p;
-    if (yych <= 0xDF) {
-      if (yych <= ',') {
-        if (yych <= 0x00)
-          goto yy542;
-        if (yych != '\n')
-          goto yy544;
-      } else {
-        if (yych <= '-')
-          goto yy545;
-        if (yych <= 0x7F)
-          goto yy544;
-        if (yych >= 0xC2)
-          goto yy546;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych <= 0xE0)
-          goto yy547;
-        if (yych == 0xED)
-          goto yy549;
-        goto yy548;
-      } else {
-        if (yych <= 0xF0)
-          goto yy550;
-        if (yych <= 0xF3)
-          goto yy551;
-        if (yych <= 0xF4)
-          goto yy552;
-      }
-    }
-  yy542:
-    ++p;
-  yy543 : { return 0; }
-  yy544:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= '\n') {
-      if (yych <= 0x00)
-        goto yy543;
-      if (yych <= '\t')
-        goto yy554;
-      goto yy543;
-    } else {
-      if (yych <= 0x7F)
-        goto yy554;
-      if (yych <= 0xC1)
-        goto yy543;
-      if (yych <= 0xF4)
-        goto yy554;
-      goto yy543;
-    }
-  yy545:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 128) {
-      goto yy564;
-    }
-    if (yych <= '\n') {
-      if (yych <= 0x00)
-        goto yy543;
-      if (yych <= '\t')
-        goto yy554;
-      goto yy543;
-    } else {
-      if (yych <= 0x7F)
-        goto yy554;
-      if (yych <= 0xC1)
-        goto yy543;
-      if (yych <= 0xF4)
-        goto yy554;
-      goto yy543;
-    }
-  yy546:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy543;
-    if (yych <= 0xBF)
-      goto yy553;
-    goto yy543;
-  yy547:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x9F)
-      goto yy543;
-    if (yych <= 0xBF)
-      goto yy557;
-    goto yy543;
-  yy548:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy543;
-    if (yych <= 0xBF)
-      goto yy557;
-    goto yy543;
-  yy549:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy543;
-    if (yych <= 0x9F)
-      goto yy557;
-    goto yy543;
-  yy550:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x8F)
-      goto yy543;
-    if (yych <= 0xBF)
-      goto yy559;
-    goto yy543;
-  yy551:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy543;
-    if (yych <= 0xBF)
-      goto yy559;
-    goto yy543;
-  yy552:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy543;
-    if (yych <= 0x8F)
-      goto yy559;
-    goto yy543;
-  yy553:
-    yych = *++p;
-  yy554:
-    if (yybm[0 + yych] & 64) {
-      goto yy553;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy555;
-        if (yych <= '-')
-          goto yy556;
-      } else {
-        if (yych <= 0xDF)
-          goto yy557;
-        if (yych <= 0xE0)
-          goto yy558;
-        goto yy559;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy560;
-        if (yych <= 0xEF)
-          goto yy559;
-        goto yy561;
-      } else {
-        if (yych <= 0xF3)
-          goto yy562;
-        if (yych <= 0xF4)
-          goto yy563;
-      }
-    }
-  yy555:
-    p = marker;
-    if (yyaccept == 0) {
-      goto yy543;
-    } else {
-      goto yy566;
-    }
-  yy556:
-    yych = *++p;
-    if (yybm[0 + yych] & 64) {
-      goto yy553;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy555;
-        if (yych <= '-')
-          goto yy564;
-        goto yy555;
-      } else {
-        if (yych <= 0xDF)
-          goto yy557;
-        if (yych <= 0xE0)
-          goto yy558;
-        goto yy559;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy560;
-        if (yych <= 0xEF)
-          goto yy559;
-        goto yy561;
-      } else {
-        if (yych <= 0xF3)
-          goto yy562;
-        if (yych <= 0xF4)
-          goto yy563;
-        goto yy555;
-      }
-    }
-  yy557:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy555;
-    if (yych <= 0xBF)
-      goto yy553;
-    goto yy555;
-  yy558:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy555;
-    if (yych <= 0xBF)
-      goto yy557;
-    goto yy555;
-  yy559:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy555;
-    if (yych <= 0xBF)
-      goto yy557;
-    goto yy555;
-  yy560:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy555;
-    if (yych <= 0x9F)
-      goto yy557;
-    goto yy555;
-  yy561:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy555;
-    if (yych <= 0xBF)
-      goto yy559;
-    goto yy555;
-  yy562:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy555;
-    if (yych <= 0xBF)
-      goto yy559;
-    goto yy555;
-  yy563:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy555;
-    if (yych <= 0x8F)
-      goto yy559;
-    goto yy555;
-  yy564:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy564;
-    }
-    if (yych <= 0xDF) {
-      if (yych <= '=') {
-        if (yych <= 0x00)
-          goto yy555;
-        if (yych == '\n')
-          goto yy555;
-        goto yy553;
-      } else {
-        if (yych <= '>')
-          goto yy565;
-        if (yych <= 0x7F)
-          goto yy553;
-        if (yych <= 0xC1)
-          goto yy555;
-        goto yy557;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych <= 0xE0)
-          goto yy558;
-        if (yych == 0xED)
-          goto yy560;
-        goto yy559;
-      } else {
-        if (yych <= 0xF0)
-          goto yy561;
-        if (yych <= 0xF3)
-          goto yy562;
-        if (yych <= 0xF4)
-          goto yy563;
-        goto yy555;
-      }
-    }
-  yy565:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 64) {
-      goto yy553;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy566;
-        if (yych <= '-')
-          goto yy556;
-      } else {
-        if (yych <= 0xDF)
-          goto yy557;
-        if (yych <= 0xE0)
-          goto yy558;
-        goto yy559;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy560;
-        if (yych <= 0xEF)
-          goto yy559;
-        goto yy561;
-      } else {
-        if (yych <= 0xF3)
-          goto yy562;
-        if (yych <= 0xF4)
-          goto yy563;
-      }
-    }
-  yy566 : { return (bufsize_t)(p - start); }
-  }
-}
-
-// Try to match an HTML block end line of type 3
-bufsize_t _scan_html_block_end_3(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    unsigned int yyaccept = 0;
-    static const unsigned char yybm[] = {
-        0,  64, 64, 64, 64, 64, 64, 64, 64, 64,  0,  64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,
-    };
-    yych = *p;
-    if (yych <= 0xDF) {
-      if (yych <= '>') {
-        if (yych <= 0x00)
-          goto yy568;
-        if (yych != '\n')
-          goto yy570;
-      } else {
-        if (yych <= '?')
-          goto yy571;
-        if (yych <= 0x7F)
-          goto yy570;
-        if (yych >= 0xC2)
-          goto yy572;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych <= 0xE0)
-          goto yy573;
-        if (yych == 0xED)
-          goto yy575;
-        goto yy574;
-      } else {
-        if (yych <= 0xF0)
-          goto yy576;
-        if (yych <= 0xF3)
-          goto yy577;
-        if (yych <= 0xF4)
-          goto yy578;
-      }
-    }
-  yy568:
-    ++p;
-  yy569 : { return 0; }
-  yy570:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= '\n') {
-      if (yych <= 0x00)
-        goto yy569;
-      if (yych <= '\t')
-        goto yy580;
-      goto yy569;
-    } else {
-      if (yych <= 0x7F)
-        goto yy580;
-      if (yych <= 0xC1)
-        goto yy569;
-      if (yych <= 0xF4)
-        goto yy580;
-      goto yy569;
-    }
-  yy571:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= '=') {
-      if (yych <= 0x00)
-        goto yy569;
-      if (yych == '\n')
-        goto yy569;
-      goto yy580;
-    } else {
-      if (yych <= 0x7F) {
-        if (yych <= '>')
-          goto yy590;
-        goto yy580;
-      } else {
-        if (yych <= 0xC1)
-          goto yy569;
-        if (yych <= 0xF4)
-          goto yy580;
-        goto yy569;
-      }
-    }
-  yy572:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy569;
-    if (yych <= 0xBF)
-      goto yy579;
-    goto yy569;
-  yy573:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x9F)
-      goto yy569;
-    if (yych <= 0xBF)
-      goto yy583;
-    goto yy569;
-  yy574:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy569;
-    if (yych <= 0xBF)
-      goto yy583;
-    goto yy569;
-  yy575:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy569;
-    if (yych <= 0x9F)
-      goto yy583;
-    goto yy569;
-  yy576:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x8F)
-      goto yy569;
-    if (yych <= 0xBF)
-      goto yy585;
-    goto yy569;
-  yy577:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy569;
-    if (yych <= 0xBF)
-      goto yy585;
-    goto yy569;
-  yy578:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy569;
-    if (yych <= 0x8F)
-      goto yy585;
-    goto yy569;
-  yy579:
-    yych = *++p;
-  yy580:
-    if (yybm[0 + yych] & 64) {
-      goto yy579;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy581;
-        if (yych <= '?')
-          goto yy582;
-      } else {
-        if (yych <= 0xDF)
-          goto yy583;
-        if (yych <= 0xE0)
-          goto yy584;
-        goto yy585;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy586;
-        if (yych <= 0xEF)
-          goto yy585;
-        goto yy587;
-      } else {
-        if (yych <= 0xF3)
-          goto yy588;
-        if (yych <= 0xF4)
-          goto yy589;
-      }
-    }
-  yy581:
-    p = marker;
-    if (yyaccept == 0) {
-      goto yy569;
-    } else {
-      goto yy591;
-    }
-  yy582:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy582;
-    }
-    if (yych <= 0xDF) {
-      if (yych <= '=') {
-        if (yych <= 0x00)
-          goto yy581;
-        if (yych == '\n')
-          goto yy581;
-        goto yy579;
-      } else {
-        if (yych <= '>')
-          goto yy590;
-        if (yych <= 0x7F)
-          goto yy579;
-        if (yych <= 0xC1)
-          goto yy581;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych <= 0xE0)
-          goto yy584;
-        if (yych == 0xED)
-          goto yy586;
-        goto yy585;
-      } else {
-        if (yych <= 0xF0)
-          goto yy587;
-        if (yych <= 0xF3)
-          goto yy588;
-        if (yych <= 0xF4)
-          goto yy589;
-        goto yy581;
-      }
-    }
-  yy583:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy581;
-    if (yych <= 0xBF)
-      goto yy579;
-    goto yy581;
-  yy584:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy581;
-    if (yych <= 0xBF)
-      goto yy583;
-    goto yy581;
-  yy585:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy581;
-    if (yych <= 0xBF)
-      goto yy583;
-    goto yy581;
-  yy586:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy581;
-    if (yych <= 0x9F)
-      goto yy583;
-    goto yy581;
-  yy587:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy581;
-    if (yych <= 0xBF)
-      goto yy585;
-    goto yy581;
-  yy588:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy581;
-    if (yych <= 0xBF)
-      goto yy585;
-    goto yy581;
-  yy589:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy581;
-    if (yych <= 0x8F)
-      goto yy585;
-    goto yy581;
-  yy590:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 64) {
-      goto yy579;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy591;
-        if (yych <= '?')
-          goto yy582;
-      } else {
-        if (yych <= 0xDF)
-          goto yy583;
-        if (yych <= 0xE0)
-          goto yy584;
-        goto yy585;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy586;
-        if (yych <= 0xEF)
-          goto yy585;
-        goto yy587;
-      } else {
-        if (yych <= 0xF3)
-          goto yy588;
-        if (yych <= 0xF4)
-          goto yy589;
-      }
-    }
-  yy591 : { return (bufsize_t)(p - start); }
-  }
-}
-
-// Try to match an HTML block end line of type 4
-bufsize_t _scan_html_block_end_4(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    unsigned int yyaccept = 0;
-    static const unsigned char yybm[] = {
-        0,   128, 128, 128, 128, 128, 128, 128, 128, 128, 0,   128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 64,  128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
-        128, 128, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,
-    };
-    yych = *p;
-    if (yybm[0 + yych] & 64) {
-      goto yy596;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '\n') {
-        if (yych <= 0x00)
-          goto yy593;
-        if (yych <= '\t')
-          goto yy595;
-      } else {
-        if (yych <= 0x7F)
-          goto yy595;
-        if (yych <= 0xC1)
-          goto yy593;
-        if (yych <= 0xDF)
-          goto yy598;
-        goto yy599;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy601;
-        goto yy600;
-      } else {
-        if (yych <= 0xF0)
-          goto yy602;
-        if (yych <= 0xF3)
-          goto yy603;
-        if (yych <= 0xF4)
-          goto yy604;
-      }
-    }
-  yy593:
-    ++p;
-  yy594 : { return 0; }
-  yy595:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= '\n') {
-      if (yych <= 0x00)
-        goto yy594;
-      if (yych <= '\t')
-        goto yy606;
-      goto yy594;
-    } else {
-      if (yych <= 0x7F)
-        goto yy606;
-      if (yych <= 0xC1)
-        goto yy594;
-      if (yych <= 0xF4)
-        goto yy606;
-      goto yy594;
-    }
-  yy596:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 128) {
-      goto yy605;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy597;
-        if (yych <= '>')
-          goto yy596;
-      } else {
-        if (yych <= 0xDF)
-          goto yy608;
-        if (yych <= 0xE0)
-          goto yy609;
-        goto yy610;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy611;
-        if (yych <= 0xEF)
-          goto yy610;
-        goto yy612;
-      } else {
-        if (yych <= 0xF3)
-          goto yy613;
-        if (yych <= 0xF4)
-          goto yy614;
-      }
-    }
-  yy597 : { return (bufsize_t)(p - start); }
-  yy598:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy594;
-    if (yych <= 0xBF)
-      goto yy605;
-    goto yy594;
-  yy599:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x9F)
-      goto yy594;
-    if (yych <= 0xBF)
-      goto yy608;
-    goto yy594;
-  yy600:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy594;
-    if (yych <= 0xBF)
-      goto yy608;
-    goto yy594;
-  yy601:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy594;
-    if (yych <= 0x9F)
-      goto yy608;
-    goto yy594;
-  yy602:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x8F)
-      goto yy594;
-    if (yych <= 0xBF)
-      goto yy610;
-    goto yy594;
-  yy603:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy594;
-    if (yych <= 0xBF)
-      goto yy610;
-    goto yy594;
-  yy604:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy594;
-    if (yych <= 0x8F)
-      goto yy610;
-    goto yy594;
-  yy605:
-    yych = *++p;
-  yy606:
-    if (yybm[0 + yych] & 128) {
-      goto yy605;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy607;
-        if (yych <= '>')
-          goto yy596;
-      } else {
-        if (yych <= 0xDF)
-          goto yy608;
-        if (yych <= 0xE0)
-          goto yy609;
-        goto yy610;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy611;
-        if (yych <= 0xEF)
-          goto yy610;
-        goto yy612;
-      } else {
-        if (yych <= 0xF3)
-          goto yy613;
-        if (yych <= 0xF4)
-          goto yy614;
-      }
-    }
-  yy607:
-    p = marker;
-    if (yyaccept == 0) {
-      goto yy594;
-    } else {
-      goto yy597;
-    }
-  yy608:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy607;
-    if (yych <= 0xBF)
-      goto yy605;
-    goto yy607;
-  yy609:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy607;
-    if (yych <= 0xBF)
-      goto yy608;
-    goto yy607;
-  yy610:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy607;
-    if (yych <= 0xBF)
-      goto yy608;
-    goto yy607;
-  yy611:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy607;
-    if (yych <= 0x9F)
-      goto yy608;
-    goto yy607;
-  yy612:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy607;
-    if (yych <= 0xBF)
-      goto yy610;
-    goto yy607;
-  yy613:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy607;
-    if (yych <= 0xBF)
-      goto yy610;
-    goto yy607;
-  yy614:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy607;
-    if (yych <= 0x8F)
-      goto yy610;
-    goto yy607;
-  }
-}
-
-// Try to match an HTML block end line of type 5
-bufsize_t _scan_html_block_end_5(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    unsigned int yyaccept = 0;
-    static const unsigned char yybm[] = {
-        0,  64, 64, 64,  64, 64, 64, 64, 64, 64, 0,  64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 128, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64,  64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-        0,  0,  0,  0,
-    };
-    yych = *p;
-    if (yych <= 0xDF) {
-      if (yych <= '\\') {
-        if (yych <= 0x00)
-          goto yy616;
-        if (yych != '\n')
-          goto yy618;
-      } else {
-        if (yych <= ']')
-          goto yy619;
-        if (yych <= 0x7F)
-          goto yy618;
-        if (yych >= 0xC2)
-          goto yy620;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych <= 0xE0)
-          goto yy621;
-        if (yych == 0xED)
-          goto yy623;
-        goto yy622;
-      } else {
-        if (yych <= 0xF0)
-          goto yy624;
-        if (yych <= 0xF3)
-          goto yy625;
-        if (yych <= 0xF4)
-          goto yy626;
-      }
-    }
-  yy616:
-    ++p;
-  yy617 : { return 0; }
-  yy618:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= '\n') {
-      if (yych <= 0x00)
-        goto yy617;
-      if (yych <= '\t')
-        goto yy628;
-      goto yy617;
-    } else {
-      if (yych <= 0x7F)
-        goto yy628;
-      if (yych <= 0xC1)
-        goto yy617;
-      if (yych <= 0xF4)
-        goto yy628;
-      goto yy617;
-    }
-  yy619:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 128) {
-      goto yy638;
-    }
-    if (yych <= '\n') {
-      if (yych <= 0x00)
-        goto yy617;
-      if (yych <= '\t')
-        goto yy628;
-      goto yy617;
-    } else {
-      if (yych <= 0x7F)
-        goto yy628;
-      if (yych <= 0xC1)
-        goto yy617;
-      if (yych <= 0xF4)
-        goto yy628;
-      goto yy617;
-    }
-  yy620:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy617;
-    if (yych <= 0xBF)
-      goto yy627;
-    goto yy617;
-  yy621:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x9F)
-      goto yy617;
-    if (yych <= 0xBF)
-      goto yy631;
-    goto yy617;
-  yy622:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy617;
-    if (yych <= 0xBF)
-      goto yy631;
-    goto yy617;
-  yy623:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy617;
-    if (yych <= 0x9F)
-      goto yy631;
-    goto yy617;
-  yy624:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x8F)
-      goto yy617;
-    if (yych <= 0xBF)
-      goto yy633;
-    goto yy617;
-  yy625:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy617;
-    if (yych <= 0xBF)
-      goto yy633;
-    goto yy617;
-  yy626:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x7F)
-      goto yy617;
-    if (yych <= 0x8F)
-      goto yy633;
-    goto yy617;
-  yy627:
-    yych = *++p;
-  yy628:
-    if (yybm[0 + yych] & 64) {
-      goto yy627;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy629;
-        if (yych <= ']')
-          goto yy630;
-      } 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;
-      }
-    }
-  yy629:
-    p = marker;
-    if (yyaccept == 0) {
-      goto yy617;
-    } else {
-      goto yy640;
-    }
-  yy630:
-    yych = *++p;
-    if (yybm[0 + yych] & 64) {
-      goto yy627;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy629;
-        if (yych <= ']')
-          goto yy638;
-        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;
-        goto yy629;
-      }
-    }
-  yy631:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy629;
-    if (yych <= 0xBF)
-      goto yy627;
-    goto yy629;
-  yy632:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy629;
-    if (yych <= 0xBF)
-      goto yy631;
-    goto yy629;
-  yy633:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy629;
-    if (yych <= 0xBF)
-      goto yy631;
-    goto yy629;
-  yy634:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy629;
-    if (yych <= 0x9F)
-      goto yy631;
-    goto yy629;
-  yy635:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy629;
-    if (yych <= 0xBF)
-      goto yy633;
-    goto yy629;
-  yy636:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy629;
-    if (yych <= 0xBF)
-      goto yy633;
-    goto yy629;
-  yy637:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy629;
-    if (yych <= 0x8F)
-      goto yy633;
-    goto yy629;
-  yy638:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy638;
-    }
-    if (yych <= 0xDF) {
-      if (yych <= '=') {
-        if (yych <= 0x00)
-          goto yy629;
-        if (yych == '\n')
-          goto yy629;
-        goto yy627;
-      } else {
-        if (yych <= '>')
-          goto yy639;
-        if (yych <= 0x7F)
-          goto yy627;
-        if (yych <= 0xC1)
-          goto yy629;
-        goto yy631;
-      }
-    } 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 yy629;
-      }
-    }
-  yy639:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 64) {
-      goto yy627;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= '\n')
-          goto yy640;
-        if (yych <= ']')
-          goto yy630;
-      } 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;
-      }
-    }
-  yy640 : { return (bufsize_t)(p - start); }
-  }
-}
-
-// Try to match a link title (in single quotes, in double quotes, or
-// in parentheses), returning number of chars matched.  Allow one
-// level of internal nesting (quotes within quotes).
-bufsize_t _scan_link_title(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    unsigned int yyaccept = 0;
-    static const unsigned char yybm[] = {
-        0,   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
-        208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
-        208, 208, 208, 208, 208, 208, 192, 208, 208, 208, 208, 144, 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 yy643;
-    } else {
-      if (yych <= '\'')
-        goto yy644;
-      if (yych <= '(')
-        goto yy645;
-    }
-    ++p;
-  yy642 : { return 0; }
-  yy643:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x00)
-      goto yy642;
-    if (yych <= 0x7F)
-      goto yy647;
-    if (yych <= 0xC1)
-      goto yy642;
-    if (yych <= 0xF4)
-      goto yy647;
-    goto yy642;
-  yy644:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= 0x00)
-      goto yy642;
-    if (yych <= 0x7F)
-      goto yy660;
-    if (yych <= 0xC1)
-      goto yy642;
-    if (yych <= 0xF4)
-      goto yy660;
-    goto yy642;
-  yy645:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych <= '(') {
-      if (yych <= 0x00)
-        goto yy642;
-      if (yych <= '\'')
-        goto yy672;
-      goto yy642;
-    } else {
-      if (yych <= 0x7F)
-        goto yy672;
-      if (yych <= 0xC1)
-        goto yy642;
-      if (yych <= 0xF4)
-        goto yy672;
-      goto yy642;
-    }
-  yy646:
-    yych = *++p;
-  yy647:
-    if (yybm[0 + yych] & 16) {
-      goto yy646;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '\\') {
-        if (yych <= 0x00)
-          goto yy648;
-        if (yych <= '"')
-          goto yy649;
-        goto yy651;
-      } else {
-        if (yych <= 0xC1)
-          goto yy648;
-        if (yych <= 0xDF)
-          goto yy652;
-        goto yy653;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy655;
-        goto yy654;
-      } else {
-        if (yych <= 0xF0)
-          goto yy656;
-        if (yych <= 0xF3)
-          goto yy657;
-        if (yych <= 0xF4)
-          goto yy658;
-      }
-    }
-  yy648:
-    p = marker;
-    if (yyaccept <= 1) {
-      if (yyaccept == 0) {
-        goto yy642;
-      } else {
-        goto yy650;
-      }
-    } else {
-      if (yyaccept == 2) {
-        goto yy662;
-      } else {
-        goto yy674;
-      }
-    }
-  yy649:
-    ++p;
-  yy650 : { return (bufsize_t)(p - start); }
-  yy651:
-    yych = *++p;
-    if (yybm[0 + yych] & 16) {
-      goto yy646;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '\\') {
-        if (yych <= 0x00)
-          goto yy648;
-        if (yych <= '"')
-          goto yy683;
-        goto yy651;
-      } else {
-        if (yych <= 0xC1)
-          goto yy648;
-        if (yych >= 0xE0)
-          goto yy653;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy655;
-        goto yy654;
-      } else {
-        if (yych <= 0xF0)
-          goto yy656;
-        if (yych <= 0xF3)
-          goto yy657;
-        if (yych <= 0xF4)
-          goto yy658;
-        goto yy648;
-      }
-    }
-  yy652:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy646;
-    goto yy648;
-  yy653:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy652;
-    goto yy648;
-  yy654:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy652;
-    goto yy648;
-  yy655:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0x9F)
-      goto yy652;
-    goto yy648;
-  yy656:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy654;
-    goto yy648;
-  yy657:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy654;
-    goto yy648;
-  yy658:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0x8F)
-      goto yy654;
-    goto yy648;
-  yy659:
-    yych = *++p;
-  yy660:
-    if (yybm[0 + yych] & 64) {
-      goto yy659;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '\\') {
-        if (yych <= 0x00)
-          goto yy648;
-        if (yych >= '(')
-          goto yy663;
-      } else {
-        if (yych <= 0xC1)
-          goto yy648;
-        if (yych <= 0xDF)
-          goto yy664;
-        goto yy665;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy667;
-        goto yy666;
-      } else {
-        if (yych <= 0xF0)
-          goto yy668;
-        if (yych <= 0xF3)
-          goto yy669;
-        if (yych <= 0xF4)
-          goto yy670;
-        goto yy648;
-      }
-    }
-  yy661:
-    ++p;
-  yy662 : { return (bufsize_t)(p - start); }
-  yy663:
-    yych = *++p;
-    if (yybm[0 + yych] & 64) {
-      goto yy659;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '\\') {
-        if (yych <= 0x00)
-          goto yy648;
-        if (yych <= '\'')
-          goto yy684;
-        goto yy663;
-      } else {
-        if (yych <= 0xC1)
-          goto yy648;
-        if (yych >= 0xE0)
-          goto yy665;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy667;
-        goto yy666;
-      } else {
-        if (yych <= 0xF0)
-          goto yy668;
-        if (yych <= 0xF3)
-          goto yy669;
-        if (yych <= 0xF4)
-          goto yy670;
-        goto yy648;
-      }
-    }
-  yy664:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy659;
-    goto yy648;
-  yy665:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy664;
-    goto yy648;
-  yy666:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy664;
-    goto yy648;
-  yy667:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0x9F)
-      goto yy664;
-    goto yy648;
-  yy668:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy666;
-    goto yy648;
-  yy669:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy666;
-    goto yy648;
-  yy670:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0x8F)
-      goto yy666;
-    goto yy648;
-  yy671:
-    yych = *++p;
-  yy672:
-    if (yybm[0 + yych] & 128) {
-      goto yy671;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '\\') {
-        if (yych <= '(')
-          goto yy648;
-        if (yych >= '*')
-          goto yy675;
-      } else {
-        if (yych <= 0xC1)
-          goto yy648;
-        if (yych <= 0xDF)
-          goto yy676;
-        goto yy677;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy679;
-        goto yy678;
-      } else {
-        if (yych <= 0xF0)
-          goto yy680;
-        if (yych <= 0xF3)
-          goto yy681;
-        if (yych <= 0xF4)
-          goto yy682;
-        goto yy648;
-      }
-    }
-  yy673:
-    ++p;
-  yy674 : { return (bufsize_t)(p - start); }
-  yy675:
-    yych = *++p;
-    if (yych <= 0xDF) {
-      if (yych <= '[') {
-        if (yych <= 0x00)
-          goto yy648;
-        if (yych == ')')
-          goto yy685;
-        goto yy671;
-      } else {
-        if (yych <= '\\')
-          goto yy675;
-        if (yych <= 0x7F)
-          goto yy671;
-        if (yych <= 0xC1)
-          goto yy648;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych <= 0xE0)
-          goto yy677;
-        if (yych == 0xED)
-          goto yy679;
-        goto yy678;
-      } else {
-        if (yych <= 0xF0)
-          goto yy680;
-        if (yych <= 0xF3)
-          goto yy681;
-        if (yych <= 0xF4)
-          goto yy682;
-        goto yy648;
-      }
-    }
-  yy676:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy671;
-    goto yy648;
-  yy677:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy676;
-    goto yy648;
-  yy678:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy676;
-    goto yy648;
-  yy679:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0x9F)
-      goto yy676;
-    goto yy648;
-  yy680:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy678;
-    goto yy648;
-  yy681:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0xBF)
-      goto yy678;
-    goto yy648;
-  yy682:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy648;
-    if (yych <= 0x8F)
-      goto yy678;
-    goto yy648;
-  yy683:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 16) {
-      goto yy646;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '\\') {
-        if (yych <= 0x00)
-          goto yy650;
-        if (yych <= '"')
-          goto yy649;
-        goto yy651;
-      } else {
-        if (yych <= 0xC1)
-          goto yy650;
-        if (yych <= 0xDF)
-          goto yy652;
-        goto yy653;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy655;
-        goto yy654;
-      } else {
-        if (yych <= 0xF0)
-          goto yy656;
-        if (yych <= 0xF3)
-          goto yy657;
-        if (yych <= 0xF4)
-          goto yy658;
-        goto yy650;
-      }
-    }
-  yy684:
-    yyaccept = 2;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 64) {
-      goto yy659;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '\\') {
-        if (yych <= 0x00)
-          goto yy662;
-        if (yych <= '\'')
-          goto yy661;
-        goto yy663;
-      } else {
-        if (yych <= 0xC1)
-          goto yy662;
-        if (yych <= 0xDF)
-          goto yy664;
-        goto yy665;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy667;
-        goto yy666;
-      } else {
-        if (yych <= 0xF0)
-          goto yy668;
-        if (yych <= 0xF3)
-          goto yy669;
-        if (yych <= 0xF4)
-          goto yy670;
-        goto yy662;
-      }
-    }
-  yy685:
-    yyaccept = 3;
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 128) {
-      goto yy671;
-    }
-    if (yych <= 0xE0) {
-      if (yych <= '\\') {
-        if (yych <= '(')
-          goto yy674;
-        if (yych <= ')')
-          goto yy673;
-        goto yy675;
-      } else {
-        if (yych <= 0xC1)
-          goto yy674;
-        if (yych <= 0xDF)
-          goto yy676;
-        goto yy677;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych == 0xED)
-          goto yy679;
-        goto yy678;
-      } else {
-        if (yych <= 0xF0)
-          goto yy680;
-        if (yych <= 0xF3)
-          goto yy681;
-        if (yych <= 0xF4)
-          goto yy682;
-        goto yy674;
-      }
-    }
-  }
-}
-
-// Match space characters, including newlines.
-bufsize_t _scan_spacechars(const unsigned char *p) {
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    static const unsigned char yybm[] = {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   128, 0,   0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0,   0,   0,   0, 0,
-    };
-    yych = *p;
-    if (yybm[0 + yych] & 128) {
-      goto yy687;
-    }
-    ++p;
-    { return 0; }
-  yy687:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy687;
-    }
-    { return (bufsize_t)(p - start); }
-  }
-}
-
-// Match ATX heading start.
-bufsize_t _scan_atx_heading_start(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    static const unsigned char yybm[] = {
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,   0,   0, 0, 0,
-    };
-    yych = *p;
-    if (yych == '#')
-      goto yy690;
-    ++p;
-  yy689 : { return 0; }
-  yy690:
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 128) {
-      goto yy691;
-    }
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy689;
-      if (yych <= '\n')
-        goto yy693;
-      goto yy689;
-    } else {
-      if (yych <= '\r')
-        goto yy693;
-      if (yych == '#')
-        goto yy694;
-      goto yy689;
-    }
-  yy691:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy691;
-    }
-  yy692 : { return (bufsize_t)(p - start); }
-  yy693:
-    ++p;
-    goto yy692;
-  yy694:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy691;
-    }
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy695;
-      if (yych <= '\n')
-        goto yy693;
-    } else {
-      if (yych <= '\r')
-        goto yy693;
-      if (yych == '#')
-        goto yy696;
-    }
-  yy695:
-    p = marker;
-    goto yy689;
-  yy696:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy691;
-    }
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy695;
-      if (yych <= '\n')
-        goto yy693;
-      goto yy695;
-    } else {
-      if (yych <= '\r')
-        goto yy693;
-      if (yych != '#')
-        goto yy695;
-    }
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy691;
-    }
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy695;
-      if (yych <= '\n')
-        goto yy693;
-      goto yy695;
-    } else {
-      if (yych <= '\r')
-        goto yy693;
-      if (yych != '#')
-        goto yy695;
-    }
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy691;
-    }
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy695;
-      if (yych <= '\n')
-        goto yy693;
-      goto yy695;
-    } else {
-      if (yych <= '\r')
-        goto yy693;
-      if (yych != '#')
-        goto yy695;
-    }
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy691;
-    }
-    if (yych <= 0x08)
-      goto yy695;
-    if (yych <= '\n')
-      goto yy693;
-    if (yych == '\r')
-      goto yy693;
-    goto yy695;
-  }
-}
-
-// Match setext heading line.  Return 1 for level-1 heading,
-// 2 for level-2, 0 for no match.
-bufsize_t _scan_setext_heading_line(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-
-  {
-    unsigned char yych;
-    static const unsigned char yybm[] = {
-        0, 0,  0, 0, 0, 0, 0, 0, 0, 32, 0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  32, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-        0, 64, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0,
-        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0,
-        0, 0,  0, 0, 0, 0, 0, 0, 0, 0,  0,  0, 0, 0,
-    };
-    yych = *p;
-    if (yych == '-')
-      goto yy699;
-    if (yych == '=')
-      goto yy700;
-    ++p;
-  yy698 : { return 0; }
-  yy699:
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 64) {
-      goto yy705;
-    }
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy698;
-      if (yych <= '\n')
-        goto yy702;
-      goto yy698;
-    } else {
-      if (yych <= '\r')
-        goto yy702;
-      if (yych == ' ')
-        goto yy702;
-      goto yy698;
-    }
-  yy700:
-    yych = *(marker = ++p);
-    if (yybm[0 + yych] & 128) {
-      goto yy709;
-    }
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy698;
-      if (yych <= '\n')
-        goto yy707;
-      goto yy698;
-    } else {
-      if (yych <= '\r')
-        goto yy707;
-      if (yych == ' ')
-        goto yy707;
-      goto yy698;
-    }
-  yy701:
-    yych = *++p;
-  yy702:
-    if (yybm[0 + yych] & 32) {
-      goto yy701;
-    }
-    if (yych <= 0x08)
-      goto yy703;
-    if (yych <= '\n')
-      goto yy704;
-    if (yych == '\r')
-      goto yy704;
-  yy703:
-    p = marker;
-    goto yy698;
-  yy704:
-    ++p;
-    { return 2; }
-  yy705:
-    yych = *++p;
-    if (yybm[0 + yych] & 32) {
-      goto yy701;
-    }
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy703;
-      if (yych <= '\n')
-        goto yy704;
-      goto yy703;
-    } else {
-      if (yych <= '\r')
-        goto yy704;
-      if (yych == '-')
-        goto yy705;
-      goto yy703;
-    }
-  yy706:
-    yych = *++p;
-  yy707:
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy703;
-      if (yych <= '\t')
-        goto yy706;
-      if (yych >= '\v')
-        goto yy703;
-    } else {
-      if (yych <= '\r')
-        goto yy708;
-      if (yych == ' ')
-        goto yy706;
-      goto yy703;
-    }
-  yy708:
-    ++p;
-    { return 1; }
-  yy709:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy709;
-    }
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy703;
-      if (yych <= '\t')
-        goto yy706;
-      if (yych <= '\n')
-        goto yy708;
-      goto yy703;
-    } else {
-      if (yych <= '\r')
-        goto yy708;
-      if (yych == ' ')
-        goto yy706;
-      goto yy703;
-    }
-  }
-}
-
-// Scan an opening code fence.
-bufsize_t _scan_open_code_fence(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    static const unsigned char yybm[] = {
-        0,   192, 192, 192, 192, 192, 192, 192, 192, 192, 0,   192, 192, 0,
-        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
-        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
-        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
-        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
-        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
-        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 144, 192,
-        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
-        192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
-        224, 192, 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-        0,   0,   0,   0,
-    };
-    yych = *p;
-    if (yych == '`')
-      goto yy712;
-    if (yych == '~')
-      goto yy713;
-    ++p;
-  yy711 : { return 0; }
-  yy712:
-    yych = *(marker = ++p);
-    if (yych == '`')
-      goto yy714;
-    goto yy711;
-  yy713:
-    yych = *(marker = ++p);
-    if (yych == '~')
-      goto yy716;
-    goto yy711;
-  yy714:
-    yych = *++p;
-    if (yybm[0 + yych] & 16) {
-      goto yy717;
-    }
-  yy715:
-    p = marker;
-    goto yy711;
-  yy716:
-    yych = *++p;
-    if (yybm[0 + yych] & 32) {
-      goto yy718;
-    }
-    goto yy715;
-  yy717:
-    yych = *++p;
-    if (yybm[0 + yych] & 16) {
-      goto yy717;
-    }
-    if (yych <= 0xDF) {
-      if (yych <= '\f') {
-        if (yych <= 0x00)
-          goto yy715;
-        if (yych == '\n') {
-          marker = p;
-          goto yy720;
-        }
-        marker = p;
-        goto yy719;
-      } else {
-        if (yych <= '\r') {
-          marker = p;
-          goto yy720;
-        }
-        if (yych <= 0x7F) {
-          marker = p;
-          goto yy719;
-        }
-        if (yych <= 0xC1)
-          goto yy715;
-        marker = p;
-        goto yy721;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych <= 0xE0) {
-          marker = p;
-          goto yy722;
-        }
-        if (yych == 0xED) {
-          marker = p;
-          goto yy724;
-        }
-        marker = p;
-        goto yy723;
-      } else {
-        if (yych <= 0xF0) {
-          marker = p;
-          goto yy725;
-        }
-        if (yych <= 0xF3) {
-          marker = p;
-          goto yy726;
-        }
-        if (yych <= 0xF4) {
-          marker = p;
-          goto yy727;
-        }
-        goto yy715;
-      }
-    }
-  yy718:
-    yych = *++p;
-    if (yybm[0 + yych] & 32) {
-      goto yy718;
-    }
-    if (yych <= 0xDF) {
-      if (yych <= '\f') {
-        if (yych <= 0x00)
-          goto yy715;
-        if (yych == '\n') {
-          marker = p;
-          goto yy729;
-        }
-        marker = p;
-        goto yy728;
-      } else {
-        if (yych <= '\r') {
-          marker = p;
-          goto yy729;
-        }
-        if (yych <= 0x7F) {
-          marker = p;
-          goto yy728;
-        }
-        if (yych <= 0xC1)
-          goto yy715;
-        marker = p;
-        goto yy730;
-      }
-    } else {
-      if (yych <= 0xEF) {
-        if (yych <= 0xE0) {
-          marker = p;
-          goto yy731;
-        }
-        if (yych == 0xED) {
-          marker = p;
-          goto yy733;
-        }
-        marker = p;
-        goto yy732;
-      } else {
-        if (yych <= 0xF0) {
-          marker = p;
-          goto yy734;
-        }
-        if (yych <= 0xF3) {
-          marker = p;
-          goto yy735;
-        }
-        if (yych <= 0xF4) {
-          marker = p;
-          goto yy736;
-        }
-        goto yy715;
-      }
-    }
-  yy719:
-    yych = *++p;
-    if (yybm[0 + yych] & 64) {
-      goto yy719;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy715;
-        if (yych >= 0x0E)
-          goto yy715;
-      } else {
-        if (yych <= 0xDF)
-          goto yy721;
-        if (yych <= 0xE0)
-          goto yy722;
-        goto yy723;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy724;
-        if (yych <= 0xEF)
-          goto yy723;
-        goto yy725;
-      } else {
-        if (yych <= 0xF3)
-          goto yy726;
-        if (yych <= 0xF4)
-          goto yy727;
-        goto yy715;
-      }
-    }
-  yy720:
-    ++p;
-    p = marker;
-    { return (bufsize_t)(p - start); }
-  yy721:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy715;
-    if (yych <= 0xBF)
-      goto yy719;
-    goto yy715;
-  yy722:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy715;
-    if (yych <= 0xBF)
-      goto yy721;
-    goto yy715;
-  yy723:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy715;
-    if (yych <= 0xBF)
-      goto yy721;
-    goto yy715;
-  yy724:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy715;
-    if (yych <= 0x9F)
-      goto yy721;
-    goto yy715;
-  yy725:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy715;
-    if (yych <= 0xBF)
-      goto yy723;
-    goto yy715;
-  yy726:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy715;
-    if (yych <= 0xBF)
-      goto yy723;
-    goto yy715;
-  yy727:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy715;
-    if (yych <= 0x8F)
-      goto yy723;
-    goto yy715;
-  yy728:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy728;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= 0x00)
-          goto yy715;
-        if (yych >= 0x0E)
-          goto yy715;
-      } else {
-        if (yych <= 0xDF)
-          goto yy730;
-        if (yych <= 0xE0)
-          goto yy731;
-        goto yy732;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy733;
-        if (yych <= 0xEF)
-          goto yy732;
-        goto yy734;
-      } else {
-        if (yych <= 0xF3)
-          goto yy735;
-        if (yych <= 0xF4)
-          goto yy736;
-        goto yy715;
-      }
-    }
-  yy729:
-    ++p;
-    p = marker;
-    { return (bufsize_t)(p - start); }
-  yy730:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy715;
-    if (yych <= 0xBF)
-      goto yy728;
-    goto yy715;
-  yy731:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy715;
-    if (yych <= 0xBF)
-      goto yy730;
-    goto yy715;
-  yy732:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy715;
-    if (yych <= 0xBF)
-      goto yy730;
-    goto yy715;
-  yy733:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy715;
-    if (yych <= 0x9F)
-      goto yy730;
-    goto yy715;
-  yy734:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy715;
-    if (yych <= 0xBF)
-      goto yy732;
-    goto yy715;
-  yy735:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy715;
-    if (yych <= 0xBF)
-      goto yy732;
-    goto yy715;
-  yy736:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy715;
-    if (yych <= 0x8F)
-      goto yy732;
-    goto yy715;
-  }
-}
-
-// Scan a closing code fence with length at least len.
-bufsize_t _scan_close_code_fence(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    static const unsigned char yybm[] = {
-        0, 0, 0, 0, 0, 0, 0, 0, 0,  128, 0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   128, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 32, 0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0, 0,  0,   0,   0, 0, 0,
-    };
-    yych = *p;
-    if (yych == '`')
-      goto yy739;
-    if (yych == '~')
-      goto yy740;
-    ++p;
-  yy738 : { return 0; }
-  yy739:
-    yych = *(marker = ++p);
-    if (yych == '`')
-      goto yy741;
-    goto yy738;
-  yy740:
-    yych = *(marker = ++p);
-    if (yych == '~')
-      goto yy743;
-    goto yy738;
-  yy741:
-    yych = *++p;
-    if (yybm[0 + yych] & 32) {
-      goto yy744;
-    }
-  yy742:
-    p = marker;
-    goto yy738;
-  yy743:
-    yych = *++p;
-    if (yybm[0 + yych] & 64) {
-      goto yy745;
-    }
-    goto yy742;
-  yy744:
-    yych = *++p;
-    if (yybm[0 + yych] & 32) {
-      goto yy744;
-    }
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy742;
-      if (yych <= '\t') {
-        marker = p;
-        goto yy746;
-      }
-      if (yych <= '\n') {
-        marker = p;
-        goto yy747;
-      }
-      goto yy742;
-    } else {
-      if (yych <= '\r') {
-        marker = p;
-        goto yy747;
-      }
-      if (yych == ' ') {
-        marker = p;
-        goto yy746;
-      }
-      goto yy742;
-    }
-  yy745:
-    yych = *++p;
-    if (yybm[0 + yych] & 64) {
-      goto yy745;
-    }
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy742;
-      if (yych <= '\t') {
-        marker = p;
-        goto yy748;
-      }
-      if (yych <= '\n') {
-        marker = p;
-        goto yy749;
-      }
-      goto yy742;
-    } else {
-      if (yych <= '\r') {
-        marker = p;
-        goto yy749;
-      }
-      if (yych == ' ') {
-        marker = p;
-        goto yy748;
-      }
-      goto yy742;
-    }
-  yy746:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy746;
-    }
-    if (yych <= 0x08)
-      goto yy742;
-    if (yych <= '\n')
-      goto yy747;
-    if (yych != '\r')
-      goto yy742;
-  yy747:
-    ++p;
-    p = marker;
-    { return (bufsize_t)(p - start); }
-  yy748:
-    yych = *++p;
-    if (yych <= '\f') {
-      if (yych <= 0x08)
-        goto yy742;
-      if (yych <= '\t')
-        goto yy748;
-      if (yych >= '\v')
-        goto yy742;
-    } else {
-      if (yych <= '\r')
-        goto yy749;
-      if (yych == ' ')
-        goto yy748;
-      goto yy742;
-    }
-  yy749:
-    ++p;
-    p = marker;
-    { return (bufsize_t)(p - start); }
-  }
-}
-
-// Scans an entity.
-// Returns number of chars matched.
-bufsize_t _scan_entity(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    yych = *p;
-    if (yych == '&')
-      goto yy752;
-    ++p;
-  yy751 : { return 0; }
-  yy752:
-    yych = *(marker = ++p);
-    if (yych <= '@') {
-      if (yych != '#')
-        goto yy751;
-    } else {
-      if (yych <= 'Z')
-        goto yy754;
-      if (yych <= '`')
-        goto yy751;
-      if (yych <= 'z')
-        goto yy754;
-      goto yy751;
-    }
-    yych = *++p;
-    if (yych <= 'W') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy755;
-    } else {
-      if (yych <= 'X')
-        goto yy756;
-      if (yych == 'x')
-        goto yy756;
-    }
-  yy753:
-    p = marker;
-    goto yy751;
-  yy754:
-    yych = *++p;
-    if (yych <= '@') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy757;
-      goto yy753;
-    } else {
-      if (yych <= 'Z')
-        goto yy757;
-      if (yych <= '`')
-        goto yy753;
-      if (yych <= 'z')
-        goto yy757;
-      goto yy753;
-    }
-  yy755:
-    yych = *++p;
-    if (yych <= '/')
-      goto yy753;
-    if (yych <= '9')
-      goto yy758;
-    if (yych == ';')
-      goto yy759;
-    goto yy753;
-  yy756:
-    yych = *++p;
-    if (yych <= '@') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy760;
-      goto yy753;
-    } else {
-      if (yych <= 'F')
-        goto yy760;
-      if (yych <= '`')
-        goto yy753;
-      if (yych <= 'f')
-        goto yy760;
-      goto yy753;
-    }
-  yy757:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy761;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy761;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'z')
-          goto yy761;
-        goto yy753;
-      }
-    }
-  yy758:
-    yych = *++p;
-    if (yych <= '/')
-      goto yy753;
-    if (yych <= '9')
-      goto yy762;
-    if (yych != ';')
-      goto yy753;
-  yy759:
-    ++p;
-    { return (bufsize_t)(p - start); }
-  yy760:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy763;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'F') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy763;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'f')
-          goto yy763;
-        goto yy753;
-      }
-    }
-  yy761:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy764;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy764;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'z')
-          goto yy764;
-        goto yy753;
-      }
-    }
-  yy762:
-    yych = *++p;
-    if (yych <= '/')
-      goto yy753;
-    if (yych <= '9')
-      goto yy765;
-    if (yych == ';')
-      goto yy759;
-    goto yy753;
-  yy763:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy766;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'F') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy766;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'f')
-          goto yy766;
-        goto yy753;
-      }
-    }
-  yy764:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy767;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy767;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'z')
-          goto yy767;
-        goto yy753;
-      }
-    }
-  yy765:
-    yych = *++p;
-    if (yych <= '/')
-      goto yy753;
-    if (yych <= '9')
-      goto yy768;
-    if (yych == ';')
-      goto yy759;
-    goto yy753;
-  yy766:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy769;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'F') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy769;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'f')
-          goto yy769;
-        goto yy753;
-      }
-    }
-  yy767:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy770;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy770;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'z')
-          goto yy770;
-        goto yy753;
-      }
-    }
-  yy768:
-    yych = *++p;
-    if (yych <= '/')
-      goto yy753;
-    if (yych <= '9')
-      goto yy771;
-    if (yych == ';')
-      goto yy759;
-    goto yy753;
-  yy769:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy772;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'F') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy772;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'f')
-          goto yy772;
-        goto yy753;
-      }
-    }
-  yy770:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy773;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy773;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'z')
-          goto yy773;
-        goto yy753;
-      }
-    }
-  yy771:
-    yych = *++p;
-    if (yych <= '/')
-      goto yy753;
-    if (yych <= '9')
-      goto yy774;
-    if (yych == ';')
-      goto yy759;
-    goto yy753;
-  yy772:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy774;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'F') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy774;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'f')
-          goto yy774;
-        goto yy753;
-      }
-    }
-  yy773:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy775;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy775;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'z')
-          goto yy775;
-        goto yy753;
-      }
-    }
-  yy774:
-    yych = *++p;
-    if (yych == ';')
-      goto yy759;
-    goto yy753;
-  yy775:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy776;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy776:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy777;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy777:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy778;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy778:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy779;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy779:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy780;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy780:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy781;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy781:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy782;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy782:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy783;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy783:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy784;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy784:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy785;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy785:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy786;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy786:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy787;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy787:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy788;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy788:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy789;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy789:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy790;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy790:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy791;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy791:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy792;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy792:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy793;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy793:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy794;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy794:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy795;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy795:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy796;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy796:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy797;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy797:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy798;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych >= '{')
-          goto yy753;
-      }
-    }
-  yy798:
-    yych = *++p;
-    if (yych <= ';') {
-      if (yych <= '/')
-        goto yy753;
-      if (yych <= '9')
-        goto yy774;
-      if (yych <= ':')
-        goto yy753;
-      goto yy759;
-    } else {
-      if (yych <= 'Z') {
-        if (yych <= '@')
-          goto yy753;
-        goto yy774;
-      } else {
-        if (yych <= '`')
-          goto yy753;
-        if (yych <= 'z')
-          goto yy774;
-        goto yy753;
-      }
-    }
-  }
-}
-
-// Returns positive value if a URL begins in a way that is potentially
-// dangerous, with javascript:, vbscript:, file:, or data:, otherwise 0.
-bufsize_t _scan_dangerous_url(const unsigned char *p) {
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-
-  {
-    unsigned char yych;
-    unsigned int yyaccept = 0;
-    yych = *p;
-    if (yych <= 'V') {
-      if (yych <= 'F') {
-        if (yych == 'D')
-          goto yy801;
-        if (yych >= 'F')
-          goto yy802;
-      } else {
-        if (yych == 'J')
-          goto yy803;
-        if (yych >= 'V')
-          goto yy804;
-      }
-    } else {
-      if (yych <= 'f') {
-        if (yych == 'd')
-          goto yy801;
-        if (yych >= 'f')
-          goto yy802;
-      } else {
-        if (yych <= 'j') {
-          if (yych >= 'j')
-            goto yy803;
-        } else {
-          if (yych == 'v')
-            goto yy804;
-        }
-      }
-    }
-    ++p;
-  yy800 : { return 0; }
-  yy801:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych == 'A')
-      goto yy805;
-    if (yych == 'a')
-      goto yy805;
-    goto yy800;
-  yy802:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych == 'I')
-      goto yy807;
-    if (yych == 'i')
-      goto yy807;
-    goto yy800;
-  yy803:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych == 'A')
-      goto yy808;
-    if (yych == 'a')
-      goto yy808;
-    goto yy800;
-  yy804:
-    yyaccept = 0;
-    yych = *(marker = ++p);
-    if (yych == 'B')
-      goto yy809;
-    if (yych == 'b')
-      goto yy809;
-    goto yy800;
-  yy805:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy810;
-    if (yych == 't')
-      goto yy810;
-  yy806:
-    p = marker;
-    if (yyaccept == 0) {
-      goto yy800;
-    } else {
-      goto yy818;
-    }
-  yy807:
-    yych = *++p;
-    if (yych == 'L')
-      goto yy811;
-    if (yych == 'l')
-      goto yy811;
-    goto yy806;
-  yy808:
-    yych = *++p;
-    if (yych == 'V')
-      goto yy812;
-    if (yych == 'v')
-      goto yy812;
-    goto yy806;
-  yy809:
-    yych = *++p;
-    if (yych == 'S')
-      goto yy813;
-    if (yych == 's')
-      goto yy813;
-    goto yy806;
-  yy810:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy814;
-    if (yych == 'a')
-      goto yy814;
-    goto yy806;
-  yy811:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy815;
-    if (yych == 'e')
-      goto yy815;
-    goto yy806;
-  yy812:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy809;
-    if (yych == 'a')
-      goto yy809;
-    goto yy806;
-  yy813:
-    yych = *++p;
-    if (yych == 'C')
-      goto yy816;
-    if (yych == 'c')
-      goto yy816;
-    goto yy806;
-  yy814:
-    yych = *++p;
-    if (yych == ':')
-      goto yy817;
-    goto yy806;
-  yy815:
-    yych = *++p;
-    if (yych == ':')
-      goto yy819;
-    goto yy806;
-  yy816:
-    yych = *++p;
-    if (yych == 'R')
-      goto yy820;
-    if (yych == 'r')
-      goto yy820;
-    goto yy806;
-  yy817:
-    yyaccept = 1;
-    yych = *(marker = ++p);
-    if (yych == 'I')
-      goto yy821;
-    if (yych == 'i')
-      goto yy821;
-  yy818 : { return (bufsize_t)(p - start); }
-  yy819:
-    ++p;
-    goto yy818;
-  yy820:
-    yych = *++p;
-    if (yych == 'I')
-      goto yy822;
-    if (yych == 'i')
-      goto yy822;
-    goto yy806;
-  yy821:
-    yych = *++p;
-    if (yych == 'M')
-      goto yy823;
-    if (yych == 'm')
-      goto yy823;
-    goto yy806;
-  yy822:
-    yych = *++p;
-    if (yych == 'P')
-      goto yy824;
-    if (yych == 'p')
-      goto yy824;
-    goto yy806;
-  yy823:
-    yych = *++p;
-    if (yych == 'A')
-      goto yy825;
-    if (yych == 'a')
-      goto yy825;
-    goto yy806;
-  yy824:
-    yych = *++p;
-    if (yych == 'T')
-      goto yy815;
-    if (yych == 't')
-      goto yy815;
-    goto yy806;
-  yy825:
-    yych = *++p;
-    if (yych == 'G')
-      goto yy826;
-    if (yych != 'g')
-      goto yy806;
-  yy826:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy827;
-    if (yych != 'e')
-      goto yy806;
-  yy827:
-    yych = *++p;
-    if (yych != '/')
-      goto yy806;
-    yych = *++p;
-    if (yych <= 'W') {
-      if (yych <= 'J') {
-        if (yych == 'G')
-          goto yy828;
-        if (yych <= 'I')
-          goto yy806;
-        goto yy829;
-      } else {
-        if (yych == 'P')
-          goto yy830;
-        if (yych <= 'V')
-          goto yy806;
-        goto yy831;
-      }
-    } else {
-      if (yych <= 'j') {
-        if (yych == 'g')
-          goto yy828;
-        if (yych <= 'i')
-          goto yy806;
-        goto yy829;
-      } else {
-        if (yych <= 'p') {
-          if (yych <= 'o')
-            goto yy806;
-          goto yy830;
-        } else {
-          if (yych == 'w')
-            goto yy831;
-          goto yy806;
-        }
-      }
-    }
-  yy828:
-    yych = *++p;
-    if (yych == 'I')
-      goto yy832;
-    if (yych == 'i')
-      goto yy832;
-    goto yy806;
-  yy829:
-    yych = *++p;
-    if (yych == 'P')
-      goto yy833;
-    if (yych == 'p')
-      goto yy833;
-    goto yy806;
-  yy830:
-    yych = *++p;
-    if (yych == 'N')
-      goto yy834;
-    if (yych == 'n')
-      goto yy834;
-    goto yy806;
-  yy831:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy835;
-    if (yych == 'e')
-      goto yy835;
-    goto yy806;
-  yy832:
-    yych = *++p;
-    if (yych == 'F')
-      goto yy836;
-    if (yych == 'f')
-      goto yy836;
-    goto yy806;
-  yy833:
-    yych = *++p;
-    if (yych == 'E')
-      goto yy834;
-    if (yych != 'e')
-      goto yy806;
-  yy834:
-    yych = *++p;
-    if (yych == 'G')
-      goto yy836;
-    if (yych == 'g')
-      goto yy836;
-    goto yy806;
-  yy835:
-    yych = *++p;
-    if (yych == 'B')
-      goto yy837;
-    if (yych == 'b')
-      goto yy837;
-    goto yy806;
-  yy836:
-    ++p;
-    { return 0; }
-  yy837:
-    yych = *++p;
-    if (yych == 'P')
-      goto yy836;
-    if (yych == 'p')
-      goto yy836;
-    goto yy806;
-  }
-}
-
-// 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 yy840;
-    ++p;
-  yy839 : { return 0; }
-  yy840:
-    yych = *(marker = ++p);
-    if (yych != '^')
-      goto yy839;
-    yych = *++p;
-    if (yych != ']')
-      goto yy843;
-  yy841:
-    p = marker;
-    goto yy839;
-  yy842:
-    yych = *++p;
-  yy843:
-    if (yybm[0 + yych] & 64) {
-      goto yy842;
-    }
-    if (yych <= 0xEC) {
-      if (yych <= 0xC1) {
-        if (yych <= ' ')
-          goto yy841;
-        if (yych <= ']')
-          goto yy851;
-        goto yy841;
-      } else {
-        if (yych <= 0xDF)
-          goto yy844;
-        if (yych <= 0xE0)
-          goto yy845;
-        goto yy846;
-      }
-    } else {
-      if (yych <= 0xF0) {
-        if (yych <= 0xED)
-          goto yy847;
-        if (yych <= 0xEF)
-          goto yy846;
-        goto yy848;
-      } else {
-        if (yych <= 0xF3)
-          goto yy849;
-        if (yych <= 0xF4)
-          goto yy850;
-        goto yy841;
-      }
-    }
-  yy844:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy841;
-    if (yych <= 0xBF)
-      goto yy842;
-    goto yy841;
-  yy845:
-    yych = *++p;
-    if (yych <= 0x9F)
-      goto yy841;
-    if (yych <= 0xBF)
-      goto yy844;
-    goto yy841;
-  yy846:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy841;
-    if (yych <= 0xBF)
-      goto yy844;
-    goto yy841;
-  yy847:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy841;
-    if (yych <= 0x9F)
-      goto yy844;
-    goto yy841;
-  yy848:
-    yych = *++p;
-    if (yych <= 0x8F)
-      goto yy841;
-    if (yych <= 0xBF)
-      goto yy846;
-    goto yy841;
-  yy849:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy841;
-    if (yych <= 0xBF)
-      goto yy846;
-    goto yy841;
-  yy850:
-    yych = *++p;
-    if (yych <= 0x7F)
-      goto yy841;
-    if (yych <= 0x8F)
-      goto yy846;
-    goto yy841;
-  yy851:
-    yych = *++p;
-    if (yych != ':')
-      goto yy841;
-  yy852:
-    yych = *++p;
-    if (yybm[0 + yych] & 128) {
-      goto yy852;
-    }
-    { return (bufsize_t)(p - start); }
-  }
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/scanners.h b/vendor/core/vendor/cmark-gfm/src/scanners.h
deleted file mode 100644
index 7e6a10aeb..000000000
--- a/vendor/core/vendor/cmark-gfm/src/scanners.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef CMARK_SCANNERS_H
-#define CMARK_SCANNERS_H
-
-#include "cmark-gfm.h"
-#include "chunk.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c,
-                   bufsize_t offset);
-bufsize_t _scan_scheme(const unsigned char *p);
-bufsize_t _scan_autolink_uri(const unsigned char *p);
-bufsize_t _scan_autolink_email(const unsigned char *p);
-bufsize_t _scan_html_tag(const unsigned char *p);
-bufsize_t _scan_liberal_html_tag(const unsigned char *p);
-bufsize_t _scan_html_comment(const unsigned char *p);
-bufsize_t _scan_html_pi(const unsigned char *p);
-bufsize_t _scan_html_declaration(const unsigned char *p);
-bufsize_t _scan_html_cdata(const unsigned char *p);
-bufsize_t _scan_html_block_start(const unsigned char *p);
-bufsize_t _scan_html_block_start_7(const unsigned char *p);
-bufsize_t _scan_html_block_end_1(const unsigned char *p);
-bufsize_t _scan_html_block_end_2(const unsigned char *p);
-bufsize_t _scan_html_block_end_3(const unsigned char *p);
-bufsize_t _scan_html_block_end_4(const unsigned char *p);
-bufsize_t _scan_html_block_end_5(const unsigned char *p);
-bufsize_t _scan_link_title(const unsigned char *p);
-bufsize_t _scan_spacechars(const unsigned char *p);
-bufsize_t _scan_atx_heading_start(const unsigned char *p);
-bufsize_t _scan_setext_heading_line(const unsigned char *p);
-bufsize_t _scan_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_comment(c, n) _scan_at(&_scan_html_comment, c, n)
-#define scan_html_pi(c, n) _scan_at(&_scan_html_pi, c, n)
-#define scan_html_declaration(c, n) _scan_at(&_scan_html_declaration, c, n)
-#define scan_html_cdata(c, n) _scan_at(&_scan_html_cdata, c, n)
-#define scan_html_block_start(c, n) _scan_at(&_scan_html_block_start, c, n)
-#define scan_html_block_start_7(c, n) _scan_at(&_scan_html_block_start_7, c, n)
-#define scan_html_block_end_1(c, n) _scan_at(&_scan_html_block_end_1, c, n)
-#define scan_html_block_end_2(c, n) _scan_at(&_scan_html_block_end_2, c, n)
-#define scan_html_block_end_3(c, n) _scan_at(&_scan_html_block_end_3, c, n)
-#define scan_html_block_end_4(c, n) _scan_at(&_scan_html_block_end_4, c, n)
-#define scan_html_block_end_5(c, n) _scan_at(&_scan_html_block_end_5, c, n)
-#define scan_link_title(c, n) _scan_at(&_scan_link_title, c, n)
-#define scan_spacechars(c, n) _scan_at(&_scan_spacechars, c, n)
-#define scan_atx_heading_start(c, n) _scan_at(&_scan_atx_heading_start, c, n)
-#define scan_setext_heading_line(c, n)                                         \
-  _scan_at(&_scan_setext_heading_line, c, n)
-#define scan_open_code_fence(c, n) _scan_at(&_scan_open_code_fence, c, n)
-#define scan_close_code_fence(c, n) _scan_at(&_scan_close_code_fence, c, n)
-#define scan_entity(c, n) _scan_at(&_scan_entity, c, n)
-#define scan_dangerous_url(c, n) _scan_at(&_scan_dangerous_url, c, n)
-#define scan_footnote_definition(c, n) _scan_at(&_scan_footnote_definition, c, n)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/vendor/core/vendor/cmark-gfm/src/scanners.re b/vendor/core/vendor/cmark-gfm/src/scanners.re
deleted file mode 100644
index ac4b9cf4c..000000000
--- a/vendor/core/vendor/cmark-gfm/src/scanners.re
+++ /dev/null
@@ -1,365 +0,0 @@
-#include 
-#include "chunk.h"
-#include "scanners.h"
-
-bufsize_t _scan_at(bufsize_t (*scanner)(const unsigned char *), cmark_chunk *c, bufsize_t offset)
-{
-	bufsize_t res;
-	unsigned char *ptr = (unsigned char *)c->data;
-
-        if (ptr == NULL || offset > c->len) {
-          return 0;
-        } else {
-	  unsigned char lim = ptr[c->len];
-
-	  ptr[c->len] = '\0';
-	  res = scanner(ptr + offset);
-	  ptr[c->len] = lim;
-        }
-
-	return res;
-}
-
-/*!re2c
-  re2c:define:YYCTYPE  = "unsigned char";
-  re2c:define:YYCURSOR = p;
-  re2c:define:YYMARKER = marker;
-  re2c:define:YYCTXMARKER = marker;
-  re2c:yyfill:enable = 0;
-
-  wordchar = [^\x00-\x20];
-
-  spacechar = [ \t\v\f\r\n];
-
-  reg_char     = [^\\()\x00-\x20];
-
-  escaped_char = [\\][!"#$%&'()*+,./:;<=>?@[\\\]^_`{|}~-];
-
-  tagname = [A-Za-z][A-Za-z0-9-]*;
-
-  blocktagname = 'address'|'article'|'aside'|'base'|'basefont'|'blockquote'|'body'|'caption'|'center'|'col'|'colgroup'|'dd'|'details'|'dialog'|'dir'|'div'|'dl'|'dt'|'fieldset'|'figcaption'|'figure'|'footer'|'form'|'frame'|'frameset'|'h1'|'h2'|'h3'|'h4'|'h5'|'h6'|'head'|'header'|'hr'|'html'|'iframe'|'legend'|'li'|'link'|'main'|'menu'|'menuitem'|'nav'|'noframes'|'ol'|'optgroup'|'option'|'p'|'param'|'section'|'source'|'title'|'summary'|'table'|'tbody'|'td'|'tfoot'|'th'|'thead'|'title'|'tr'|'track'|'ul';
-
-  attributename = [a-zA-Z_:][a-zA-Z0-9:._-]*;
-
-  unquotedvalue = [^ \t\r\n\v\f"'=<>`\x00]+;
-  singlequotedvalue = ['][^'\x00]*['];
-  doublequotedvalue = ["][^"\x00]*["];
-
-  attributevalue = unquotedvalue | singlequotedvalue | doublequotedvalue;
-
-  attributevaluespec = spacechar* [=] spacechar* attributevalue;
-
-  attribute = spacechar+ attributename attributevaluespec?;
-
-  opentag = tagname attribute* spacechar* [/]? [>];
-  closetag = [/] tagname spacechar* [>];
-
-  htmlcomment = "--" ([^\x00-]+ | "-" [^\x00-] | "--" [^\x00>])* "-->";
-
-  processinginstruction = ([^?>\x00]+ | [?][^>\x00] | [>])+;
-
-  declaration = [A-Z]+ spacechar+ [^>\x00]*;
-
-  cdata = "CDATA[" ([^\]\x00]+ | "]" [^\]\x00] | "]]" [^>\x00])*;
-
-  htmltag = opentag | closetag;
-
-  in_parens_nosp   = [(] (reg_char|escaped_char|[\\])* [)];
-
-  in_double_quotes = ["] (escaped_char|[^"\x00])* ["];
-  in_single_quotes = ['] (escaped_char|[^'\x00])* ['];
-  in_parens        = [(] (escaped_char|[^)\x00])* [)];
-
-  scheme           = [A-Za-z][A-Za-z0-9.+-]{1,31};
-*/
-
-// Try to match a scheme including colon.
-bufsize_t _scan_scheme(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  scheme [:] { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Try to match URI autolink after first <, returning number of chars matched.
-bufsize_t _scan_autolink_uri(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  scheme [:][^\x00-\x20<>]*[>]  { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Try to match email autolink after first <, returning num of chars matched.
-bufsize_t _scan_autolink_email(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  [a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+
-    [@]
-    [a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?
-    ([.][a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*
-    [>] { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Try to match an HTML tag after first <, returning num of chars matched.
-bufsize_t _scan_html_tag(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  htmltag { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Try to (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; }
-*/
-}
-
-bufsize_t _scan_html_comment(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  htmlcomment { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-bufsize_t _scan_html_pi(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  processinginstruction { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-bufsize_t _scan_html_declaration(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  declaration { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-bufsize_t _scan_html_cdata(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  cdata { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Try to match an HTML block tag start line, returning
-// an integer code for the type of block (1-6, matching the spec).
-// #7 is handled by a separate function, below.
-bufsize_t _scan_html_block_start(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-/*!re2c
-  [<] ('script'|'pre'|'textarea'|'style') (spacechar | [>]) { return 1; }
-  '' { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Try to match an HTML block end line of type 3
-bufsize_t _scan_html_block_end_3(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  [^\n\x00]* '?>' { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Try to match an HTML block end line of type 4
-bufsize_t _scan_html_block_end_4(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  [^\n\x00]* '>' { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Try to match an HTML block end line of type 5
-bufsize_t _scan_html_block_end_5(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  [^\n\x00]* ']]>' { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Try to match a link title (in single quotes, in double quotes, or
-// in parentheses), returning number of chars matched.  Allow one
-// level of internal nesting (quotes within quotes).
-bufsize_t _scan_link_title(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  ["] (escaped_char|[^"\x00])* ["]   { return (bufsize_t)(p - start); }
-  ['] (escaped_char|[^'\x00])* ['] { return (bufsize_t)(p - start); }
-  [(] (escaped_char|[^()\x00])* [)]  { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Match space characters, including newlines.
-bufsize_t _scan_spacechars(const unsigned char *p)
-{
-  const unsigned char *start = p; \
-/*!re2c
-  [ \t\v\f\r\n]+ { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Match ATX heading start.
-bufsize_t _scan_atx_heading_start(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  [#]{1,6} ([ \t]+|[\r\n])  { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Match setext heading line.  Return 1 for level-1 heading,
-// 2 for level-2, 0 for no match.
-bufsize_t _scan_setext_heading_line(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-/*!re2c
-  [=]+ [ \t]* [\r\n] { return 1; }
-  [-]+ [ \t]* [\r\n] { return 2; }
-  * { return 0; }
-*/
-}
-
-// Scan an opening code fence.
-bufsize_t _scan_open_code_fence(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  [`]{3,} / [^`\r\n\x00]*[\r\n] { return (bufsize_t)(p - start); }
-  [~]{3,} / [^\r\n\x00]*[\r\n] { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Scan a closing code fence with length at least len.
-bufsize_t _scan_close_code_fence(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  [`]{3,} / [ \t]*[\r\n] { return (bufsize_t)(p - start); }
-  [~]{3,} / [ \t]*[\r\n] { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Scans an entity.
-// Returns number of chars matched.
-bufsize_t _scan_entity(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  [&] ([#] ([Xx][A-Fa-f0-9]{1,6}|[0-9]{1,7}) |[A-Za-z][A-Za-z0-9]{1,31} ) [;]
-     { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// Returns positive value if a URL begins in a way that is potentially
-// dangerous, with javascript:, vbscript:, file:, or data:, otherwise 0.
-bufsize_t _scan_dangerous_url(const unsigned char *p)
-{
-  const unsigned char *marker = NULL;
-  const unsigned char *start = p;
-/*!re2c
-  'data:image/' ('png'|'gif'|'jpeg'|'webp') { return 0; }
-  'javascript:' | 'vbscript:' | 'file:' | 'data:' { return (bufsize_t)(p - start); }
-  * { return 0; }
-*/
-}
-
-// 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/vendor/core/vendor/cmark-gfm/src/syntax_extension.c b/vendor/core/vendor/cmark-gfm/src/syntax_extension.c
deleted file mode 100644
index d24fe43e6..000000000
--- a/vendor/core/vendor/cmark-gfm/src/syntax_extension.c
+++ /dev/null
@@ -1,149 +0,0 @@
-#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/vendor/core/vendor/cmark-gfm/src/syntax_extension.h b/vendor/core/vendor/cmark-gfm/src/syntax_extension.h
deleted file mode 100644
index a5fe11e57..000000000
--- a/vendor/core/vendor/cmark-gfm/src/syntax_extension.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef CMARK_SYNTAX_EXTENSION_H
-#define CMARK_SYNTAX_EXTENSION_H
-
-#include "cmark-gfm.h"
-#include "cmark-gfm-extension_api.h"
-#include "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/vendor/core/vendor/cmark-gfm/src/utf8.c b/vendor/core/vendor/cmark-gfm/src/utf8.c
deleted file mode 100644
index c29bbf770..000000000
--- a/vendor/core/vendor/cmark-gfm/src/utf8.c
+++ /dev/null
@@ -1,317 +0,0 @@
-#include 
-#include 
-#include 
-
-#include "cmark_ctype.h"
-#include "utf8.h"
-
-static const int8_t utf8proc_utf8class[256] = {
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-    4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0};
-
-static void encode_unknown(cmark_strbuf *buf) {
-  static const uint8_t repl[] = {239, 191, 189};
-  cmark_strbuf_put(buf, repl, 3);
-}
-
-static int utf8proc_charlen(const uint8_t *str, bufsize_t str_len) {
-  int length, i;
-
-  if (!str_len)
-    return 0;
-
-  length = utf8proc_utf8class[str[0]];
-
-  if (!length)
-    return -1;
-
-  if (str_len >= 0 && (bufsize_t)length > str_len)
-    return -str_len;
-
-  for (i = 1; i < length; i++) {
-    if ((str[i] & 0xC0) != 0x80)
-      return -i;
-  }
-
-  return length;
-}
-
-// Validate a single UTF-8 character according to RFC 3629.
-static int utf8proc_valid(const uint8_t *str, bufsize_t str_len) {
-  int length = utf8proc_utf8class[str[0]];
-
-  if (!length)
-    return -1;
-
-  if ((bufsize_t)length > str_len)
-    return -str_len;
-
-  switch (length) {
-  case 2:
-    if ((str[1] & 0xC0) != 0x80)
-      return -1;
-    if (str[0] < 0xC2) {
-      // Overlong
-      return -length;
-    }
-    break;
-
-  case 3:
-    if ((str[1] & 0xC0) != 0x80)
-      return -1;
-    if ((str[2] & 0xC0) != 0x80)
-      return -2;
-    if (str[0] == 0xE0) {
-      if (str[1] < 0xA0) {
-        // Overlong
-        return -length;
-      }
-    } else if (str[0] == 0xED) {
-      if (str[1] >= 0xA0) {
-        // Surrogate
-        return -length;
-      }
-    }
-    break;
-
-  case 4:
-    if ((str[1] & 0xC0) != 0x80)
-      return -1;
-    if ((str[2] & 0xC0) != 0x80)
-      return -2;
-    if ((str[3] & 0xC0) != 0x80)
-      return -3;
-    if (str[0] == 0xF0) {
-      if (str[1] < 0x90) {
-        // Overlong
-        return -length;
-      }
-    } else if (str[0] >= 0xF4) {
-      if (str[0] > 0xF4 || str[1] >= 0x90) {
-        // Above 0x10FFFF
-        return -length;
-      }
-    }
-    break;
-  }
-
-  return length;
-}
-
-void cmark_utf8proc_check(cmark_strbuf *ob, const uint8_t *line,
-                          bufsize_t size) {
-  bufsize_t i = 0;
-
-  while (i < size) {
-    bufsize_t org = i;
-    int charlen = 0;
-
-    while (i < size) {
-      if (line[i] < 0x80 && line[i] != 0) {
-        i++;
-      } else if (line[i] >= 0x80) {
-        charlen = utf8proc_valid(line + i, size - i);
-        if (charlen < 0) {
-          charlen = -charlen;
-          break;
-        }
-        i += charlen;
-      } else if (line[i] == 0) {
-        // ASCII NUL is technically valid but rejected
-        // for security reasons.
-        charlen = 1;
-        break;
-      }
-    }
-
-    if (i > org) {
-      cmark_strbuf_put(ob, line + org, i - org);
-    }
-
-    if (i >= size) {
-      break;
-    } else {
-      // Invalid UTF-8
-      encode_unknown(ob);
-      i += charlen;
-    }
-  }
-}
-
-int cmark_utf8proc_iterate(const uint8_t *str, bufsize_t str_len,
-                           int32_t *dst) {
-  int length;
-  int32_t uc = -1;
-
-  *dst = -1;
-  length = utf8proc_charlen(str, str_len);
-  if (length < 0)
-    return -1;
-
-  switch (length) {
-  case 1:
-    uc = str[0];
-    break;
-  case 2:
-    uc = ((str[0] & 0x1F) << 6) + (str[1] & 0x3F);
-    if (uc < 0x80)
-      uc = -1;
-    break;
-  case 3:
-    uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) << 6) + (str[2] & 0x3F);
-    if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000))
-      uc = -1;
-    break;
-  case 4:
-    uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12) +
-         ((str[2] & 0x3F) << 6) + (str[3] & 0x3F);
-    if (uc < 0x10000 || uc >= 0x110000)
-      uc = -1;
-    break;
-  }
-
-  if (uc < 0)
-    return -1;
-
-  *dst = uc;
-  return length;
-}
-
-void cmark_utf8proc_encode_char(int32_t uc, cmark_strbuf *buf) {
-  uint8_t dst[4];
-  bufsize_t len = 0;
-
-  assert(uc >= 0);
-
-  if (uc < 0x80) {
-    dst[0] = (uint8_t)(uc);
-    len = 1;
-  } else if (uc < 0x800) {
-    dst[0] = (uint8_t)(0xC0 + (uc >> 6));
-    dst[1] = 0x80 + (uc & 0x3F);
-    len = 2;
-  } else if (uc == 0xFFFF) {
-    dst[0] = 0xFF;
-    len = 1;
-  } else if (uc == 0xFFFE) {
-    dst[0] = 0xFE;
-    len = 1;
-  } else if (uc < 0x10000) {
-    dst[0] = (uint8_t)(0xE0 + (uc >> 12));
-    dst[1] = 0x80 + ((uc >> 6) & 0x3F);
-    dst[2] = 0x80 + (uc & 0x3F);
-    len = 3;
-  } else if (uc < 0x110000) {
-    dst[0] = (uint8_t)(0xF0 + (uc >> 18));
-    dst[1] = 0x80 + ((uc >> 12) & 0x3F);
-    dst[2] = 0x80 + ((uc >> 6) & 0x3F);
-    dst[3] = 0x80 + (uc & 0x3F);
-    len = 4;
-  } else {
-    encode_unknown(buf);
-    return;
-  }
-
-  cmark_strbuf_put(buf, dst, len);
-}
-
-void cmark_utf8proc_case_fold(cmark_strbuf *dest, const uint8_t *str,
-                              bufsize_t len) {
-  int32_t c;
-
-#define bufpush(x) cmark_utf8proc_encode_char(x, dest)
-
-  while (len > 0) {
-    bufsize_t char_len = cmark_utf8proc_iterate(str, len, &c);
-
-    if (char_len >= 0) {
-#include "case_fold_switch.inc"
-    } else {
-      encode_unknown(dest);
-      char_len = -char_len;
-    }
-
-    str += char_len;
-    len -= char_len;
-  }
-}
-
-// matches anything in the Zs class, plus LF, CR, TAB, FF.
-int cmark_utf8proc_is_space(int32_t uc) {
-  return (uc == 9 || uc == 10 || uc == 12 || uc == 13 || uc == 32 ||
-          uc == 160 || uc == 5760 || (uc >= 8192 && uc <= 8202) || uc == 8239 ||
-          uc == 8287 || uc == 12288);
-}
-
-// matches anything in the P[cdefios] classes.
-int cmark_utf8proc_is_punctuation(int32_t uc) {
-  return (
-      (uc < 128 && cmark_ispunct((char)uc)) || uc == 161 || uc == 167 ||
-      uc == 171 || uc == 182 || uc == 183 || uc == 187 || uc == 191 ||
-      uc == 894 || uc == 903 || (uc >= 1370 && uc <= 1375) || uc == 1417 ||
-      uc == 1418 || uc == 1470 || uc == 1472 || uc == 1475 || uc == 1478 ||
-      uc == 1523 || uc == 1524 || uc == 1545 || uc == 1546 || uc == 1548 ||
-      uc == 1549 || uc == 1563 || uc == 1566 || uc == 1567 ||
-      (uc >= 1642 && uc <= 1645) || uc == 1748 || (uc >= 1792 && uc <= 1805) ||
-      (uc >= 2039 && uc <= 2041) || (uc >= 2096 && uc <= 2110) || uc == 2142 ||
-      uc == 2404 || uc == 2405 || uc == 2416 || uc == 2800 || uc == 3572 ||
-      uc == 3663 || uc == 3674 || uc == 3675 || (uc >= 3844 && uc <= 3858) ||
-      uc == 3860 || (uc >= 3898 && uc <= 3901) || uc == 3973 ||
-      (uc >= 4048 && uc <= 4052) || uc == 4057 || uc == 4058 ||
-      (uc >= 4170 && uc <= 4175) || uc == 4347 || (uc >= 4960 && uc <= 4968) ||
-      uc == 5120 || uc == 5741 || uc == 5742 || uc == 5787 || uc == 5788 ||
-      (uc >= 5867 && uc <= 5869) || uc == 5941 || uc == 5942 ||
-      (uc >= 6100 && uc <= 6102) || (uc >= 6104 && uc <= 6106) ||
-      (uc >= 6144 && uc <= 6154) || uc == 6468 || uc == 6469 || uc == 6686 ||
-      uc == 6687 || (uc >= 6816 && uc <= 6822) || (uc >= 6824 && uc <= 6829) ||
-      (uc >= 7002 && uc <= 7008) || (uc >= 7164 && uc <= 7167) ||
-      (uc >= 7227 && uc <= 7231) || uc == 7294 || uc == 7295 ||
-      (uc >= 7360 && uc <= 7367) || uc == 7379 || (uc >= 8208 && uc <= 8231) ||
-      (uc >= 8240 && uc <= 8259) || (uc >= 8261 && uc <= 8273) ||
-      (uc >= 8275 && uc <= 8286) || uc == 8317 || uc == 8318 || uc == 8333 ||
-      uc == 8334 || (uc >= 8968 && uc <= 8971) || uc == 9001 || uc == 9002 ||
-      (uc >= 10088 && uc <= 10101) || uc == 10181 || uc == 10182 ||
-      (uc >= 10214 && uc <= 10223) || (uc >= 10627 && uc <= 10648) ||
-      (uc >= 10712 && uc <= 10715) || uc == 10748 || uc == 10749 ||
-      (uc >= 11513 && uc <= 11516) || uc == 11518 || uc == 11519 ||
-      uc == 11632 || (uc >= 11776 && uc <= 11822) ||
-      (uc >= 11824 && uc <= 11842) || (uc >= 12289 && uc <= 12291) ||
-      (uc >= 12296 && uc <= 12305) || (uc >= 12308 && uc <= 12319) ||
-      uc == 12336 || uc == 12349 || uc == 12448 || uc == 12539 || uc == 42238 ||
-      uc == 42239 || (uc >= 42509 && uc <= 42511) || uc == 42611 ||
-      uc == 42622 || (uc >= 42738 && uc <= 42743) ||
-      (uc >= 43124 && uc <= 43127) || uc == 43214 || uc == 43215 ||
-      (uc >= 43256 && uc <= 43258) || uc == 43310 || uc == 43311 ||
-      uc == 43359 || (uc >= 43457 && uc <= 43469) || uc == 43486 ||
-      uc == 43487 || (uc >= 43612 && uc <= 43615) || uc == 43742 ||
-      uc == 43743 || uc == 43760 || uc == 43761 || uc == 44011 || uc == 64830 ||
-      uc == 64831 || (uc >= 65040 && uc <= 65049) ||
-      (uc >= 65072 && uc <= 65106) || (uc >= 65108 && uc <= 65121) ||
-      uc == 65123 || uc == 65128 || uc == 65130 || uc == 65131 ||
-      (uc >= 65281 && uc <= 65283) || (uc >= 65285 && uc <= 65290) ||
-      (uc >= 65292 && uc <= 65295) || uc == 65306 || uc == 65307 ||
-      uc == 65311 || uc == 65312 || (uc >= 65339 && uc <= 65341) ||
-      uc == 65343 || uc == 65371 || uc == 65373 ||
-      (uc >= 65375 && uc <= 65381) || (uc >= 65792 && uc <= 65794) ||
-      uc == 66463 || uc == 66512 || uc == 66927 || uc == 67671 || uc == 67871 ||
-      uc == 67903 || (uc >= 68176 && uc <= 68184) || uc == 68223 ||
-      (uc >= 68336 && uc <= 68342) || (uc >= 68409 && uc <= 68415) ||
-      (uc >= 68505 && uc <= 68508) || (uc >= 69703 && uc <= 69709) ||
-      uc == 69819 || uc == 69820 || (uc >= 69822 && uc <= 69825) ||
-      (uc >= 69952 && uc <= 69955) || uc == 70004 || uc == 70005 ||
-      (uc >= 70085 && uc <= 70088) || uc == 70093 ||
-      (uc >= 70200 && uc <= 70205) || uc == 70854 ||
-      (uc >= 71105 && uc <= 71113) || (uc >= 71233 && uc <= 71235) ||
-      (uc >= 74864 && uc <= 74868) || uc == 92782 || uc == 92783 ||
-      uc == 92917 || (uc >= 92983 && uc <= 92987) || uc == 92996 ||
-      uc == 113823);
-}
diff --git a/vendor/core/vendor/cmark-gfm/src/utf8.h b/vendor/core/vendor/cmark-gfm/src/utf8.h
deleted file mode 100644
index 04ec1611b..000000000
--- a/vendor/core/vendor/cmark-gfm/src/utf8.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef CMARK_UTF8_H
-#define CMARK_UTF8_H
-
-#include 
-#include "buffer.h"
-
-#ifdef __cplusplus
-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
-}
-#endif
-
-#endif
diff --git a/vendor/core/vendor/cmark-gfm/src/xml.c b/vendor/core/vendor/cmark-gfm/src/xml.c
deleted file mode 100644
index 5753e5ab9..000000000
--- a/vendor/core/vendor/cmark-gfm/src/xml.c
+++ /dev/null
@@ -1,182 +0,0 @@
-#include 
-#include 
-#include 
-#include 
-
-#include "config.h"
-#include "cmark-gfm.h"
-#include "node.h"
-#include "buffer.h"
-#include "houdini.h"
-#include "syntax_extension.h"
-
-#define BUFFER_SIZE 100
-#define MAX_INDENT 40
-
-// Functions to convert cmark_nodes to XML strings.
-
-static void escape_xml(cmark_strbuf *dest, const unsigned char *source,
-                       bufsize_t length) {
-  houdini_escape_html0(dest, source, length, 0);
-}
-
-struct render_state {
-  cmark_strbuf *xml;
-  int indent;
-};
-
-static CMARK_INLINE void indent(struct render_state *state) {
-  int i;
-  for (i = 0; i < state->indent && i < MAX_INDENT; i++) {
-    cmark_strbuf_putc(state->xml, ' ');
-  }
-}
-
-static int S_render_node(cmark_node *node, cmark_event_type ev_type,
-                         struct render_state *state, int options) {
-  cmark_strbuf *xml = state->xml;
-  bool literal = false;
-  cmark_delim_type delim;
-  bool entering = (ev_type == CMARK_EVENT_ENTER);
-  char buffer[BUFFER_SIZE];
-
-  if (entering) {
-    indent(state);
-    cmark_strbuf_putc(xml, '<');
-    cmark_strbuf_puts(xml, cmark_node_get_type_string(node));
-
-    if (options & CMARK_OPT_SOURCEPOS && node->start_line != 0) {
-      snprintf(buffer, BUFFER_SIZE, " sourcepos=\"%d:%d-%d:%d\"",
-               node->start_line, node->start_column, node->end_line,
-               node->end_column);
-      cmark_strbuf_puts(xml, buffer);
-    }
-
-    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) {
-    case CMARK_NODE_DOCUMENT:
-      cmark_strbuf_puts(xml, " xmlns=\"http://commonmark.org/xml/1.0\"");
-      break;
-    case CMARK_NODE_TEXT:
-    case CMARK_NODE_CODE:
-    case CMARK_NODE_HTML_BLOCK:
-    case CMARK_NODE_HTML_INLINE:
-      cmark_strbuf_puts(xml, " xml:space=\"preserve\">");
-      escape_xml(xml, node->as.literal.data, node->as.literal.len);
-      cmark_strbuf_puts(xml, "as.heading.level);
-      cmark_strbuf_puts(xml, buffer);
-      break;
-    case CMARK_NODE_CODE_BLOCK:
-      if (node->as.code.info.len > 0) {
-        cmark_strbuf_puts(xml, " info=\"");
-        escape_xml(xml, node->as.code.info.data, node->as.code.info.len);
-        cmark_strbuf_putc(xml, '"');
-      }
-      cmark_strbuf_puts(xml, " xml:space=\"preserve\">");
-      escape_xml(xml, node->as.code.literal.data, node->as.code.literal.len);
-      cmark_strbuf_puts(xml, "as.custom.on_enter.data,
-                 node->as.custom.on_enter.len);
-      cmark_strbuf_putc(xml, '"');
-      cmark_strbuf_puts(xml, " on_exit=\"");
-      escape_xml(xml, node->as.custom.on_exit.data,
-                 node->as.custom.on_exit.len);
-      cmark_strbuf_putc(xml, '"');
-      break;
-    case CMARK_NODE_LINK:
-    case CMARK_NODE_IMAGE:
-      cmark_strbuf_puts(xml, " destination=\"");
-      escape_xml(xml, node->as.link.url.data, node->as.link.url.len);
-      cmark_strbuf_putc(xml, '"');
-      cmark_strbuf_puts(xml, " title=\"");
-      escape_xml(xml, node->as.link.title.data, node->as.link.title.len);
-      cmark_strbuf_putc(xml, '"');
-      break;
-    default:
-      break;
-    }
-    if (node->first_child) {
-      state->indent += 2;
-    } else if (!literal) {
-      cmark_strbuf_puts(xml, " /");
-    }
-    cmark_strbuf_puts(xml, ">\n");
-
-  } else if (node->first_child) {
-    state->indent -= 2;
-    indent(state);
-    cmark_strbuf_puts(xml, "\n");
-  }
-
-  return 1;
-}
-
-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(mem);
-  cmark_event_type ev_type;
-  cmark_node *cur;
-  struct render_state state = {&xml, 0};
-
-  cmark_iter *iter = cmark_iter_new(root);
-
-  cmark_strbuf_puts(state.xml, "\n");
-  cmark_strbuf_puts(state.xml,
-                    "\n");
-  while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
-    cur = cmark_iter_get_node(iter);
-    S_render_node(cur, ev_type, &state, options);
-  }
-  result = (char *)cmark_strbuf_detach(&xml);
-
-  cmark_iter_free(iter);
-  return result;
-}
diff --git a/vendor/core/vendor/googlebenchmark/CMakeLists.txt b/vendor/core/vendor/googlebenchmark/CMakeLists.txt
deleted file mode 100644
index 216c1c921..000000000
--- a/vendor/core/vendor/googlebenchmark/CMakeLists.txt
+++ /dev/null
@@ -1,351 +0,0 @@
-# Require CMake 3.10. If available, use the policies up to CMake 3.22.
-cmake_minimum_required (VERSION 3.10...3.22)
-
-project (benchmark VERSION 1.8.5 LANGUAGES CXX)
-
-option(BENCHMARK_ENABLE_TESTING "Enable testing of the benchmark library." ON)
-option(BENCHMARK_ENABLE_EXCEPTIONS "Enable the use of exceptions in the benchmark library." ON)
-option(BENCHMARK_ENABLE_LTO "Enable link time optimisation of the benchmark library." OFF)
-option(BENCHMARK_USE_LIBCXX "Build and test using libc++ as the standard library." OFF)
-option(BENCHMARK_ENABLE_WERROR "Build Release candidates with -Werror." ON)
-option(BENCHMARK_FORCE_WERROR "Build Release candidates with -Werror regardless of compiler issues." OFF)
-
-if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "PGI")
-  # PGC++ maybe reporting false positives.
-  set(BENCHMARK_ENABLE_WERROR OFF)
-endif()
-if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "NVHPC")
-  set(BENCHMARK_ENABLE_WERROR OFF)
-endif()
-if(BENCHMARK_FORCE_WERROR)
-  set(BENCHMARK_ENABLE_WERROR ON)
-endif(BENCHMARK_FORCE_WERROR)
-
-if(NOT (MSVC OR CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"))
-  option(BENCHMARK_BUILD_32_BITS "Build a 32 bit version of the library." OFF)
-else()
-  set(BENCHMARK_BUILD_32_BITS OFF CACHE BOOL "Build a 32 bit version of the library - unsupported when using MSVC)" FORCE)
-endif()
-option(BENCHMARK_ENABLE_INSTALL "Enable installation of benchmark. (Projects embedding benchmark may want to turn this OFF.)" ON)
-option(BENCHMARK_ENABLE_DOXYGEN "Build documentation with Doxygen." OFF)
-option(BENCHMARK_INSTALL_DOCS "Enable installation of documentation." ON)
-
-# Allow unmet dependencies to be met using CMake's ExternalProject mechanics, which
-# may require downloading the source code.
-option(BENCHMARK_DOWNLOAD_DEPENDENCIES "Allow the downloading and in-tree building of unmet dependencies" OFF)
-
-# This option can be used to disable building and running unit tests which depend on gtest
-# in cases where it is not possible to build or find a valid version of gtest.
-option(BENCHMARK_ENABLE_GTEST_TESTS "Enable building the unit tests which depend on gtest" ON)
-option(BENCHMARK_USE_BUNDLED_GTEST "Use bundled GoogleTest. If disabled, the find_package(GTest) will be used." ON)
-
-option(BENCHMARK_ENABLE_LIBPFM "Enable performance counters provided by libpfm" OFF)
-
-# Export only public symbols
-set(CMAKE_CXX_VISIBILITY_PRESET hidden)
-set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
-
-if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
-    # As of CMake 3.18, CMAKE_SYSTEM_PROCESSOR is not set properly for MSVC and
-    # cross-compilation (e.g. Host=x86_64, target=aarch64) requires using the
-    # undocumented, but working variable.
-    # See https://gitlab.kitware.com/cmake/cmake/-/issues/15170
-    set(CMAKE_SYSTEM_PROCESSOR ${MSVC_CXX_ARCHITECTURE_ID})
-    if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM")
-      set(CMAKE_CROSSCOMPILING TRUE)
-    endif()
-endif()
-
-set(ENABLE_ASSEMBLY_TESTS_DEFAULT OFF)
-function(should_enable_assembly_tests)
-  if(CMAKE_BUILD_TYPE)
-    string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER)
-    if (${CMAKE_BUILD_TYPE_LOWER} MATCHES "coverage")
-      # FIXME: The --coverage flag needs to be removed when building assembly
-      # tests for this to work.
-      return()
-    endif()
-  endif()
-  if (MSVC OR CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
-    return()
-  elseif(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
-    return()
-  elseif(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
-    # FIXME: Make these work on 32 bit builds
-    return()
-  elseif(BENCHMARK_BUILD_32_BITS)
-     # FIXME: Make these work on 32 bit builds
-    return()
-  endif()
-  find_program(LLVM_FILECHECK_EXE FileCheck)
-  if (LLVM_FILECHECK_EXE)
-    set(LLVM_FILECHECK_EXE "${LLVM_FILECHECK_EXE}" CACHE PATH "llvm filecheck" FORCE)
-    message(STATUS "LLVM FileCheck Found: ${LLVM_FILECHECK_EXE}")
-  else()
-    message(STATUS "Failed to find LLVM FileCheck")
-    return()
-  endif()
-  set(ENABLE_ASSEMBLY_TESTS_DEFAULT ON PARENT_SCOPE)
-endfunction()
-should_enable_assembly_tests()
-
-# This option disables the building and running of the assembly verification tests
-option(BENCHMARK_ENABLE_ASSEMBLY_TESTS "Enable building and running the assembly tests"
-    ${ENABLE_ASSEMBLY_TESTS_DEFAULT})
-
-# Make sure we can import out CMake functions
-list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
-list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
-
-
-# Read the git tags to determine the project version
-include(GetGitVersion)
-get_git_version(GIT_VERSION)
-
-# If no git version can be determined, use the version
-# from the project() command
-if ("${GIT_VERSION}" STREQUAL "v0.0.0")
-  set(VERSION "v${benchmark_VERSION}")
-else()
-  set(VERSION "${GIT_VERSION}")
-endif()
-
-# Normalize version: drop "v" prefix, replace first "-" with ".",
-# drop everything after second "-" (including said "-").
-string(STRIP ${VERSION} VERSION)
-if(VERSION MATCHES v[^-]*-)
-   string(REGEX REPLACE "v([^-]*)-([0-9]+)-.*" "\\1.\\2"  NORMALIZED_VERSION ${VERSION})
-else()
-   string(REGEX REPLACE "v(.*)" "\\1" NORMALIZED_VERSION ${VERSION})
-endif()
-
-# Tell the user what versions we are using
-message(STATUS "Google Benchmark version: ${VERSION}, normalized to ${NORMALIZED_VERSION}")
-
-# The version of the libraries
-set(GENERIC_LIB_VERSION ${NORMALIZED_VERSION})
-string(SUBSTRING ${NORMALIZED_VERSION} 0 1 GENERIC_LIB_SOVERSION)
-
-# Import our CMake modules
-include(AddCXXCompilerFlag)
-include(CheckCXXCompilerFlag)
-include(CheckLibraryExists)
-include(CXXFeatureCheck)
-
-check_library_exists(rt shm_open "" HAVE_LIB_RT)
-
-if (BENCHMARK_BUILD_32_BITS)
-  add_required_cxx_compiler_flag(-m32)
-endif()
-
-set(BENCHMARK_CXX_STANDARD 14)
-
-set(CMAKE_CXX_STANDARD ${BENCHMARK_CXX_STANDARD})
-set(CMAKE_CXX_STANDARD_REQUIRED YES)
-set(CMAKE_CXX_EXTENSIONS OFF)
-
-if (MSVC)
-  # Turn compiler warnings up to 11
-  string(REGEX REPLACE "[-/]W[1-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
-  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
-
-  if (NOT BENCHMARK_ENABLE_EXCEPTIONS)
-    add_cxx_compiler_flag(-EHs-)
-    add_cxx_compiler_flag(-EHa-)
-    add_definitions(-D_HAS_EXCEPTIONS=0)
-  endif()
-  # Link time optimisation
-  if (BENCHMARK_ENABLE_LTO)
-    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
-    set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /LTCG")
-    set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
-    set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
-
-    set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /GL")
-    string(REGEX REPLACE "[-/]INCREMENTAL" "/INCREMENTAL:NO" CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO}")
-    set(CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO} /LTCG")
-    string(REGEX REPLACE "[-/]INCREMENTAL" "/INCREMENTAL:NO" CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}")
-    set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /LTCG")
-    string(REGEX REPLACE "[-/]INCREMENTAL" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
-    set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /LTCG")
-
-    set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /GL")
-    set(CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL "${CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL} /LTCG")
-    set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL} /LTCG")
-    set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} /LTCG")
-  endif()
-else()
-  # Turn on Large-file Support
-  add_definitions(-D_FILE_OFFSET_BITS=64)
-  add_definitions(-D_LARGEFILE64_SOURCE)
-  add_definitions(-D_LARGEFILE_SOURCE)
-  # Turn compiler warnings up to 11
-  add_cxx_compiler_flag(-Wall)
-  add_cxx_compiler_flag(-Wextra)
-  add_cxx_compiler_flag(-Wshadow)
-  add_cxx_compiler_flag(-Wfloat-equal)
-  add_cxx_compiler_flag(-Wold-style-cast)
-  add_cxx_compiler_flag(-Wconversion)
-  if(BENCHMARK_ENABLE_WERROR)
-      add_cxx_compiler_flag(-Werror)
-  endif()
-  if (NOT BENCHMARK_ENABLE_TESTING)
-    # Disable warning when compiling tests as gtest does not use 'override'.
-    add_cxx_compiler_flag(-Wsuggest-override)
-  endif()
-  add_cxx_compiler_flag(-pedantic)
-  add_cxx_compiler_flag(-pedantic-errors)
-  add_cxx_compiler_flag(-Wshorten-64-to-32)
-  add_cxx_compiler_flag(-fstrict-aliasing)
-  # Disable warnings regarding deprecated parts of the library while building
-  # and testing those parts of the library.
-  add_cxx_compiler_flag(-Wno-deprecated-declarations)
-  if (CMAKE_CXX_COMPILER_ID STREQUAL "Intel" OR CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
-    # Intel silently ignores '-Wno-deprecated-declarations',
-    # warning no. 1786 must be explicitly disabled.
-    # See #631 for rationale.
-    add_cxx_compiler_flag(-wd1786)
-    add_cxx_compiler_flag(-fno-finite-math-only)
-  endif()
-  # Disable deprecation warnings for release builds (when -Werror is enabled).
-  if(BENCHMARK_ENABLE_WERROR)
-      add_cxx_compiler_flag(-Wno-deprecated)
-  endif()
-  if (NOT BENCHMARK_ENABLE_EXCEPTIONS)
-    add_cxx_compiler_flag(-fno-exceptions)
-  endif()
-
-  if (HAVE_CXX_FLAG_FSTRICT_ALIASING)
-    if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Intel" AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM") #ICC17u2: Many false positives for Wstrict-aliasing
-      add_cxx_compiler_flag(-Wstrict-aliasing)
-    endif()
-  endif()
-  # ICC17u2: overloaded virtual function "benchmark::Fixture::SetUp" is only partially overridden
-  # (because of deprecated overload)
-  add_cxx_compiler_flag(-wd654)
-  add_cxx_compiler_flag(-Wthread-safety)
-  if (HAVE_CXX_FLAG_WTHREAD_SAFETY)
-    cxx_feature_check(THREAD_SAFETY_ATTRIBUTES "-DINCLUDE_DIRECTORIES=${PROJECT_SOURCE_DIR}/include")
-  endif()
-
-  # On most UNIX like platforms g++ and clang++ define _GNU_SOURCE as a
-  # predefined macro, which turns on all of the wonderful libc extensions.
-  # However g++ doesn't do this in Cygwin so we have to define it ourselves
-  # since we depend on GNU/POSIX/BSD extensions.
-  if (CYGWIN)
-    add_definitions(-D_GNU_SOURCE=1)
-  endif()
-
-  if (QNXNTO)
-    add_definitions(-D_QNX_SOURCE)
-  endif()
-
-  # Link time optimisation
-  if (BENCHMARK_ENABLE_LTO)
-    add_cxx_compiler_flag(-flto)
-    add_cxx_compiler_flag(-Wno-lto-type-mismatch)
-    if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
-      find_program(GCC_AR gcc-ar)
-      if (GCC_AR)
-        set(CMAKE_AR ${GCC_AR})
-      endif()
-      find_program(GCC_RANLIB gcc-ranlib)
-      if (GCC_RANLIB)
-        set(CMAKE_RANLIB ${GCC_RANLIB})
-      endif()
-    elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
-      include(llvm-toolchain)
-    endif()
-  endif()
-
-  # Coverage build type
-  set(BENCHMARK_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG}"
-    CACHE STRING "Flags used by the C++ compiler during coverage builds."
-    FORCE)
-  set(BENCHMARK_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_DEBUG}"
-    CACHE STRING "Flags used for linking binaries during coverage builds."
-    FORCE)
-  set(BENCHMARK_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}"
-    CACHE STRING "Flags used by the shared libraries linker during coverage builds."
-    FORCE)
-  mark_as_advanced(
-    BENCHMARK_CXX_FLAGS_COVERAGE
-    BENCHMARK_EXE_LINKER_FLAGS_COVERAGE
-    BENCHMARK_SHARED_LINKER_FLAGS_COVERAGE)
-  set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
-    "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage.")
-  add_cxx_compiler_flag(--coverage COVERAGE)
-endif()
-
-if (BENCHMARK_USE_LIBCXX)
-  if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
-    add_cxx_compiler_flag(-stdlib=libc++)
-  elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
-          "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel" OR
-          "${CMAKE_CXX_COMPILER_ID}" STREQUAL "IntelLLVM")
-    add_cxx_compiler_flag(-nostdinc++)
-    message(WARNING "libc++ header path must be manually specified using CMAKE_CXX_FLAGS")
-    # Adding -nodefaultlibs directly to CMAKE__LINKER_FLAGS will break
-    # configuration checks such as 'find_package(Threads)'
-    list(APPEND BENCHMARK_CXX_LINKER_FLAGS -nodefaultlibs)
-    # -lc++ cannot be added directly to CMAKE__LINKER_FLAGS because
-    # linker flags appear before all linker inputs and -lc++ must appear after.
-    list(APPEND BENCHMARK_CXX_LIBRARIES c++)
-  else()
-    message(FATAL_ERROR "-DBENCHMARK_USE_LIBCXX:BOOL=ON is not supported for compiler")
-  endif()
-endif(BENCHMARK_USE_LIBCXX)
-
-set(EXTRA_CXX_FLAGS "")
-if (WIN32 AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
-  # Clang on Windows fails to compile the regex feature check under C++11
-  set(EXTRA_CXX_FLAGS "-DCMAKE_CXX_STANDARD=14")
-endif()
-
-# C++ feature checks
-# Determine the correct regular expression engine to use
-cxx_feature_check(STD_REGEX ${EXTRA_CXX_FLAGS})
-cxx_feature_check(GNU_POSIX_REGEX ${EXTRA_CXX_FLAGS})
-cxx_feature_check(POSIX_REGEX ${EXTRA_CXX_FLAGS})
-if(NOT HAVE_STD_REGEX AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX)
-  message(FATAL_ERROR "Failed to determine the source files for the regular expression backend")
-endif()
-if (NOT BENCHMARK_ENABLE_EXCEPTIONS AND HAVE_STD_REGEX
-        AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX)
-  message(WARNING "Using std::regex with exceptions disabled is not fully supported")
-endif()
-
-cxx_feature_check(STEADY_CLOCK)
-# Ensure we have pthreads
-set(THREADS_PREFER_PTHREAD_FLAG ON)
-find_package(Threads REQUIRED)
-cxx_feature_check(PTHREAD_AFFINITY)
-
-if (BENCHMARK_ENABLE_LIBPFM)
-  find_package(PFM REQUIRED)
-endif()
-
-# Set up directories
-include_directories(${PROJECT_SOURCE_DIR}/include)
-
-# Build the targets
-add_subdirectory(src)
-
-if (BENCHMARK_ENABLE_TESTING)
-  enable_testing()
-  if (BENCHMARK_ENABLE_GTEST_TESTS AND
-      NOT (TARGET gtest AND TARGET gtest_main AND
-           TARGET gmock AND TARGET gmock_main))
-    if (BENCHMARK_USE_BUNDLED_GTEST)
-      include(GoogleTest)
-    else()
-      find_package(GTest CONFIG REQUIRED)
-      add_library(gtest ALIAS GTest::gtest)
-      add_library(gtest_main ALIAS GTest::gtest_main)
-      add_library(gmock ALIAS GTest::gmock)
-      add_library(gmock_main ALIAS GTest::gmock_main)
-    endif()
-  endif()
-  add_subdirectory(test)
-endif()
diff --git a/vendor/core/vendor/googlebenchmark/LICENSE b/vendor/core/vendor/googlebenchmark/LICENSE
deleted file mode 100644
index d64569567..000000000
--- a/vendor/core/vendor/googlebenchmark/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/vendor/core/vendor/googlebenchmark/cmake/AddCXXCompilerFlag.cmake b/vendor/core/vendor/googlebenchmark/cmake/AddCXXCompilerFlag.cmake
deleted file mode 100644
index 858589e97..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/AddCXXCompilerFlag.cmake
+++ /dev/null
@@ -1,78 +0,0 @@
-# - Adds a compiler flag if it is supported by the compiler
-#
-# This function checks that the supplied compiler flag is supported and then
-# adds it to the corresponding compiler flags
-#
-#  add_cxx_compiler_flag( [])
-#
-# - Example
-#
-# include(AddCXXCompilerFlag)
-# add_cxx_compiler_flag(-Wall)
-# add_cxx_compiler_flag(-no-strict-aliasing RELEASE)
-# Requires CMake 2.6+
-
-if(__add_cxx_compiler_flag)
-  return()
-endif()
-set(__add_cxx_compiler_flag INCLUDED)
-
-include(CheckCXXCompilerFlag)
-
-function(mangle_compiler_flag FLAG OUTPUT)
-  string(TOUPPER "HAVE_CXX_FLAG_${FLAG}" SANITIZED_FLAG)
-  string(REPLACE "+" "X" SANITIZED_FLAG ${SANITIZED_FLAG})
-  string(REGEX REPLACE "[^A-Za-z_0-9]" "_" SANITIZED_FLAG ${SANITIZED_FLAG})
-  string(REGEX REPLACE "_+" "_" SANITIZED_FLAG ${SANITIZED_FLAG})
-  set(${OUTPUT} "${SANITIZED_FLAG}" PARENT_SCOPE)
-endfunction(mangle_compiler_flag)
-
-function(add_cxx_compiler_flag FLAG)
-  mangle_compiler_flag("${FLAG}" MANGLED_FLAG)
-  set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
-  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}")
-  check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG})
-  set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
-  if(${MANGLED_FLAG})
-    if(ARGC GREATER 1)
-      set(VARIANT ${ARGV1})
-      string(TOUPPER "_${VARIANT}" VARIANT)
-    else()
-      set(VARIANT "")
-    endif()
-    set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${BENCHMARK_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE)
-  endif()
-endfunction()
-
-function(add_required_cxx_compiler_flag FLAG)
-  mangle_compiler_flag("${FLAG}" MANGLED_FLAG)
-  set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
-  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}")
-  check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG})
-  set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
-  if(${MANGLED_FLAG})
-    if(ARGC GREATER 1)
-      set(VARIANT ${ARGV1})
-      string(TOUPPER "_${VARIANT}" VARIANT)
-    else()
-      set(VARIANT "")
-    endif()
-    set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE)
-    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE)
-    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE)
-    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE)
-    set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}" PARENT_SCOPE)
-  else()
-    message(FATAL_ERROR "Required flag '${FLAG}' is not supported by the compiler")
-  endif()
-endfunction()
-
-function(check_cxx_warning_flag FLAG)
-  mangle_compiler_flag("${FLAG}" MANGLED_FLAG)
-  set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
-  # Add -Werror to ensure the compiler generates an error if the warning flag
-  # doesn't exist.
-  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror ${FLAG}")
-  check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG})
-  set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
-endfunction()
diff --git a/vendor/core/vendor/googlebenchmark/cmake/CXXFeatureCheck.cmake b/vendor/core/vendor/googlebenchmark/cmake/CXXFeatureCheck.cmake
deleted file mode 100644
index e51482659..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/CXXFeatureCheck.cmake
+++ /dev/null
@@ -1,82 +0,0 @@
-# - Compile and run code to check for C++ features
-#
-# This functions compiles a source file under the `cmake` folder
-# and adds the corresponding `HAVE_[FILENAME]` flag to the CMake
-# environment
-#
-#  cxx_feature_check( [])
-#
-# - Example
-#
-# include(CXXFeatureCheck)
-# cxx_feature_check(STD_REGEX)
-# Requires CMake 2.8.12+
-
-if(__cxx_feature_check)
-  return()
-endif()
-set(__cxx_feature_check INCLUDED)
-
-option(CXXFEATURECHECK_DEBUG OFF)
-
-function(cxx_feature_check FILE)
-  string(TOLOWER ${FILE} FILE)
-  string(TOUPPER ${FILE} VAR)
-  string(TOUPPER "HAVE_${VAR}" FEATURE)
-  if (DEFINED HAVE_${VAR})
-    set(HAVE_${VAR} 1 PARENT_SCOPE)
-    add_definitions(-DHAVE_${VAR})
-    return()
-  endif()
-
-  set(FEATURE_CHECK_CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
-  if (ARGC GREATER 1)
-    message(STATUS "Enabling additional flags: ${ARGV1}")
-    list(APPEND FEATURE_CHECK_CMAKE_FLAGS ${ARGV1})
-  endif()
-
-  if (NOT DEFINED COMPILE_${FEATURE})
-    if(CMAKE_CROSSCOMPILING)
-      message(STATUS "Cross-compiling to test ${FEATURE}")
-      try_compile(COMPILE_${FEATURE}
-              ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp
-              CXX_STANDARD 11
-              CXX_STANDARD_REQUIRED ON
-              CMAKE_FLAGS ${FEATURE_CHECK_CMAKE_FLAGS}
-              LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES}
-              OUTPUT_VARIABLE COMPILE_OUTPUT_VAR)
-      if(COMPILE_${FEATURE})
-        message(WARNING
-              "If you see build failures due to cross compilation, try setting HAVE_${VAR} to 0")
-        set(RUN_${FEATURE} 0 CACHE INTERNAL "")
-      else()
-        set(RUN_${FEATURE} 1 CACHE INTERNAL "")
-      endif()
-    else()
-      message(STATUS "Compiling and running to test ${FEATURE}")
-      try_run(RUN_${FEATURE} COMPILE_${FEATURE}
-              ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp
-              CXX_STANDARD 11
-              CXX_STANDARD_REQUIRED ON
-              CMAKE_FLAGS ${FEATURE_CHECK_CMAKE_FLAGS}
-              LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES}
-              COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT_VAR)
-    endif()
-  endif()
-
-  if(RUN_${FEATURE} EQUAL 0)
-    message(STATUS "Performing Test ${FEATURE} -- success")
-    set(HAVE_${VAR} 1 PARENT_SCOPE)
-    add_definitions(-DHAVE_${VAR})
-  else()
-    if(NOT COMPILE_${FEATURE})
-      if(CXXFEATURECHECK_DEBUG)
-        message(STATUS "Performing Test ${FEATURE} -- failed to compile: ${COMPILE_OUTPUT_VAR}")
-      else()
-        message(STATUS "Performing Test ${FEATURE} -- failed to compile")
-      endif()
-    else()
-      message(STATUS "Performing Test ${FEATURE} -- compiled but failed to run")
-    endif()
-  endif()
-endfunction()
diff --git a/vendor/core/vendor/googlebenchmark/cmake/Config.cmake.in b/vendor/core/vendor/googlebenchmark/cmake/Config.cmake.in
deleted file mode 100644
index 3659cfa2a..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/Config.cmake.in
+++ /dev/null
@@ -1,11 +0,0 @@
-@PACKAGE_INIT@
-
-include (CMakeFindDependencyMacro)
-
-find_dependency (Threads)
-
-if (@BENCHMARK_ENABLE_LIBPFM@)
-    find_dependency (PFM)
-endif()
-
-include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
diff --git a/vendor/core/vendor/googlebenchmark/cmake/GetGitVersion.cmake b/vendor/core/vendor/googlebenchmark/cmake/GetGitVersion.cmake
deleted file mode 100644
index b0210103b..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/GetGitVersion.cmake
+++ /dev/null
@@ -1,36 +0,0 @@
-# - Returns a version string from Git tags
-#
-# This function inspects the annotated git tags for the project and returns a string
-# into a CMake variable
-#
-#  get_git_version()
-#
-# - Example
-#
-# include(GetGitVersion)
-# get_git_version(GIT_VERSION)
-#
-# Requires CMake 2.8.11+
-find_package(Git)
-
-if(__get_git_version)
-  return()
-endif()
-set(__get_git_version INCLUDED)
-
-function(get_git_version var)
-  if(GIT_EXECUTABLE)
-      execute_process(COMMAND ${GIT_EXECUTABLE} describe --tags --match "v[0-9]*.[0-9]*.[0-9]*" --abbrev=8 --dirty
-          WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-          RESULT_VARIABLE status
-          OUTPUT_VARIABLE GIT_VERSION
-          ERROR_QUIET)
-      if(status)
-          set(GIT_VERSION "v0.0.0")
-      endif()
-  else()
-      set(GIT_VERSION "v0.0.0")
-  endif()
-
-  set(${var} ${GIT_VERSION} PARENT_SCOPE)
-endfunction()
diff --git a/vendor/core/vendor/googlebenchmark/cmake/GoogleTest.cmake b/vendor/core/vendor/googlebenchmark/cmake/GoogleTest.cmake
deleted file mode 100644
index e66e9d1a2..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/GoogleTest.cmake
+++ /dev/null
@@ -1,58 +0,0 @@
-# Download and unpack googletest at configure time
-set(GOOGLETEST_PREFIX "${benchmark_BINARY_DIR}/third_party/googletest")
-configure_file(${benchmark_SOURCE_DIR}/cmake/GoogleTest.cmake.in ${GOOGLETEST_PREFIX}/CMakeLists.txt @ONLY)
-
-set(GOOGLETEST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/googletest" CACHE PATH "") # Mind the quotes
-execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}"
-  -DALLOW_DOWNLOADING_GOOGLETEST=${BENCHMARK_DOWNLOAD_DEPENDENCIES} -DGOOGLETEST_PATH:PATH=${GOOGLETEST_PATH} .
-  RESULT_VARIABLE result
-  WORKING_DIRECTORY ${GOOGLETEST_PREFIX}
-)
-
-if(result)
-  message(FATAL_ERROR "CMake step for googletest failed: ${result}")
-endif()
-
-execute_process(
-  COMMAND ${CMAKE_COMMAND} --build .
-  RESULT_VARIABLE result
-  WORKING_DIRECTORY ${GOOGLETEST_PREFIX}
-)
-
-if(result)
-  message(FATAL_ERROR "Build step for googletest failed: ${result}")
-endif()
-
-# Prevent overriding the parent project's compiler/linker
-# settings on Windows
-set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
-
-include(${GOOGLETEST_PREFIX}/googletest-paths.cmake)
-
-# Add googletest directly to our build. This defines
-# the gtest and gtest_main targets.
-add_subdirectory(${GOOGLETEST_SOURCE_DIR}
-                 ${GOOGLETEST_BINARY_DIR}
-                 EXCLUDE_FROM_ALL)
-
-# googletest doesn't seem to want to stay build warning clean so let's not hurt ourselves.
-if (MSVC)
-  target_compile_options(gtest PRIVATE "/wd4244" "/wd4722")
-  target_compile_options(gtest_main PRIVATE "/wd4244" "/wd4722")
-  target_compile_options(gmock PRIVATE "/wd4244" "/wd4722")
-  target_compile_options(gmock_main PRIVATE "/wd4244" "/wd4722")
-else()
-  target_compile_options(gtest PRIVATE "-w")
-  target_compile_options(gtest_main PRIVATE "-w")
-  target_compile_options(gmock PRIVATE "-w")
-  target_compile_options(gmock_main PRIVATE "-w")
-endif()
-
-if(NOT DEFINED GTEST_COMPILE_COMMANDS)
-    set(GTEST_COMPILE_COMMANDS ON)
-endif()
-
-set_target_properties(gtest PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $ EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
-set_target_properties(gtest_main PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $ EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
-set_target_properties(gmock PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $ EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
-set_target_properties(gmock_main PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $ EXPORT_COMPILE_COMMANDS ${GTEST_COMPILE_COMMANDS})
diff --git a/vendor/core/vendor/googlebenchmark/cmake/GoogleTest.cmake.in b/vendor/core/vendor/googlebenchmark/cmake/GoogleTest.cmake.in
deleted file mode 100644
index ce653ac37..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/GoogleTest.cmake.in
+++ /dev/null
@@ -1,59 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-
-project(googletest-download NONE)
-
-# Enable ExternalProject CMake module
-include(ExternalProject)
-
-option(ALLOW_DOWNLOADING_GOOGLETEST "If googletest src tree is not found in location specified by GOOGLETEST_PATH, do fetch the archive from internet" OFF)
-set(GOOGLETEST_PATH "/usr/src/googletest" CACHE PATH
-                    "Path to the googletest root tree. Should contain googletest and googlemock subdirs. And CMakeLists.txt in root, and in both of these subdirs")
-
-# Download and install GoogleTest
-
-message(STATUS "Looking for Google Test sources")
-message(STATUS "Looking for Google Test sources in ${GOOGLETEST_PATH}")
-if(EXISTS "${GOOGLETEST_PATH}"            AND IS_DIRECTORY "${GOOGLETEST_PATH}"            AND EXISTS "${GOOGLETEST_PATH}/CMakeLists.txt" AND
-   EXISTS "${GOOGLETEST_PATH}/googletest" AND IS_DIRECTORY "${GOOGLETEST_PATH}/googletest" AND EXISTS "${GOOGLETEST_PATH}/googletest/CMakeLists.txt" AND
-   EXISTS "${GOOGLETEST_PATH}/googlemock" AND IS_DIRECTORY "${GOOGLETEST_PATH}/googlemock" AND EXISTS "${GOOGLETEST_PATH}/googlemock/CMakeLists.txt")
-  message(STATUS "Found Google Test in ${GOOGLETEST_PATH}")
-
-  ExternalProject_Add(
-    googletest
-    PREFIX            "${CMAKE_BINARY_DIR}"
-    DOWNLOAD_DIR      "${CMAKE_BINARY_DIR}/download"
-    SOURCE_DIR        "${GOOGLETEST_PATH}" # use existing src dir.
-    BINARY_DIR        "${CMAKE_BINARY_DIR}/build"
-    CONFIGURE_COMMAND ""
-    BUILD_COMMAND     ""
-    INSTALL_COMMAND   ""
-    TEST_COMMAND      ""
-  )
-else()
-  if(NOT ALLOW_DOWNLOADING_GOOGLETEST)
-    message(SEND_ERROR "Did not find Google Test sources! Either pass correct path in GOOGLETEST_PATH, or enable BENCHMARK_DOWNLOAD_DEPENDENCIES, or disable BENCHMARK_USE_BUNDLED_GTEST, or disable BENCHMARK_ENABLE_GTEST_TESTS / BENCHMARK_ENABLE_TESTING.")
-    return()
-  else()
-    message(WARNING "Did not find Google Test sources! Fetching from web...")
-    ExternalProject_Add(
-      googletest
-      GIT_REPOSITORY    https://github.com/google/googletest.git
-      GIT_TAG           "release-1.11.0"
-      PREFIX            "${CMAKE_BINARY_DIR}"
-      STAMP_DIR         "${CMAKE_BINARY_DIR}/stamp"
-      DOWNLOAD_DIR      "${CMAKE_BINARY_DIR}/download"
-      SOURCE_DIR        "${CMAKE_BINARY_DIR}/src"
-      BINARY_DIR        "${CMAKE_BINARY_DIR}/build"
-      CONFIGURE_COMMAND ""
-      BUILD_COMMAND     ""
-      INSTALL_COMMAND   ""
-      TEST_COMMAND      ""
-    )
-  endif()
-endif()
-
-ExternalProject_Get_Property(googletest SOURCE_DIR BINARY_DIR)
-file(WRITE googletest-paths.cmake
-"set(GOOGLETEST_SOURCE_DIR \"${SOURCE_DIR}\")
-set(GOOGLETEST_BINARY_DIR \"${BINARY_DIR}\")
-")
diff --git a/vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMAr.cmake b/vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMAr.cmake
deleted file mode 100644
index 23469813c..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMAr.cmake
+++ /dev/null
@@ -1,16 +0,0 @@
-include(FeatureSummary)
-
-find_program(LLVMAR_EXECUTABLE
-  NAMES llvm-ar
-  DOC "The llvm-ar executable"
-  )
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(LLVMAr
-  DEFAULT_MSG
-  LLVMAR_EXECUTABLE)
-
-SET_PACKAGE_PROPERTIES(LLVMAr PROPERTIES
-  URL https://llvm.org/docs/CommandGuide/llvm-ar.html
-  DESCRIPTION "create, modify, and extract from archives"
-)
diff --git a/vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMNm.cmake b/vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMNm.cmake
deleted file mode 100644
index e56430a04..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMNm.cmake
+++ /dev/null
@@ -1,16 +0,0 @@
-include(FeatureSummary)
-
-find_program(LLVMNM_EXECUTABLE
-  NAMES llvm-nm
-  DOC "The llvm-nm executable"
-  )
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(LLVMNm
-  DEFAULT_MSG
-  LLVMNM_EXECUTABLE)
-
-SET_PACKAGE_PROPERTIES(LLVMNm PROPERTIES
-  URL https://llvm.org/docs/CommandGuide/llvm-nm.html
-  DESCRIPTION "list LLVM bitcode and object file’s symbol table"
-)
diff --git a/vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMRanLib.cmake b/vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMRanLib.cmake
deleted file mode 100644
index 7b53e1a79..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/Modules/FindLLVMRanLib.cmake
+++ /dev/null
@@ -1,15 +0,0 @@
-include(FeatureSummary)
-
-find_program(LLVMRANLIB_EXECUTABLE
-  NAMES llvm-ranlib
-  DOC "The llvm-ranlib executable"
-  )
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(LLVMRanLib
-  DEFAULT_MSG
-  LLVMRANLIB_EXECUTABLE)
-
-SET_PACKAGE_PROPERTIES(LLVMRanLib PROPERTIES
-  DESCRIPTION "generate index for LLVM archive"
-)
diff --git a/vendor/core/vendor/googlebenchmark/cmake/Modules/FindPFM.cmake b/vendor/core/vendor/googlebenchmark/cmake/Modules/FindPFM.cmake
deleted file mode 100644
index 4c1ce938f..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/Modules/FindPFM.cmake
+++ /dev/null
@@ -1,28 +0,0 @@
-# If successful, the following variables will be defined:
-# PFM_FOUND.
-# PFM_LIBRARIES
-# PFM_INCLUDE_DIRS
-# the following target will be defined:
-# PFM::libpfm
-
-include(FeatureSummary)
-include(FindPackageHandleStandardArgs)
-
-set_package_properties(PFM PROPERTIES
-                       URL http://perfmon2.sourceforge.net/
-                       DESCRIPTION "A helper library to develop monitoring tools"
-                       PURPOSE "Used to program specific performance monitoring events")
-
-find_library(PFM_LIBRARY NAMES pfm)
-find_path(PFM_INCLUDE_DIR NAMES perfmon/pfmlib.h)
-
-find_package_handle_standard_args(PFM REQUIRED_VARS PFM_LIBRARY PFM_INCLUDE_DIR)
-
-if (PFM_FOUND AND NOT TARGET PFM::libpfm)
-    add_library(PFM::libpfm UNKNOWN IMPORTED)
-    set_target_properties(PFM::libpfm PROPERTIES
-        IMPORTED_LOCATION "${PFM_LIBRARY}"
-        INTERFACE_INCLUDE_DIRECTORIES "${PFM_INCLUDE_DIR}")
-endif()
-
-mark_as_advanced(PFM_LIBRARY PFM_INCLUDE_DIR)
diff --git a/vendor/core/vendor/googlebenchmark/cmake/benchmark.pc.in b/vendor/core/vendor/googlebenchmark/cmake/benchmark.pc.in
deleted file mode 100644
index 043f2fc75..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/benchmark.pc.in
+++ /dev/null
@@ -1,12 +0,0 @@
-prefix=@CMAKE_INSTALL_PREFIX@
-exec_prefix=${prefix}
-libdir=@CMAKE_INSTALL_FULL_LIBDIR@
-includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
-
-Name: @PROJECT_NAME@
-Description: Google microbenchmark framework
-Version: @VERSION@
-
-Libs: -L${libdir} -lbenchmark
-Libs.private: -lpthread @BENCHMARK_PRIVATE_LINK_LIBRARIES@
-Cflags: -I${includedir}
diff --git a/vendor/core/vendor/googlebenchmark/cmake/benchmark_main.pc.in b/vendor/core/vendor/googlebenchmark/cmake/benchmark_main.pc.in
deleted file mode 100644
index a90f3cd06..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/benchmark_main.pc.in
+++ /dev/null
@@ -1,7 +0,0 @@
-libdir=@CMAKE_INSTALL_FULL_LIBDIR@
-
-Name: @PROJECT_NAME@
-Description: Google microbenchmark framework (with main() function)
-Version: @VERSION@
-Requires: benchmark
-Libs: -L${libdir} -lbenchmark_main
diff --git a/vendor/core/vendor/googlebenchmark/cmake/gnu_posix_regex.cpp b/vendor/core/vendor/googlebenchmark/cmake/gnu_posix_regex.cpp
deleted file mode 100644
index b5b91cdab..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/gnu_posix_regex.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include 
-#include 
-int main() {
-  std::string str = "test0159";
-  regex_t re;
-  int ec = regcomp(&re, "^[a-z]+[0-9]+$", REG_EXTENDED | REG_NOSUB);
-  if (ec != 0) {
-    return ec;
-  }
-  return regexec(&re, str.c_str(), 0, nullptr, 0) ? -1 : 0;
-}
-
diff --git a/vendor/core/vendor/googlebenchmark/cmake/llvm-toolchain.cmake b/vendor/core/vendor/googlebenchmark/cmake/llvm-toolchain.cmake
deleted file mode 100644
index fc119e52f..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/llvm-toolchain.cmake
+++ /dev/null
@@ -1,8 +0,0 @@
-find_package(LLVMAr REQUIRED)
-set(CMAKE_AR "${LLVMAR_EXECUTABLE}" CACHE FILEPATH "" FORCE)
-
-find_package(LLVMNm REQUIRED)
-set(CMAKE_NM "${LLVMNM_EXECUTABLE}" CACHE FILEPATH "" FORCE)
-
-find_package(LLVMRanLib REQUIRED)
-set(CMAKE_RANLIB "${LLVMRANLIB_EXECUTABLE}" CACHE FILEPATH "" FORCE)
diff --git a/vendor/core/vendor/googlebenchmark/cmake/posix_regex.cpp b/vendor/core/vendor/googlebenchmark/cmake/posix_regex.cpp
deleted file mode 100644
index 466dc6256..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/posix_regex.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include 
-#include 
-int main() {
-  std::string str = "test0159";
-  regex_t re;
-  int ec = regcomp(&re, "^[a-z]+[0-9]+$", REG_EXTENDED | REG_NOSUB);
-  if (ec != 0) {
-    return ec;
-  }
-  int ret = regexec(&re, str.c_str(), 0, nullptr, 0) ? -1 : 0;
-  regfree(&re);
-  return ret;
-}
-
diff --git a/vendor/core/vendor/googlebenchmark/cmake/pthread_affinity.cpp b/vendor/core/vendor/googlebenchmark/cmake/pthread_affinity.cpp
deleted file mode 100644
index 7b143bc02..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/pthread_affinity.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include 
-int main() {
-  cpu_set_t set;
-  CPU_ZERO(&set);
-  for (int i = 0; i < CPU_SETSIZE; ++i) {
-    CPU_SET(i, &set);
-    CPU_CLR(i, &set);
-  }
-  pthread_t self = pthread_self();
-  int ret;
-  ret = pthread_getaffinity_np(self, sizeof(set), &set);
-  if (ret != 0) return ret;
-  ret = pthread_setaffinity_np(self, sizeof(set), &set);
-  if (ret != 0) return ret;
-  return 0;
-}
diff --git a/vendor/core/vendor/googlebenchmark/cmake/split_list.cmake b/vendor/core/vendor/googlebenchmark/cmake/split_list.cmake
deleted file mode 100644
index 67aed3fdc..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/split_list.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-macro(split_list listname)
-  string(REPLACE ";" " " ${listname} "${${listname}}")
-endmacro()
diff --git a/vendor/core/vendor/googlebenchmark/cmake/std_regex.cpp b/vendor/core/vendor/googlebenchmark/cmake/std_regex.cpp
deleted file mode 100644
index 696f2a26b..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/std_regex.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include 
-#include 
-int main() {
-  const std::string str = "test0159";
-  std::regex re;
-  re = std::regex("^[a-z]+[0-9]+$",
-       std::regex_constants::extended | std::regex_constants::nosubs);
-  return std::regex_search(str, re) ? 0 : -1;
-}
-
diff --git a/vendor/core/vendor/googlebenchmark/cmake/steady_clock.cpp b/vendor/core/vendor/googlebenchmark/cmake/steady_clock.cpp
deleted file mode 100644
index 66d50d17e..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/steady_clock.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include 
-
-int main() {
-    typedef std::chrono::steady_clock Clock;
-    Clock::time_point tp = Clock::now();
-    ((void)tp);
-}
diff --git a/vendor/core/vendor/googlebenchmark/cmake/thread_safety_attributes.cpp b/vendor/core/vendor/googlebenchmark/cmake/thread_safety_attributes.cpp
deleted file mode 100644
index 46161babd..000000000
--- a/vendor/core/vendor/googlebenchmark/cmake/thread_safety_attributes.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-#define HAVE_THREAD_SAFETY_ATTRIBUTES
-#include "../src/mutex.h"
-
-int main() {}
diff --git a/vendor/core/vendor/googlebenchmark/include/benchmark/benchmark.h b/vendor/core/vendor/googlebenchmark/include/benchmark/benchmark.h
deleted file mode 100644
index 7dd72e27b..000000000
--- a/vendor/core/vendor/googlebenchmark/include/benchmark/benchmark.h
+++ /dev/null
@@ -1,2060 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Support for registering benchmarks for functions.
-
-/* Example usage:
-// Define a function that executes the code to be measured a
-// specified number of times:
-static void BM_StringCreation(benchmark::State& state) {
-  for (auto _ : state)
-    std::string empty_string;
-}
-
-// Register the function as a benchmark
-BENCHMARK(BM_StringCreation);
-
-// Define another benchmark
-static void BM_StringCopy(benchmark::State& state) {
-  std::string x = "hello";
-  for (auto _ : state)
-    std::string copy(x);
-}
-BENCHMARK(BM_StringCopy);
-
-// Augment the main() program to invoke benchmarks if specified
-// via the --benchmark_filter command line flag.  E.g.,
-//       my_unittest --benchmark_filter=all
-//       my_unittest --benchmark_filter=BM_StringCreation
-//       my_unittest --benchmark_filter=String
-//       my_unittest --benchmark_filter='Copy|Creation'
-int main(int argc, char** argv) {
-  benchmark::Initialize(&argc, argv);
-  benchmark::RunSpecifiedBenchmarks();
-  benchmark::Shutdown();
-  return 0;
-}
-
-// Sometimes a family of microbenchmarks can be implemented with
-// just one routine that takes an extra argument to specify which
-// one of the family of benchmarks to run.  For example, the following
-// code defines a family of microbenchmarks for measuring the speed
-// of memcpy() calls of different lengths:
-
-static void BM_memcpy(benchmark::State& state) {
-  char* src = new char[state.range(0)]; char* dst = new char[state.range(0)];
-  memset(src, 'x', state.range(0));
-  for (auto _ : state)
-    memcpy(dst, src, state.range(0));
-  state.SetBytesProcessed(state.iterations() * state.range(0));
-  delete[] src; delete[] dst;
-}
-BENCHMARK(BM_memcpy)->Arg(8)->Arg(64)->Arg(512)->Arg(1<<10)->Arg(8<<10);
-
-// The preceding code is quite repetitive, and can be replaced with the
-// following short-hand.  The following invocation will pick a few
-// appropriate arguments in the specified range and will generate a
-// microbenchmark for each such argument.
-BENCHMARK(BM_memcpy)->Range(8, 8<<10);
-
-// You might have a microbenchmark that depends on two inputs.  For
-// example, the following code defines a family of microbenchmarks for
-// measuring the speed of set insertion.
-static void BM_SetInsert(benchmark::State& state) {
-  set data;
-  for (auto _ : state) {
-    state.PauseTiming();
-    data = ConstructRandomSet(state.range(0));
-    state.ResumeTiming();
-    for (int j = 0; j < state.range(1); ++j)
-      data.insert(RandomNumber());
-  }
-}
-BENCHMARK(BM_SetInsert)
-   ->Args({1<<10, 128})
-   ->Args({2<<10, 128})
-   ->Args({4<<10, 128})
-   ->Args({8<<10, 128})
-   ->Args({1<<10, 512})
-   ->Args({2<<10, 512})
-   ->Args({4<<10, 512})
-   ->Args({8<<10, 512});
-
-// The preceding code is quite repetitive, and can be replaced with
-// the following short-hand.  The following macro will pick a few
-// appropriate arguments in the product of the two specified ranges
-// and will generate a microbenchmark for each such pair.
-BENCHMARK(BM_SetInsert)->Ranges({{1<<10, 8<<10}, {128, 512}});
-
-// For more complex patterns of inputs, passing a custom function
-// to Apply allows programmatic specification of an
-// arbitrary set of arguments to run the microbenchmark on.
-// The following example enumerates a dense range on
-// one parameter, and a sparse range on the second.
-static void CustomArguments(benchmark::internal::Benchmark* b) {
-  for (int i = 0; i <= 10; ++i)
-    for (int j = 32; j <= 1024*1024; j *= 8)
-      b->Args({i, j});
-}
-BENCHMARK(BM_SetInsert)->Apply(CustomArguments);
-
-// Templated microbenchmarks work the same way:
-// Produce then consume 'size' messages 'iters' times
-// Measures throughput in the absence of multiprogramming.
-template  int BM_Sequential(benchmark::State& state) {
-  Q q;
-  typename Q::value_type v;
-  for (auto _ : state) {
-    for (int i = state.range(0); i--; )
-      q.push(v);
-    for (int e = state.range(0); e--; )
-      q.Wait(&v);
-  }
-  // actually messages, not bytes:
-  state.SetBytesProcessed(state.iterations() * state.range(0));
-}
-BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue)->Range(1<<0, 1<<10);
-
-Use `Benchmark::MinTime(double t)` to set the minimum time used to run the
-benchmark. This option overrides the `benchmark_min_time` flag.
-
-void BM_test(benchmark::State& state) {
- ... body ...
-}
-BENCHMARK(BM_test)->MinTime(2.0); // Run for at least 2 seconds.
-
-In a multithreaded test, it is guaranteed that none of the threads will start
-until all have reached the loop start, and all will have finished before any
-thread exits the loop body. As such, any global setup or teardown you want to
-do can be wrapped in a check against the thread index:
-
-static void BM_MultiThreaded(benchmark::State& state) {
-  if (state.thread_index() == 0) {
-    // Setup code here.
-  }
-  for (auto _ : state) {
-    // Run the test as normal.
-  }
-  if (state.thread_index() == 0) {
-    // Teardown code here.
-  }
-}
-BENCHMARK(BM_MultiThreaded)->Threads(4);
-
-
-If a benchmark runs a few milliseconds it may be hard to visually compare the
-measured times, since the output data is given in nanoseconds per default. In
-order to manually set the time unit, you can specify it manually:
-
-BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
-*/
-
-#ifndef BENCHMARK_BENCHMARK_H_
-#define BENCHMARK_BENCHMARK_H_
-
-// The _MSVC_LANG check should detect Visual Studio 2015 Update 3 and newer.
-#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
-#define BENCHMARK_HAS_CXX11
-#endif
-
-// This _MSC_VER check should detect VS 2017 v15.3 and newer.
-#if __cplusplus >= 201703L || \
-    (defined(_MSC_VER) && _MSC_VER >= 1911 && _MSVC_LANG >= 201703L)
-#define BENCHMARK_HAS_CXX17
-#endif
-
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "benchmark/export.h"
-
-#if defined(BENCHMARK_HAS_CXX11)
-#include 
-#include 
-#include 
-#include 
-#endif
-
-#if defined(_MSC_VER)
-#include   // for _ReadWriteBarrier
-#endif
-
-#ifndef BENCHMARK_HAS_CXX11
-#define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&);                         \
-  TypeName& operator=(const TypeName&)
-#else
-#define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&) = delete;                \
-  TypeName& operator=(const TypeName&) = delete
-#endif
-
-#ifdef BENCHMARK_HAS_CXX17
-#define BENCHMARK_UNUSED [[maybe_unused]]
-#elif defined(__GNUC__) || defined(__clang__)
-#define BENCHMARK_UNUSED __attribute__((unused))
-#else
-#define BENCHMARK_UNUSED
-#endif
-
-// Used to annotate functions, methods and classes so they
-// are not optimized by the compiler. Useful for tests
-// where you expect loops to stay in place churning cycles
-#if defined(__clang__)
-#define BENCHMARK_DONT_OPTIMIZE __attribute__((optnone))
-#elif defined(__GNUC__) || defined(__GNUG__)
-#define BENCHMARK_DONT_OPTIMIZE __attribute__((optimize(0)))
-#else
-// MSVC & Intel do not have a no-optimize attribute, only line pragmas
-#define BENCHMARK_DONT_OPTIMIZE
-#endif
-
-#if defined(__GNUC__) || defined(__clang__)
-#define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
-#elif defined(_MSC_VER) && !defined(__clang__)
-#define BENCHMARK_ALWAYS_INLINE __forceinline
-#define __func__ __FUNCTION__
-#else
-#define BENCHMARK_ALWAYS_INLINE
-#endif
-
-#define BENCHMARK_INTERNAL_TOSTRING2(x) #x
-#define BENCHMARK_INTERNAL_TOSTRING(x) BENCHMARK_INTERNAL_TOSTRING2(x)
-
-// clang-format off
-#if (defined(__GNUC__) && !defined(__NVCC__) && !defined(__NVCOMPILER)) || defined(__clang__)
-#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
-#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
-#define BENCHMARK_DISABLE_DEPRECATED_WARNING \
-  _Pragma("GCC diagnostic push")             \
-  _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
-#define BENCHMARK_RESTORE_DEPRECATED_WARNING _Pragma("GCC diagnostic pop")
-#elif defined(__NVCOMPILER)
-#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
-#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
-#define BENCHMARK_DISABLE_DEPRECATED_WARNING \
-  _Pragma("diagnostic push") \
-  _Pragma("diag_suppress deprecated_entity_with_custom_message")
-#define BENCHMARK_RESTORE_DEPRECATED_WARNING _Pragma("diagnostic pop")
-#else
-#define BENCHMARK_BUILTIN_EXPECT(x, y) x
-#define BENCHMARK_DEPRECATED_MSG(msg)
-#define BENCHMARK_WARNING_MSG(msg)                           \
-  __pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING( \
-      __LINE__) ") : warning note: " msg))
-#define BENCHMARK_DISABLE_DEPRECATED_WARNING
-#define BENCHMARK_RESTORE_DEPRECATED_WARNING
-#endif
-// clang-format on
-
-#if defined(__GNUC__) && !defined(__clang__)
-#define BENCHMARK_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-#endif
-
-#ifndef __has_builtin
-#define __has_builtin(x) 0
-#endif
-
-#if defined(__GNUC__) || __has_builtin(__builtin_unreachable)
-#define BENCHMARK_UNREACHABLE() __builtin_unreachable()
-#elif defined(_MSC_VER)
-#define BENCHMARK_UNREACHABLE() __assume(false)
-#else
-#define BENCHMARK_UNREACHABLE() ((void)0)
-#endif
-
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK_OVERRIDE override
-#else
-#define BENCHMARK_OVERRIDE
-#endif
-
-#if defined(_MSC_VER)
-#pragma warning(push)
-// C4251:  needs to have dll-interface to be used by clients of class
-#pragma warning(disable : 4251)
-#endif
-
-namespace benchmark {
-class BenchmarkReporter;
-
-// Default number of minimum benchmark running time in seconds.
-const char kDefaultMinTimeStr[] = "0.5s";
-
-// Returns the version of the library.
-BENCHMARK_EXPORT std::string GetBenchmarkVersion();
-
-BENCHMARK_EXPORT void PrintDefaultHelp();
-
-BENCHMARK_EXPORT void Initialize(int* argc, char** argv,
-                                 void (*HelperPrinterf)() = PrintDefaultHelp);
-BENCHMARK_EXPORT void Shutdown();
-
-// Report to stdout all arguments in 'argv' as unrecognized except the first.
-// Returns true there is at least on unrecognized argument (i.e. 'argc' > 1).
-BENCHMARK_EXPORT bool ReportUnrecognizedArguments(int argc, char** argv);
-
-// Returns the current value of --benchmark_filter.
-BENCHMARK_EXPORT std::string GetBenchmarkFilter();
-
-// Sets a new value to --benchmark_filter. (This will override this flag's
-// current value).
-// Should be called after `benchmark::Initialize()`, as
-// `benchmark::Initialize()` will override the flag's value.
-BENCHMARK_EXPORT void SetBenchmarkFilter(std::string value);
-
-// Returns the current value of --v (command line value for verbosity).
-BENCHMARK_EXPORT int32_t GetBenchmarkVerbosity();
-
-// Creates a default display reporter. Used by the library when no display
-// reporter is provided, but also made available for external use in case a
-// custom reporter should respect the `--benchmark_format` flag as a fallback
-BENCHMARK_EXPORT BenchmarkReporter* CreateDefaultDisplayReporter();
-
-// Generate a list of benchmarks matching the specified --benchmark_filter flag
-// and if --benchmark_list_tests is specified return after printing the name
-// of each matching benchmark. Otherwise run each matching benchmark and
-// report the results.
-//
-// spec : Specify the benchmarks to run. If users do not specify this arg,
-//        then the value of FLAGS_benchmark_filter
-//        will be used.
-//
-// The second and third overload use the specified 'display_reporter' and
-//  'file_reporter' respectively. 'file_reporter' will write to the file
-//  specified
-//   by '--benchmark_out'. If '--benchmark_out' is not given the
-//  'file_reporter' is ignored.
-//
-// RETURNS: The number of matching benchmarks.
-BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks();
-BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(std::string spec);
-
-BENCHMARK_EXPORT size_t
-RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter);
-BENCHMARK_EXPORT size_t
-RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter, std::string spec);
-
-BENCHMARK_EXPORT size_t RunSpecifiedBenchmarks(
-    BenchmarkReporter* display_reporter, BenchmarkReporter* file_reporter);
-BENCHMARK_EXPORT size_t
-RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
-                       BenchmarkReporter* file_reporter, std::string spec);
-
-// TimeUnit is passed to a benchmark in order to specify the order of magnitude
-// for the measured time.
-enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond, kSecond };
-
-BENCHMARK_EXPORT TimeUnit GetDefaultTimeUnit();
-
-// Sets the default time unit the benchmarks use
-// Has to be called before the benchmark loop to take effect
-BENCHMARK_EXPORT void SetDefaultTimeUnit(TimeUnit unit);
-
-// If a MemoryManager is registered (via RegisterMemoryManager()),
-// it can be used to collect and report allocation metrics for a run of the
-// benchmark.
-class MemoryManager {
- public:
-  static const int64_t TombstoneValue;
-
-  struct Result {
-    Result()
-        : num_allocs(0),
-          max_bytes_used(0),
-          total_allocated_bytes(TombstoneValue),
-          net_heap_growth(TombstoneValue) {}
-
-    // The number of allocations made in total between Start and Stop.
-    int64_t num_allocs;
-
-    // The peak memory use between Start and Stop.
-    int64_t max_bytes_used;
-
-    // The total memory allocated, in bytes, between Start and Stop.
-    // Init'ed to TombstoneValue if metric not available.
-    int64_t total_allocated_bytes;
-
-    // The net changes in memory, in bytes, between Start and Stop.
-    // ie., total_allocated_bytes - total_deallocated_bytes.
-    // Init'ed to TombstoneValue if metric not available.
-    int64_t net_heap_growth;
-  };
-
-  virtual ~MemoryManager() {}
-
-  // Implement this to start recording allocation information.
-  virtual void Start() = 0;
-
-  // Implement this to stop recording and fill out the given Result structure.
-  virtual void Stop(Result& result) = 0;
-};
-
-// Register a MemoryManager instance that will be used to collect and report
-// allocation measurements for benchmark runs.
-BENCHMARK_EXPORT
-void RegisterMemoryManager(MemoryManager* memory_manager);
-
-// If a ProfilerManager is registered (via RegisterProfilerManager()), the
-// benchmark will be run an additional time under the profiler to collect and
-// report profile metrics for the run of the benchmark.
-class ProfilerManager {
- public:
-  virtual ~ProfilerManager() {}
-
-  // This is called after `Setup()` code and right before the benchmark is run.
-  virtual void AfterSetupStart() = 0;
-
-  // This is called before `Teardown()` code and right after the benchmark
-  // completes.
-  virtual void BeforeTeardownStop() = 0;
-};
-
-// Register a ProfilerManager instance that will be used to collect and report
-// profile measurements for benchmark runs.
-BENCHMARK_EXPORT
-void RegisterProfilerManager(ProfilerManager* profiler_manager);
-
-// Add a key-value pair to output as part of the context stanza in the report.
-BENCHMARK_EXPORT
-void AddCustomContext(const std::string& key, const std::string& value);
-
-namespace internal {
-class Benchmark;
-class BenchmarkImp;
-class BenchmarkFamilies;
-
-BENCHMARK_EXPORT std::map*& GetGlobalContext();
-
-BENCHMARK_EXPORT
-void UseCharPointer(char const volatile*);
-
-// Take ownership of the pointer and register the benchmark. Return the
-// registered benchmark.
-BENCHMARK_EXPORT Benchmark* RegisterBenchmarkInternal(Benchmark*);
-
-// Ensure that the standard streams are properly initialized in every TU.
-BENCHMARK_EXPORT int InitializeStreams();
-BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
-
-}  // namespace internal
-
-#if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || \
-    defined(__EMSCRIPTEN__)
-#define BENCHMARK_HAS_NO_INLINE_ASSEMBLY
-#endif
-
-// Force the compiler to flush pending writes to global memory. Acts as an
-// effective read/write barrier
-#ifdef BENCHMARK_HAS_CXX11
-inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
-  std::atomic_signal_fence(std::memory_order_acq_rel);
-}
-#endif
-
-// The DoNotOptimize(...) function can be used to prevent a value or
-// expression from being optimized away by the compiler. This function is
-// intended to add little to no overhead.
-// See: https://youtu.be/nXaxk27zwlk?t=2441
-#ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY
-#if !defined(__GNUC__) || defined(__llvm__) || defined(__INTEL_COMPILER)
-template 
-BENCHMARK_DEPRECATED_MSG(
-    "The const-ref version of this method can permit "
-    "undesired compiler optimizations in benchmarks")
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
-  asm volatile("" : : "r,m"(value) : "memory");
-}
-
-template 
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
-#if defined(__clang__)
-  asm volatile("" : "+r,m"(value) : : "memory");
-#else
-  asm volatile("" : "+m,r"(value) : : "memory");
-#endif
-}
-
-#ifdef BENCHMARK_HAS_CXX11
-template 
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
-#if defined(__clang__)
-  asm volatile("" : "+r,m"(value) : : "memory");
-#else
-  asm volatile("" : "+m,r"(value) : : "memory");
-#endif
-}
-#endif
-#elif defined(BENCHMARK_HAS_CXX11) && (__GNUC__ >= 5)
-// Workaround for a bug with full argument copy overhead with GCC.
-// See: #1340 and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105519
-template 
-BENCHMARK_DEPRECATED_MSG(
-    "The const-ref version of this method can permit "
-    "undesired compiler optimizations in benchmarks")
-inline BENCHMARK_ALWAYS_INLINE
-    typename std::enable_if::value &&
-                            (sizeof(Tp) <= sizeof(Tp*))>::type
-    DoNotOptimize(Tp const& value) {
-  asm volatile("" : : "r,m"(value) : "memory");
-}
-
-template 
-BENCHMARK_DEPRECATED_MSG(
-    "The const-ref version of this method can permit "
-    "undesired compiler optimizations in benchmarks")
-inline BENCHMARK_ALWAYS_INLINE
-    typename std::enable_if::value ||
-                            (sizeof(Tp) > sizeof(Tp*))>::type
-    DoNotOptimize(Tp const& value) {
-  asm volatile("" : : "m"(value) : "memory");
-}
-
-template 
-inline BENCHMARK_ALWAYS_INLINE
-    typename std::enable_if::value &&
-                            (sizeof(Tp) <= sizeof(Tp*))>::type
-    DoNotOptimize(Tp& value) {
-  asm volatile("" : "+m,r"(value) : : "memory");
-}
-
-template 
-inline BENCHMARK_ALWAYS_INLINE
-    typename std::enable_if::value ||
-                            (sizeof(Tp) > sizeof(Tp*))>::type
-    DoNotOptimize(Tp& value) {
-  asm volatile("" : "+m"(value) : : "memory");
-}
-
-template 
-inline BENCHMARK_ALWAYS_INLINE
-    typename std::enable_if::value &&
-                            (sizeof(Tp) <= sizeof(Tp*))>::type
-    DoNotOptimize(Tp&& value) {
-  asm volatile("" : "+m,r"(value) : : "memory");
-}
-
-template 
-inline BENCHMARK_ALWAYS_INLINE
-    typename std::enable_if::value ||
-                            (sizeof(Tp) > sizeof(Tp*))>::type
-    DoNotOptimize(Tp&& value) {
-  asm volatile("" : "+m"(value) : : "memory");
-}
-
-#else
-// Fallback for GCC < 5. Can add some overhead because the compiler is forced
-// to use memory operations instead of operations with registers.
-// TODO: Remove if GCC < 5 will be unsupported.
-template 
-BENCHMARK_DEPRECATED_MSG(
-    "The const-ref version of this method can permit "
-    "undesired compiler optimizations in benchmarks")
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
-  asm volatile("" : : "m"(value) : "memory");
-}
-
-template 
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
-  asm volatile("" : "+m"(value) : : "memory");
-}
-
-#ifdef BENCHMARK_HAS_CXX11
-template 
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
-  asm volatile("" : "+m"(value) : : "memory");
-}
-#endif
-#endif
-
-#ifndef BENCHMARK_HAS_CXX11
-inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
-  asm volatile("" : : : "memory");
-}
-#endif
-#elif defined(_MSC_VER)
-template 
-BENCHMARK_DEPRECATED_MSG(
-    "The const-ref version of this method can permit "
-    "undesired compiler optimizations in benchmarks")
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
-  internal::UseCharPointer(&reinterpret_cast(value));
-  _ReadWriteBarrier();
-}
-
-#ifndef BENCHMARK_HAS_CXX11
-inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { _ReadWriteBarrier(); }
-#endif
-#else
-#ifdef BENCHMARK_HAS_CXX11
-template 
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) {
-  internal::UseCharPointer(&reinterpret_cast(value));
-}
-#else
-template 
-BENCHMARK_DEPRECATED_MSG(
-    "The const-ref version of this method can permit "
-    "undesired compiler optimizations in benchmarks")
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
-  internal::UseCharPointer(&reinterpret_cast(value));
-}
-
-template 
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
-  internal::UseCharPointer(&reinterpret_cast(value));
-}
-#endif
-// FIXME Add ClobberMemory() for non-gnu and non-msvc compilers, before C++11.
-#endif
-
-// This class is used for user-defined counters.
-class Counter {
- public:
-  enum Flags {
-    kDefaults = 0,
-    // Mark the counter as a rate. It will be presented divided
-    // by the duration of the benchmark.
-    kIsRate = 1 << 0,
-    // Mark the counter as a thread-average quantity. It will be
-    // presented divided by the number of threads.
-    kAvgThreads = 1 << 1,
-    // Mark the counter as a thread-average rate. See above.
-    kAvgThreadsRate = kIsRate | kAvgThreads,
-    // Mark the counter as a constant value, valid/same for *every* iteration.
-    // When reporting, it will be *multiplied* by the iteration count.
-    kIsIterationInvariant = 1 << 2,
-    // Mark the counter as a constant rate.
-    // When reporting, it will be *multiplied* by the iteration count
-    // and then divided by the duration of the benchmark.
-    kIsIterationInvariantRate = kIsRate | kIsIterationInvariant,
-    // Mark the counter as a iteration-average quantity.
-    // It will be presented divided by the number of iterations.
-    kAvgIterations = 1 << 3,
-    // Mark the counter as a iteration-average rate. See above.
-    kAvgIterationsRate = kIsRate | kAvgIterations,
-
-    // In the end, invert the result. This is always done last!
-    kInvert = 1 << 31
-  };
-
-  enum OneK {
-    // 1'000 items per 1k
-    kIs1000 = 1000,
-    // 1'024 items per 1k
-    kIs1024 = 1024
-  };
-
-  double value;
-  Flags flags;
-  OneK oneK;
-
-  BENCHMARK_ALWAYS_INLINE
-  Counter(double v = 0., Flags f = kDefaults, OneK k = kIs1000)
-      : value(v), flags(f), oneK(k) {}
-
-  BENCHMARK_ALWAYS_INLINE operator double const &() const { return value; }
-  BENCHMARK_ALWAYS_INLINE operator double&() { return value; }
-};
-
-// A helper for user code to create unforeseen combinations of Flags, without
-// having to do this cast manually each time, or providing this operator.
-Counter::Flags inline operator|(const Counter::Flags& LHS,
-                                const Counter::Flags& RHS) {
-  return static_cast(static_cast(LHS) |
-                                     static_cast(RHS));
-}
-
-// This is the container for the user-defined counters.
-typedef std::map UserCounters;
-
-// BigO is passed to a benchmark in order to specify the asymptotic
-// computational
-// complexity for the benchmark. In case oAuto is selected, complexity will be
-// calculated automatically to the best fit.
-enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda };
-
-typedef int64_t ComplexityN;
-
-typedef int64_t IterationCount;
-
-enum StatisticUnit { kTime, kPercentage };
-
-// BigOFunc is passed to a benchmark in order to specify the asymptotic
-// computational complexity for the benchmark.
-typedef double(BigOFunc)(ComplexityN);
-
-// StatisticsFunc is passed to a benchmark in order to compute some descriptive
-// statistics over all the measurements of some type
-typedef double(StatisticsFunc)(const std::vector&);
-
-namespace internal {
-struct Statistics {
-  std::string name_;
-  StatisticsFunc* compute_;
-  StatisticUnit unit_;
-
-  Statistics(const std::string& name, StatisticsFunc* compute,
-             StatisticUnit unit = kTime)
-      : name_(name), compute_(compute), unit_(unit) {}
-};
-
-class BenchmarkInstance;
-class ThreadTimer;
-class ThreadManager;
-class PerfCountersMeasurement;
-
-enum AggregationReportMode
-#if defined(BENCHMARK_HAS_CXX11)
-    : unsigned
-#else
-#endif
-{
-  // The mode has not been manually specified
-  ARM_Unspecified = 0,
-  // The mode is user-specified.
-  // This may or may not be set when the following bit-flags are set.
-  ARM_Default = 1U << 0U,
-  // File reporter should only output aggregates.
-  ARM_FileReportAggregatesOnly = 1U << 1U,
-  // Display reporter should only output aggregates
-  ARM_DisplayReportAggregatesOnly = 1U << 2U,
-  // Both reporters should only display aggregates.
-  ARM_ReportAggregatesOnly =
-      ARM_FileReportAggregatesOnly | ARM_DisplayReportAggregatesOnly
-};
-
-enum Skipped
-#if defined(BENCHMARK_HAS_CXX11)
-    : unsigned
-#endif
-{
-  NotSkipped = 0,
-  SkippedWithMessage,
-  SkippedWithError
-};
-
-}  // namespace internal
-
-// State is passed to a running Benchmark and contains state for the
-// benchmark to use.
-class BENCHMARK_EXPORT State {
- public:
-  struct StateIterator;
-  friend struct StateIterator;
-
-  // Returns iterators used to run each iteration of a benchmark using a
-  // C++11 ranged-based for loop. These functions should not be called directly.
-  //
-  // REQUIRES: The benchmark has not started running yet. Neither begin nor end
-  // have been called previously.
-  //
-  // NOTE: KeepRunning may not be used after calling either of these functions.
-  inline BENCHMARK_ALWAYS_INLINE StateIterator begin();
-  inline BENCHMARK_ALWAYS_INLINE StateIterator end();
-
-  // Returns true if the benchmark should continue through another iteration.
-  // NOTE: A benchmark may not return from the test until KeepRunning() has
-  // returned false.
-  inline bool KeepRunning();
-
-  // Returns true iff the benchmark should run n more iterations.
-  // REQUIRES: 'n' > 0.
-  // NOTE: A benchmark must not return from the test until KeepRunningBatch()
-  // has returned false.
-  // NOTE: KeepRunningBatch() may overshoot by up to 'n' iterations.
-  //
-  // Intended usage:
-  //   while (state.KeepRunningBatch(1000)) {
-  //     // process 1000 elements
-  //   }
-  inline bool KeepRunningBatch(IterationCount n);
-
-  // REQUIRES: timer is running and 'SkipWithMessage(...)' or
-  //   'SkipWithError(...)' has not been called by the current thread.
-  // Stop the benchmark timer.  If not called, the timer will be
-  // automatically stopped after the last iteration of the benchmark loop.
-  //
-  // For threaded benchmarks the PauseTiming() function only pauses the timing
-  // for the current thread.
-  //
-  // NOTE: The "real time" measurement is per-thread. If different threads
-  // report different measurements the largest one is reported.
-  //
-  // NOTE: PauseTiming()/ResumeTiming() are relatively
-  // heavyweight, and so their use should generally be avoided
-  // within each benchmark iteration, if possible.
-  void PauseTiming();
-
-  // REQUIRES: timer is not running and 'SkipWithMessage(...)' or
-  //   'SkipWithError(...)' has not been called by the current thread.
-  // Start the benchmark timer.  The timer is NOT running on entrance to the
-  // benchmark function. It begins running after control flow enters the
-  // benchmark loop.
-  //
-  // NOTE: PauseTiming()/ResumeTiming() are relatively
-  // heavyweight, and so their use should generally be avoided
-  // within each benchmark iteration, if possible.
-  void ResumeTiming();
-
-  // REQUIRES: 'SkipWithMessage(...)' or 'SkipWithError(...)' has not been
-  //            called previously by the current thread.
-  // Report the benchmark as resulting in being skipped with the specified
-  // 'msg'.
-  // After this call the user may explicitly 'return' from the benchmark.
-  //
-  // If the ranged-for style of benchmark loop is used, the user must explicitly
-  // break from the loop, otherwise all future iterations will be run.
-  // If the 'KeepRunning()' loop is used the current thread will automatically
-  // exit the loop at the end of the current iteration.
-  //
-  // For threaded benchmarks only the current thread stops executing and future
-  // calls to `KeepRunning()` will block until all threads have completed
-  // the `KeepRunning()` loop. If multiple threads report being skipped only the
-  // first skip message is used.
-  //
-  // NOTE: Calling 'SkipWithMessage(...)' does not cause the benchmark to exit
-  // the current scope immediately. If the function is called from within
-  // the 'KeepRunning()' loop the current iteration will finish. It is the users
-  // responsibility to exit the scope as needed.
-  void SkipWithMessage(const std::string& msg);
-
-  // REQUIRES: 'SkipWithMessage(...)' or 'SkipWithError(...)' has not been
-  //            called previously by the current thread.
-  // Report the benchmark as resulting in an error with the specified 'msg'.
-  // After this call the user may explicitly 'return' from the benchmark.
-  //
-  // If the ranged-for style of benchmark loop is used, the user must explicitly
-  // break from the loop, otherwise all future iterations will be run.
-  // If the 'KeepRunning()' loop is used the current thread will automatically
-  // exit the loop at the end of the current iteration.
-  //
-  // For threaded benchmarks only the current thread stops executing and future
-  // calls to `KeepRunning()` will block until all threads have completed
-  // the `KeepRunning()` loop. If multiple threads report an error only the
-  // first error message is used.
-  //
-  // NOTE: Calling 'SkipWithError(...)' does not cause the benchmark to exit
-  // the current scope immediately. If the function is called from within
-  // the 'KeepRunning()' loop the current iteration will finish. It is the users
-  // responsibility to exit the scope as needed.
-  void SkipWithError(const std::string& msg);
-
-  // Returns true if 'SkipWithMessage(...)' or 'SkipWithError(...)' was called.
-  bool skipped() const { return internal::NotSkipped != skipped_; }
-
-  // Returns true if an error has been reported with 'SkipWithError(...)'.
-  bool error_occurred() const { return internal::SkippedWithError == skipped_; }
-
-  // REQUIRES: called exactly once per iteration of the benchmarking loop.
-  // Set the manually measured time for this benchmark iteration, which
-  // is used instead of automatically measured time if UseManualTime() was
-  // specified.
-  //
-  // For threaded benchmarks the final value will be set to the largest
-  // reported values.
-  void SetIterationTime(double seconds);
-
-  // Set the number of bytes processed by the current benchmark
-  // execution.  This routine is typically called once at the end of a
-  // throughput oriented benchmark.
-  //
-  // REQUIRES: a benchmark has exited its benchmarking loop.
-  BENCHMARK_ALWAYS_INLINE
-  void SetBytesProcessed(int64_t bytes) {
-    counters["bytes_per_second"] =
-        Counter(static_cast(bytes), Counter::kIsRate, Counter::kIs1024);
-  }
-
-  BENCHMARK_ALWAYS_INLINE
-  int64_t bytes_processed() const {
-    if (counters.find("bytes_per_second") != counters.end())
-      return static_cast(counters.at("bytes_per_second"));
-    return 0;
-  }
-
-  // If this routine is called with complexity_n > 0 and complexity report is
-  // requested for the
-  // family benchmark, then current benchmark will be part of the computation
-  // and complexity_n will
-  // represent the length of N.
-  BENCHMARK_ALWAYS_INLINE
-  void SetComplexityN(ComplexityN complexity_n) {
-    complexity_n_ = complexity_n;
-  }
-
-  BENCHMARK_ALWAYS_INLINE
-  ComplexityN complexity_length_n() const { return complexity_n_; }
-
-  // If this routine is called with items > 0, then an items/s
-  // label is printed on the benchmark report line for the currently
-  // executing benchmark. It is typically called at the end of a processing
-  // benchmark where a processing items/second output is desired.
-  //
-  // REQUIRES: a benchmark has exited its benchmarking loop.
-  BENCHMARK_ALWAYS_INLINE
-  void SetItemsProcessed(int64_t items) {
-    counters["items_per_second"] =
-        Counter(static_cast(items), benchmark::Counter::kIsRate);
-  }
-
-  BENCHMARK_ALWAYS_INLINE
-  int64_t items_processed() const {
-    if (counters.find("items_per_second") != counters.end())
-      return static_cast(counters.at("items_per_second"));
-    return 0;
-  }
-
-  // If this routine is called, the specified label is printed at the
-  // end of the benchmark report line for the currently executing
-  // benchmark.  Example:
-  //  static void BM_Compress(benchmark::State& state) {
-  //    ...
-  //    double compress = input_size / output_size;
-  //    state.SetLabel(StrFormat("compress:%.1f%%", 100.0*compression));
-  //  }
-  // Produces output that looks like:
-  //  BM_Compress   50         50   14115038  compress:27.3%
-  //
-  // REQUIRES: a benchmark has exited its benchmarking loop.
-  void SetLabel(const std::string& label);
-
-  // Range arguments for this run. CHECKs if the argument has been set.
-  BENCHMARK_ALWAYS_INLINE
-  int64_t range(std::size_t pos = 0) const {
-    assert(range_.size() > pos);
-    return range_[pos];
-  }
-
-  BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead")
-  int64_t range_x() const { return range(0); }
-
-  BENCHMARK_DEPRECATED_MSG("use 'range(1)' instead")
-  int64_t range_y() const { return range(1); }
-
-  // Number of threads concurrently executing the benchmark.
-  BENCHMARK_ALWAYS_INLINE
-  int threads() const { return threads_; }
-
-  // Index of the executing thread. Values from [0, threads).
-  BENCHMARK_ALWAYS_INLINE
-  int thread_index() const { return thread_index_; }
-
-  BENCHMARK_ALWAYS_INLINE
-  IterationCount iterations() const {
-    if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) {
-      return 0;
-    }
-    return max_iterations - total_iterations_ + batch_leftover_;
-  }
-
-  BENCHMARK_ALWAYS_INLINE
-  std::string name() const { return name_; }
-
- private:
-  // items we expect on the first cache line (ie 64 bytes of the struct)
-  // When total_iterations_ is 0, KeepRunning() and friends will return false.
-  // May be larger than max_iterations.
-  IterationCount total_iterations_;
-
-  // When using KeepRunningBatch(), batch_leftover_ holds the number of
-  // iterations beyond max_iters that were run. Used to track
-  // completed_iterations_ accurately.
-  IterationCount batch_leftover_;
-
- public:
-  const IterationCount max_iterations;
-
- private:
-  bool started_;
-  bool finished_;
-  internal::Skipped skipped_;
-
-  // items we don't need on the first cache line
-  std::vector range_;
-
-  ComplexityN complexity_n_;
-
- public:
-  // Container for user-defined counters.
-  UserCounters counters;
-
- private:
-  State(std::string name, IterationCount max_iters,
-        const std::vector& ranges, int thread_i, int n_threads,
-        internal::ThreadTimer* timer, internal::ThreadManager* manager,
-        internal::PerfCountersMeasurement* perf_counters_measurement);
-
-  void StartKeepRunning();
-  // Implementation of KeepRunning() and KeepRunningBatch().
-  // is_batch must be true unless n is 1.
-  inline bool KeepRunningInternal(IterationCount n, bool is_batch);
-  void FinishKeepRunning();
-
-  const std::string name_;
-  const int thread_index_;
-  const int threads_;
-
-  internal::ThreadTimer* const timer_;
-  internal::ThreadManager* const manager_;
-  internal::PerfCountersMeasurement* const perf_counters_measurement_;
-
-  friend class internal::BenchmarkInstance;
-};
-
-inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunning() {
-  return KeepRunningInternal(1, /*is_batch=*/false);
-}
-
-inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningBatch(IterationCount n) {
-  return KeepRunningInternal(n, /*is_batch=*/true);
-}
-
-inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningInternal(IterationCount n,
-                                                               bool is_batch) {
-  // total_iterations_ is set to 0 by the constructor, and always set to a
-  // nonzero value by StartKepRunning().
-  assert(n > 0);
-  // n must be 1 unless is_batch is true.
-  assert(is_batch || n == 1);
-  if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ >= n, true)) {
-    total_iterations_ -= n;
-    return true;
-  }
-  if (!started_) {
-    StartKeepRunning();
-    if (!skipped() && total_iterations_ >= n) {
-      total_iterations_ -= n;
-      return true;
-    }
-  }
-  // For non-batch runs, total_iterations_ must be 0 by now.
-  if (is_batch && total_iterations_ != 0) {
-    batch_leftover_ = n - total_iterations_;
-    total_iterations_ = 0;
-    return true;
-  }
-  FinishKeepRunning();
-  return false;
-}
-
-struct State::StateIterator {
-  struct BENCHMARK_UNUSED Value {};
-  typedef std::forward_iterator_tag iterator_category;
-  typedef Value value_type;
-  typedef Value reference;
-  typedef Value pointer;
-  typedef std::ptrdiff_t difference_type;
-
- private:
-  friend class State;
-  BENCHMARK_ALWAYS_INLINE
-  StateIterator() : cached_(0), parent_() {}
-
-  BENCHMARK_ALWAYS_INLINE
-  explicit StateIterator(State* st)
-      : cached_(st->skipped() ? 0 : st->max_iterations), parent_(st) {}
-
- public:
-  BENCHMARK_ALWAYS_INLINE
-  Value operator*() const { return Value(); }
-
-  BENCHMARK_ALWAYS_INLINE
-  StateIterator& operator++() {
-    assert(cached_ > 0);
-    --cached_;
-    return *this;
-  }
-
-  BENCHMARK_ALWAYS_INLINE
-  bool operator!=(StateIterator const&) const {
-    if (BENCHMARK_BUILTIN_EXPECT(cached_ != 0, true)) return true;
-    parent_->FinishKeepRunning();
-    return false;
-  }
-
- private:
-  IterationCount cached_;
-  State* const parent_;
-};
-
-inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::begin() {
-  return StateIterator(this);
-}
-inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::end() {
-  StartKeepRunning();
-  return StateIterator();
-}
-
-namespace internal {
-
-typedef void(Function)(State&);
-
-// ------------------------------------------------------
-// Benchmark registration object.  The BENCHMARK() macro expands
-// into an internal::Benchmark* object.  Various methods can
-// be called on this object to change the properties of the benchmark.
-// Each method returns "this" so that multiple method calls can
-// chained into one expression.
-class BENCHMARK_EXPORT Benchmark {
- public:
-  virtual ~Benchmark();
-
-  // Note: the following methods all return "this" so that multiple
-  // method calls can be chained together in one expression.
-
-  // Specify the name of the benchmark
-  Benchmark* Name(const std::string& name);
-
-  // Run this benchmark once with "x" as the extra argument passed
-  // to the function.
-  // REQUIRES: The function passed to the constructor must accept an arg1.
-  Benchmark* Arg(int64_t x);
-
-  // Run this benchmark with the given time unit for the generated output report
-  Benchmark* Unit(TimeUnit unit);
-
-  // Run this benchmark once for a number of values picked from the
-  // range [start..limit].  (start and limit are always picked.)
-  // REQUIRES: The function passed to the constructor must accept an arg1.
-  Benchmark* Range(int64_t start, int64_t limit);
-
-  // Run this benchmark once for all values in the range [start..limit] with
-  // specific step
-  // REQUIRES: The function passed to the constructor must accept an arg1.
-  Benchmark* DenseRange(int64_t start, int64_t limit, int step = 1);
-
-  // Run this benchmark once with "args" as the extra arguments passed
-  // to the function.
-  // REQUIRES: The function passed to the constructor must accept arg1, arg2 ...
-  Benchmark* Args(const std::vector& args);
-
-  // Equivalent to Args({x, y})
-  // NOTE: This is a legacy C++03 interface provided for compatibility only.
-  //   New code should use 'Args'.
-  Benchmark* ArgPair(int64_t x, int64_t y) {
-    std::vector args;
-    args.push_back(x);
-    args.push_back(y);
-    return Args(args);
-  }
-
-  // Run this benchmark once for a number of values picked from the
-  // ranges [start..limit].  (starts and limits are always picked.)
-  // REQUIRES: The function passed to the constructor must accept arg1, arg2 ...
-  Benchmark* Ranges(const std::vector >& ranges);
-
-  // Run this benchmark once for each combination of values in the (cartesian)
-  // product of the supplied argument lists.
-  // REQUIRES: The function passed to the constructor must accept arg1, arg2 ...
-  Benchmark* ArgsProduct(const std::vector >& arglists);
-
-  // Equivalent to ArgNames({name})
-  Benchmark* ArgName(const std::string& name);
-
-  // Set the argument names to display in the benchmark name. If not called,
-  // only argument values will be shown.
-  Benchmark* ArgNames(const std::vector& names);
-
-  // Equivalent to Ranges({{lo1, hi1}, {lo2, hi2}}).
-  // NOTE: This is a legacy C++03 interface provided for compatibility only.
-  //   New code should use 'Ranges'.
-  Benchmark* RangePair(int64_t lo1, int64_t hi1, int64_t lo2, int64_t hi2) {
-    std::vector > ranges;
-    ranges.push_back(std::make_pair(lo1, hi1));
-    ranges.push_back(std::make_pair(lo2, hi2));
-    return Ranges(ranges);
-  }
-
-  // Have "setup" and/or "teardown" invoked once for every benchmark run.
-  // If the benchmark is multi-threaded (will run in k threads concurrently),
-  // the setup callback will be be invoked exactly once (not k times) before
-  // each run with k threads. Time allowing (e.g. for a short benchmark), there
-  // may be multiple such runs per benchmark, each run with its own
-  // "setup"/"teardown".
-  //
-  // If the benchmark uses different size groups of threads (e.g. via
-  // ThreadRange), the above will be true for each size group.
-  //
-  // The callback will be passed a State object, which includes the number
-  // of threads, thread-index, benchmark arguments, etc.
-  //
-  // The callback must not be NULL or self-deleting.
-  Benchmark* Setup(void (*setup)(const benchmark::State&));
-  Benchmark* Teardown(void (*teardown)(const benchmark::State&));
-
-  // Pass this benchmark object to *func, which can customize
-  // the benchmark by calling various methods like Arg, Args,
-  // Threads, etc.
-  Benchmark* Apply(void (*func)(Benchmark* benchmark));
-
-  // Set the range multiplier for non-dense range. If not called, the range
-  // multiplier kRangeMultiplier will be used.
-  Benchmark* RangeMultiplier(int multiplier);
-
-  // Set the minimum amount of time to use when running this benchmark. This
-  // option overrides the `benchmark_min_time` flag.
-  // REQUIRES: `t > 0` and `Iterations` has not been called on this benchmark.
-  Benchmark* MinTime(double t);
-
-  // Set the minimum amount of time to run the benchmark before taking runtimes
-  // of this benchmark into account. This
-  // option overrides the `benchmark_min_warmup_time` flag.
-  // REQUIRES: `t >= 0` and `Iterations` has not been called on this benchmark.
-  Benchmark* MinWarmUpTime(double t);
-
-  // Specify the amount of iterations that should be run by this benchmark.
-  // This option overrides the `benchmark_min_time` flag.
-  // REQUIRES: 'n > 0' and `MinTime` has not been called on this benchmark.
-  //
-  // NOTE: This function should only be used when *exact* iteration control is
-  //   needed and never to control or limit how long a benchmark runs, where
-  // `--benchmark_min_time=s` or `MinTime(...)` should be used instead.
-  Benchmark* Iterations(IterationCount n);
-
-  // Specify the amount of times to repeat this benchmark. This option overrides
-  // the `benchmark_repetitions` flag.
-  // REQUIRES: `n > 0`
-  Benchmark* Repetitions(int n);
-
-  // Specify if each repetition of the benchmark should be reported separately
-  // or if only the final statistics should be reported. If the benchmark
-  // is not repeated then the single result is always reported.
-  // Applies to *ALL* reporters (display and file).
-  Benchmark* ReportAggregatesOnly(bool value = true);
-
-  // Same as ReportAggregatesOnly(), but applies to display reporter only.
-  Benchmark* DisplayAggregatesOnly(bool value = true);
-
-  // By default, the CPU time is measured only for the main thread, which may
-  // be unrepresentative if the benchmark uses threads internally. If called,
-  // the total CPU time spent by all the threads will be measured instead.
-  // By default, only the main thread CPU time will be measured.
-  Benchmark* MeasureProcessCPUTime();
-
-  // If a particular benchmark should use the Wall clock instead of the CPU time
-  // (be it either the CPU time of the main thread only (default), or the
-  // total CPU usage of the benchmark), call this method. If called, the elapsed
-  // (wall) time will be used to control how many iterations are run, and in the
-  // printing of items/second or MB/seconds values.
-  // If not called, the CPU time used by the benchmark will be used.
-  Benchmark* UseRealTime();
-
-  // If a benchmark must measure time manually (e.g. if GPU execution time is
-  // being
-  // measured), call this method. If called, each benchmark iteration should
-  // call
-  // SetIterationTime(seconds) to report the measured time, which will be used
-  // to control how many iterations are run, and in the printing of items/second
-  // or MB/second values.
-  Benchmark* UseManualTime();
-
-  // Set the asymptotic computational complexity for the benchmark. If called
-  // the asymptotic computational complexity will be shown on the output.
-  Benchmark* Complexity(BigO complexity = benchmark::oAuto);
-
-  // Set the asymptotic computational complexity for the benchmark. If called
-  // the asymptotic computational complexity will be shown on the output.
-  Benchmark* Complexity(BigOFunc* complexity);
-
-  // Add this statistics to be computed over all the values of benchmark run
-  Benchmark* ComputeStatistics(const std::string& name,
-                               StatisticsFunc* statistics,
-                               StatisticUnit unit = kTime);
-
-  // Support for running multiple copies of the same benchmark concurrently
-  // in multiple threads.  This may be useful when measuring the scaling
-  // of some piece of code.
-
-  // Run one instance of this benchmark concurrently in t threads.
-  Benchmark* Threads(int t);
-
-  // Pick a set of values T from [min_threads,max_threads].
-  // min_threads and max_threads are always included in T.  Run this
-  // benchmark once for each value in T.  The benchmark run for a
-  // particular value t consists of t threads running the benchmark
-  // function concurrently.  For example, consider:
-  //    BENCHMARK(Foo)->ThreadRange(1,16);
-  // This will run the following benchmarks:
-  //    Foo in 1 thread
-  //    Foo in 2 threads
-  //    Foo in 4 threads
-  //    Foo in 8 threads
-  //    Foo in 16 threads
-  Benchmark* ThreadRange(int min_threads, int max_threads);
-
-  // For each value n in the range, run this benchmark once using n threads.
-  // min_threads and max_threads are always included in the range.
-  // stride specifies the increment. E.g. DenseThreadRange(1, 8, 3) starts
-  // a benchmark with 1, 4, 7 and 8 threads.
-  Benchmark* DenseThreadRange(int min_threads, int max_threads, int stride = 1);
-
-  // Equivalent to ThreadRange(NumCPUs(), NumCPUs())
-  Benchmark* ThreadPerCpu();
-
-  virtual void Run(State& state) = 0;
-
-  TimeUnit GetTimeUnit() const;
-
- protected:
-  explicit Benchmark(const std::string& name);
-  void SetName(const std::string& name);
-
- public:
-  const char* GetName() const;
-  int ArgsCnt() const;
-  const char* GetArgName(int arg) const;
-
- private:
-  friend class BenchmarkFamilies;
-  friend class BenchmarkInstance;
-
-  std::string name_;
-  AggregationReportMode aggregation_report_mode_;
-  std::vector arg_names_;       // Args for all benchmark runs
-  std::vector > args_;  // Args for all benchmark runs
-
-  TimeUnit time_unit_;
-  bool use_default_time_unit_;
-
-  int range_multiplier_;
-  double min_time_;
-  double min_warmup_time_;
-  IterationCount iterations_;
-  int repetitions_;
-  bool measure_process_cpu_time_;
-  bool use_real_time_;
-  bool use_manual_time_;
-  BigO complexity_;
-  BigOFunc* complexity_lambda_;
-  std::vector statistics_;
-  std::vector thread_counts_;
-
-  typedef void (*callback_function)(const benchmark::State&);
-  callback_function setup_;
-  callback_function teardown_;
-
-  Benchmark(Benchmark const&)
-#if defined(BENCHMARK_HAS_CXX11)
-      = delete
-#endif
-      ;
-
-  Benchmark& operator=(Benchmark const&)
-#if defined(BENCHMARK_HAS_CXX11)
-      = delete
-#endif
-      ;
-};
-
-}  // namespace internal
-
-// Create and register a benchmark with the specified 'name' that invokes
-// the specified functor 'fn'.
-//
-// RETURNS: A pointer to the registered benchmark.
-internal::Benchmark* RegisterBenchmark(const std::string& name,
-                                       internal::Function* fn);
-
-#if defined(BENCHMARK_HAS_CXX11)
-template 
-internal::Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn);
-#endif
-
-// Remove all registered benchmarks. All pointers to previously registered
-// benchmarks are invalidated.
-BENCHMARK_EXPORT void ClearRegisteredBenchmarks();
-
-namespace internal {
-// The class used to hold all Benchmarks created from static function.
-// (ie those created using the BENCHMARK(...) macros.
-class BENCHMARK_EXPORT FunctionBenchmark : public Benchmark {
- public:
-  FunctionBenchmark(const std::string& name, Function* func)
-      : Benchmark(name), func_(func) {}
-
-  void Run(State& st) BENCHMARK_OVERRIDE;
-
- private:
-  Function* func_;
-};
-
-#ifdef BENCHMARK_HAS_CXX11
-template 
-class LambdaBenchmark : public Benchmark {
- public:
-  void Run(State& st) BENCHMARK_OVERRIDE { lambda_(st); }
-
- private:
-  template 
-  LambdaBenchmark(const std::string& name, OLambda&& lam)
-      : Benchmark(name), lambda_(std::forward(lam)) {}
-
-  LambdaBenchmark(LambdaBenchmark const&) = delete;
-
-  template   // NOLINTNEXTLINE(readability-redundant-declaration)
-  friend Benchmark* ::benchmark::RegisterBenchmark(const std::string&, Lam&&);
-
-  Lambda lambda_;
-};
-#endif
-}  // namespace internal
-
-inline internal::Benchmark* RegisterBenchmark(const std::string& name,
-                                              internal::Function* fn) {
-  // FIXME: this should be a `std::make_unique<>()` but we don't have C++14.
-  // codechecker_intentional [cplusplus.NewDeleteLeaks]
-  return internal::RegisterBenchmarkInternal(
-      ::new internal::FunctionBenchmark(name, fn));
-}
-
-#ifdef BENCHMARK_HAS_CXX11
-template 
-internal::Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn) {
-  using BenchType =
-      internal::LambdaBenchmark::type>;
-  // FIXME: this should be a `std::make_unique<>()` but we don't have C++14.
-  // codechecker_intentional [cplusplus.NewDeleteLeaks]
-  return internal::RegisterBenchmarkInternal(
-      ::new BenchType(name, std::forward(fn)));
-}
-#endif
-
-#if defined(BENCHMARK_HAS_CXX11) && \
-    (!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
-template 
-internal::Benchmark* RegisterBenchmark(const std::string& name, Lambda&& fn,
-                                       Args&&... args) {
-  return benchmark::RegisterBenchmark(
-      name, [=](benchmark::State& st) { fn(st, args...); });
-}
-#else
-#define BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
-#endif
-
-// The base class for all fixture tests.
-class Fixture : public internal::Benchmark {
- public:
-  Fixture() : internal::Benchmark("") {}
-
-  void Run(State& st) BENCHMARK_OVERRIDE {
-    this->SetUp(st);
-    this->BenchmarkCase(st);
-    this->TearDown(st);
-  }
-
-  // These will be deprecated ...
-  virtual void SetUp(const State&) {}
-  virtual void TearDown(const State&) {}
-  // ... In favor of these.
-  virtual void SetUp(State& st) { SetUp(const_cast(st)); }
-  virtual void TearDown(State& st) { TearDown(const_cast(st)); }
-
- protected:
-  virtual void BenchmarkCase(State&) = 0;
-};
-}  // namespace benchmark
-
-// ------------------------------------------------------
-// Macro to register benchmarks
-
-// Check that __COUNTER__ is defined and that __COUNTER__ increases by 1
-// every time it is expanded. X + 1 == X + 0 is used in case X is defined to be
-// empty. If X is empty the expression becomes (+1 == +0).
-#if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0)
-#define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__
-#else
-#define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__
-#endif
-
-// Helpers for generating unique variable names
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK_PRIVATE_NAME(...)                                      \
-  BENCHMARK_PRIVATE_CONCAT(benchmark_uniq_, BENCHMARK_PRIVATE_UNIQUE_ID, \
-                           __VA_ARGS__)
-#else
-#define BENCHMARK_PRIVATE_NAME(n) \
-  BENCHMARK_PRIVATE_CONCAT(benchmark_uniq_, BENCHMARK_PRIVATE_UNIQUE_ID, n)
-#endif  // BENCHMARK_HAS_CXX11
-
-#define BENCHMARK_PRIVATE_CONCAT(a, b, c) BENCHMARK_PRIVATE_CONCAT2(a, b, c)
-#define BENCHMARK_PRIVATE_CONCAT2(a, b, c) a##b##c
-// Helper for concatenation with macro name expansion
-#define BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method) \
-  BaseClass##_##Method##_Benchmark
-
-#define BENCHMARK_PRIVATE_DECLARE(n)                                 \
-  static ::benchmark::internal::Benchmark* BENCHMARK_PRIVATE_NAME(n) \
-      BENCHMARK_UNUSED
-
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK(...)                                               \
-  BENCHMARK_PRIVATE_DECLARE(_benchmark_) =                           \
-      (::benchmark::internal::RegisterBenchmarkInternal(             \
-          new ::benchmark::internal::FunctionBenchmark(#__VA_ARGS__, \
-                                                       __VA_ARGS__)))
-#else
-#define BENCHMARK(n)                                     \
-  BENCHMARK_PRIVATE_DECLARE(n) =                         \
-      (::benchmark::internal::RegisterBenchmarkInternal( \
-          new ::benchmark::internal::FunctionBenchmark(#n, n)))
-#endif  // BENCHMARK_HAS_CXX11
-
-// Old-style macros
-#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
-#define BENCHMARK_WITH_ARG2(n, a1, a2) BENCHMARK(n)->Args({(a1), (a2)})
-#define BENCHMARK_WITH_UNIT(n, t) BENCHMARK(n)->Unit((t))
-#define BENCHMARK_RANGE(n, lo, hi) BENCHMARK(n)->Range((lo), (hi))
-#define BENCHMARK_RANGE2(n, l1, h1, l2, h2) \
-  BENCHMARK(n)->RangePair({{(l1), (h1)}, {(l2), (h2)}})
-
-#ifdef BENCHMARK_HAS_CXX11
-
-// Register a benchmark which invokes the function specified by `func`
-// with the additional arguments specified by `...`.
-//
-// For example:
-//
-// template `
-// void BM_takes_args(benchmark::State& state, ExtraArgs&&... extra_args) {
-//  [...]
-//}
-// /* Registers a benchmark named "BM_takes_args/int_string_test` */
-// BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
-#define BENCHMARK_CAPTURE(func, test_case_name, ...)     \
-  BENCHMARK_PRIVATE_DECLARE(_benchmark_) =               \
-      (::benchmark::internal::RegisterBenchmarkInternal( \
-          new ::benchmark::internal::FunctionBenchmark(  \
-              #func "/" #test_case_name,                 \
-              [](::benchmark::State& st) { func(st, __VA_ARGS__); })))
-
-#endif  // BENCHMARK_HAS_CXX11
-
-// This will register a benchmark for a templatized function.  For example:
-//
-// template
-// void BM_Foo(int iters);
-//
-// BENCHMARK_TEMPLATE(BM_Foo, 1);
-//
-// will register BM_Foo<1> as a benchmark.
-#define BENCHMARK_TEMPLATE1(n, a)                        \
-  BENCHMARK_PRIVATE_DECLARE(n) =                         \
-      (::benchmark::internal::RegisterBenchmarkInternal( \
-          new ::benchmark::internal::FunctionBenchmark(#n "<" #a ">", n)))
-
-#define BENCHMARK_TEMPLATE2(n, a, b)                                         \
-  BENCHMARK_PRIVATE_DECLARE(n) =                                             \
-      (::benchmark::internal::RegisterBenchmarkInternal(                     \
-          new ::benchmark::internal::FunctionBenchmark(#n "<" #a "," #b ">", \
-                                                       n)))
-
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK_TEMPLATE(n, ...)                       \
-  BENCHMARK_PRIVATE_DECLARE(n) =                         \
-      (::benchmark::internal::RegisterBenchmarkInternal( \
-          new ::benchmark::internal::FunctionBenchmark(  \
-              #n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
-#else
-#define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a)
-#endif
-
-#ifdef BENCHMARK_HAS_CXX11
-// This will register a benchmark for a templatized function,
-// with the additional arguments specified by `...`.
-//
-// For example:
-//
-// template `
-// void BM_takes_args(benchmark::State& state, ExtraArgs&&... extra_args) {
-//  [...]
-//}
-// /* Registers a benchmark named "BM_takes_args/int_string_test` */
-// BENCHMARK_TEMPLATE1_CAPTURE(BM_takes_args, void, int_string_test, 42,
-//                             std::string("abc"));
-#define BENCHMARK_TEMPLATE1_CAPTURE(func, a, test_case_name, ...) \
-  BENCHMARK_CAPTURE(func, test_case_name, __VA_ARGS__)
-
-#define BENCHMARK_TEMPLATE2_CAPTURE(func, a, b, test_case_name, ...) \
-  BENCHMARK_PRIVATE_DECLARE(func) =                                  \
-      (::benchmark::internal::RegisterBenchmarkInternal(             \
-          new ::benchmark::internal::FunctionBenchmark(              \
-              #func "<" #a "," #b ">"                                \
-                    "/" #test_case_name,                             \
-              [](::benchmark::State& st) { func(st, __VA_ARGS__); })))
-#endif  // BENCHMARK_HAS_CXX11
-
-#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method)          \
-  class BaseClass##_##Method##_Benchmark : public BaseClass {   \
-   public:                                                      \
-    BaseClass##_##Method##_Benchmark() {                        \
-      this->SetName(#BaseClass "/" #Method);                    \
-    }                                                           \
-                                                                \
-   protected:                                                   \
-    void BenchmarkCase(::benchmark::State&) BENCHMARK_OVERRIDE; \
-  };
-
-#define BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
-  class BaseClass##_##Method##_Benchmark : public BaseClass {    \
-   public:                                                          \
-    BaseClass##_##Method##_Benchmark() {                            \
-      this->SetName(#BaseClass "<" #a ">/" #Method);                \
-    }                                                               \
-                                                                    \
-   protected:                                                       \
-    void BenchmarkCase(::benchmark::State&) BENCHMARK_OVERRIDE;     \
-  };
-
-#define BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
-  class BaseClass##_##Method##_Benchmark : public BaseClass {    \
-   public:                                                             \
-    BaseClass##_##Method##_Benchmark() {                               \
-      this->SetName(#BaseClass "<" #a "," #b ">/" #Method);            \
-    }                                                                  \
-                                                                       \
-   protected:                                                          \
-    void BenchmarkCase(::benchmark::State&) BENCHMARK_OVERRIDE;        \
-  };
-
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, ...)       \
-  class BaseClass##_##Method##_Benchmark : public BaseClass<__VA_ARGS__> { \
-   public:                                                                 \
-    BaseClass##_##Method##_Benchmark() {                                   \
-      this->SetName(#BaseClass "<" #__VA_ARGS__ ">/" #Method);             \
-    }                                                                      \
-                                                                           \
-   protected:                                                              \
-    void BenchmarkCase(::benchmark::State&) BENCHMARK_OVERRIDE;            \
-  };
-#else
-#define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(n, a) \
-  BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(n, a)
-#endif
-
-#define BENCHMARK_DEFINE_F(BaseClass, Method)    \
-  BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
-  void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a)    \
-  BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
-  void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE2_DEFINE_F(BaseClass, Method, a, b)    \
-  BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
-  void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, ...)            \
-  BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
-  void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-#else
-#define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, a) \
-  BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a)
-#endif
-
-#define BENCHMARK_REGISTER_F(BaseClass, Method) \
-  BENCHMARK_PRIVATE_REGISTER_F(BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method))
-
-#define BENCHMARK_PRIVATE_REGISTER_F(TestName) \
-  BENCHMARK_PRIVATE_DECLARE(TestName) =        \
-      (::benchmark::internal::RegisterBenchmarkInternal(new TestName()))
-
-// This macro will define and register a benchmark within a fixture class.
-#define BENCHMARK_F(BaseClass, Method)           \
-  BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
-  BENCHMARK_REGISTER_F(BaseClass, Method);       \
-  void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE1_F(BaseClass, Method, a)           \
-  BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
-  BENCHMARK_REGISTER_F(BaseClass, Method);                    \
-  void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE2_F(BaseClass, Method, a, b)           \
-  BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
-  BENCHMARK_REGISTER_F(BaseClass, Method);                       \
-  void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK_TEMPLATE_F(BaseClass, Method, ...)                   \
-  BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
-  BENCHMARK_REGISTER_F(BaseClass, Method);                             \
-  void BENCHMARK_PRIVATE_CONCAT_NAME(BaseClass, Method)::BenchmarkCase
-#else
-#define BENCHMARK_TEMPLATE_F(BaseClass, Method, a) \
-  BENCHMARK_TEMPLATE1_F(BaseClass, Method, a)
-#endif
-
-// Helper macro to create a main routine in a test that runs the benchmarks
-// Note the workaround for Hexagon simulator passing argc != 0, argv = NULL.
-#define BENCHMARK_MAIN()                                                \
-  int main(int argc, char** argv) {                                     \
-    char arg0_default[] = "benchmark";                                  \
-    char* args_default = arg0_default;                                  \
-    if (!argv) {                                                        \
-      argc = 1;                                                         \
-      argv = &args_default;                                             \
-    }                                                                   \
-    ::benchmark::Initialize(&argc, argv);                               \
-    if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; \
-    ::benchmark::RunSpecifiedBenchmarks();                              \
-    ::benchmark::Shutdown();                                            \
-    return 0;                                                           \
-  }                                                                     \
-  int main(int, char**)
-
-// ------------------------------------------------------
-// Benchmark Reporters
-
-namespace benchmark {
-
-struct BENCHMARK_EXPORT CPUInfo {
-  struct CacheInfo {
-    std::string type;
-    int level;
-    int size;
-    int num_sharing;
-  };
-
-  enum Scaling { UNKNOWN, ENABLED, DISABLED };
-
-  int num_cpus;
-  Scaling scaling;
-  double cycles_per_second;
-  std::vector caches;
-  std::vector load_avg;
-
-  static const CPUInfo& Get();
-
- private:
-  CPUInfo();
-  BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo);
-};
-
-// Adding Struct for System Information
-struct BENCHMARK_EXPORT SystemInfo {
-  std::string name;
-  static const SystemInfo& Get();
-
- private:
-  SystemInfo();
-  BENCHMARK_DISALLOW_COPY_AND_ASSIGN(SystemInfo);
-};
-
-// BenchmarkName contains the components of the Benchmark's name
-// which allows individual fields to be modified or cleared before
-// building the final name using 'str()'.
-struct BENCHMARK_EXPORT BenchmarkName {
-  std::string function_name;
-  std::string args;
-  std::string min_time;
-  std::string min_warmup_time;
-  std::string iterations;
-  std::string repetitions;
-  std::string time_type;
-  std::string threads;
-
-  // Return the full name of the benchmark with each non-empty
-  // field separated by a '/'
-  std::string str() const;
-};
-
-// Interface for custom benchmark result printers.
-// By default, benchmark reports are printed to stdout. However an application
-// can control the destination of the reports by calling
-// RunSpecifiedBenchmarks and passing it a custom reporter object.
-// The reporter object must implement the following interface.
-class BENCHMARK_EXPORT BenchmarkReporter {
- public:
-  struct Context {
-    CPUInfo const& cpu_info;
-    SystemInfo const& sys_info;
-    // The number of chars in the longest benchmark name.
-    size_t name_field_width;
-    static const char* executable_name;
-    Context();
-  };
-
-  struct BENCHMARK_EXPORT Run {
-    static const int64_t no_repetition_index = -1;
-    enum RunType { RT_Iteration, RT_Aggregate };
-
-    Run()
-        : run_type(RT_Iteration),
-          aggregate_unit(kTime),
-          skipped(internal::NotSkipped),
-          iterations(1),
-          threads(1),
-          time_unit(GetDefaultTimeUnit()),
-          real_accumulated_time(0),
-          cpu_accumulated_time(0),
-          max_heapbytes_used(0),
-          use_real_time_for_initial_big_o(false),
-          complexity(oNone),
-          complexity_lambda(),
-          complexity_n(0),
-          report_big_o(false),
-          report_rms(false),
-          memory_result(NULL),
-          allocs_per_iter(0.0) {}
-
-    std::string benchmark_name() const;
-    BenchmarkName run_name;
-    int64_t family_index;
-    int64_t per_family_instance_index;
-    RunType run_type;
-    std::string aggregate_name;
-    StatisticUnit aggregate_unit;
-    std::string report_label;  // Empty if not set by benchmark.
-    internal::Skipped skipped;
-    std::string skip_message;
-
-    IterationCount iterations;
-    int64_t threads;
-    int64_t repetition_index;
-    int64_t repetitions;
-    TimeUnit time_unit;
-    double real_accumulated_time;
-    double cpu_accumulated_time;
-
-    // Return a value representing the real time per iteration in the unit
-    // specified by 'time_unit'.
-    // NOTE: If 'iterations' is zero the returned value represents the
-    // accumulated time.
-    double GetAdjustedRealTime() const;
-
-    // Return a value representing the cpu time per iteration in the unit
-    // specified by 'time_unit'.
-    // NOTE: If 'iterations' is zero the returned value represents the
-    // accumulated time.
-    double GetAdjustedCPUTime() const;
-
-    // This is set to 0.0 if memory tracing is not enabled.
-    double max_heapbytes_used;
-
-    // By default Big-O is computed for CPU time, but that is not what you want
-    // to happen when manual time was requested, which is stored as real time.
-    bool use_real_time_for_initial_big_o;
-
-    // Keep track of arguments to compute asymptotic complexity
-    BigO complexity;
-    BigOFunc* complexity_lambda;
-    ComplexityN complexity_n;
-
-    // what statistics to compute from the measurements
-    const std::vector* statistics;
-
-    // Inform print function whether the current run is a complexity report
-    bool report_big_o;
-    bool report_rms;
-
-    UserCounters counters;
-
-    // Memory metrics.
-    const MemoryManager::Result* memory_result;
-    double allocs_per_iter;
-  };
-
-  struct PerFamilyRunReports {
-    PerFamilyRunReports() : num_runs_total(0), num_runs_done(0) {}
-
-    // How many runs will all instances of this benchmark perform?
-    int num_runs_total;
-
-    // How many runs have happened already?
-    int num_runs_done;
-
-    // The reports about (non-errneous!) runs of this family.
-    std::vector Runs;
-  };
-
-  // Construct a BenchmarkReporter with the output stream set to 'std::cout'
-  // and the error stream set to 'std::cerr'
-  BenchmarkReporter();
-
-  // Called once for every suite of benchmarks run.
-  // The parameter "context" contains information that the
-  // reporter may wish to use when generating its report, for example the
-  // platform under which the benchmarks are running. The benchmark run is
-  // never started if this function returns false, allowing the reporter
-  // to skip runs based on the context information.
-  virtual bool ReportContext(const Context& context) = 0;
-
-  // Called once for each group of benchmark runs, gives information about
-  // the configurations of the runs.
-  virtual void ReportRunsConfig(double /*min_time*/,
-                                bool /*has_explicit_iters*/,
-                                IterationCount /*iters*/) {}
-
-  // Called once for each group of benchmark runs, gives information about
-  // cpu-time and heap memory usage during the benchmark run. If the group
-  // of runs contained more than two entries then 'report' contains additional
-  // elements representing the mean and standard deviation of those runs.
-  // Additionally if this group of runs was the last in a family of benchmarks
-  // 'reports' contains additional entries representing the asymptotic
-  // complexity and RMS of that benchmark family.
-  virtual void ReportRuns(const std::vector& report) = 0;
-
-  // Called once and only once after ever group of benchmarks is run and
-  // reported.
-  virtual void Finalize() {}
-
-  // REQUIRES: The object referenced by 'out' is valid for the lifetime
-  // of the reporter.
-  void SetOutputStream(std::ostream* out) {
-    assert(out);
-    output_stream_ = out;
-  }
-
-  // REQUIRES: The object referenced by 'err' is valid for the lifetime
-  // of the reporter.
-  void SetErrorStream(std::ostream* err) {
-    assert(err);
-    error_stream_ = err;
-  }
-
-  std::ostream& GetOutputStream() const { return *output_stream_; }
-
-  std::ostream& GetErrorStream() const { return *error_stream_; }
-
-  virtual ~BenchmarkReporter();
-
-  // Write a human readable string to 'out' representing the specified
-  // 'context'.
-  // REQUIRES: 'out' is non-null.
-  static void PrintBasicContext(std::ostream* out, Context const& context);
-
- private:
-  std::ostream* output_stream_;
-  std::ostream* error_stream_;
-};
-
-// Simple reporter that outputs benchmark data to the console. This is the
-// default reporter used by RunSpecifiedBenchmarks().
-class BENCHMARK_EXPORT ConsoleReporter : public BenchmarkReporter {
- public:
-  enum OutputOptions {
-    OO_None = 0,
-    OO_Color = 1,
-    OO_Tabular = 2,
-    OO_ColorTabular = OO_Color | OO_Tabular,
-    OO_Defaults = OO_ColorTabular
-  };
-  explicit ConsoleReporter(OutputOptions opts_ = OO_Defaults)
-      : output_options_(opts_), name_field_width_(0), printed_header_(false) {}
-
-  bool ReportContext(const Context& context) BENCHMARK_OVERRIDE;
-  void ReportRuns(const std::vector& reports) BENCHMARK_OVERRIDE;
-
- protected:
-  virtual void PrintRunData(const Run& report);
-  virtual void PrintHeader(const Run& report);
-
-  OutputOptions output_options_;
-  size_t name_field_width_;
-  UserCounters prev_counters_;
-  bool printed_header_;
-};
-
-class BENCHMARK_EXPORT JSONReporter : public BenchmarkReporter {
- public:
-  JSONReporter() : first_report_(true) {}
-  bool ReportContext(const Context& context) BENCHMARK_OVERRIDE;
-  void ReportRuns(const std::vector& reports) BENCHMARK_OVERRIDE;
-  void Finalize() BENCHMARK_OVERRIDE;
-
- private:
-  void PrintRunData(const Run& report);
-
-  bool first_report_;
-};
-
-class BENCHMARK_EXPORT BENCHMARK_DEPRECATED_MSG(
-    "The CSV Reporter will be removed in a future release") CSVReporter
-    : public BenchmarkReporter {
- public:
-  CSVReporter() : printed_header_(false) {}
-  bool ReportContext(const Context& context) BENCHMARK_OVERRIDE;
-  void ReportRuns(const std::vector& reports) BENCHMARK_OVERRIDE;
-
- private:
-  void PrintRunData(const Run& report);
-
-  bool printed_header_;
-  std::set user_counter_names_;
-};
-
-inline const char* GetTimeUnitString(TimeUnit unit) {
-  switch (unit) {
-    case kSecond:
-      return "s";
-    case kMillisecond:
-      return "ms";
-    case kMicrosecond:
-      return "us";
-    case kNanosecond:
-      return "ns";
-  }
-  BENCHMARK_UNREACHABLE();
-}
-
-inline double GetTimeUnitMultiplier(TimeUnit unit) {
-  switch (unit) {
-    case kSecond:
-      return 1;
-    case kMillisecond:
-      return 1e3;
-    case kMicrosecond:
-      return 1e6;
-    case kNanosecond:
-      return 1e9;
-  }
-  BENCHMARK_UNREACHABLE();
-}
-
-// Creates a list of integer values for the given range and multiplier.
-// This can be used together with ArgsProduct() to allow multiple ranges
-// with different multipliers.
-// Example:
-// ArgsProduct({
-//   CreateRange(0, 1024, /*multi=*/32),
-//   CreateRange(0, 100, /*multi=*/4),
-//   CreateDenseRange(0, 4, /*step=*/1),
-// });
-BENCHMARK_EXPORT
-std::vector CreateRange(int64_t lo, int64_t hi, int multi);
-
-// Creates a list of integer values for the given range and step.
-BENCHMARK_EXPORT
-std::vector CreateDenseRange(int64_t start, int64_t limit, int step);
-
-}  // namespace benchmark
-
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
-
-#endif  // BENCHMARK_BENCHMARK_H_
diff --git a/vendor/core/vendor/googlebenchmark/include/benchmark/export.h b/vendor/core/vendor/googlebenchmark/include/benchmark/export.h
deleted file mode 100644
index f96f8596c..000000000
--- a/vendor/core/vendor/googlebenchmark/include/benchmark/export.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef BENCHMARK_EXPORT_H
-#define BENCHMARK_EXPORT_H
-
-#if defined(_WIN32)
-#define EXPORT_ATTR __declspec(dllexport)
-#define IMPORT_ATTR __declspec(dllimport)
-#define NO_EXPORT_ATTR
-#define DEPRECATED_ATTR __declspec(deprecated)
-#else  // _WIN32
-#define EXPORT_ATTR __attribute__((visibility("default")))
-#define IMPORT_ATTR __attribute__((visibility("default")))
-#define NO_EXPORT_ATTR __attribute__((visibility("hidden")))
-#define DEPRECATE_ATTR __attribute__((__deprecated__))
-#endif  // _WIN32
-
-#ifdef BENCHMARK_STATIC_DEFINE
-#define BENCHMARK_EXPORT
-#define BENCHMARK_NO_EXPORT
-#else  // BENCHMARK_STATIC_DEFINE
-#ifndef BENCHMARK_EXPORT
-#ifdef benchmark_EXPORTS
-/* We are building this library */
-#define BENCHMARK_EXPORT EXPORT_ATTR
-#else  // benchmark_EXPORTS
-/* We are using this library */
-#define BENCHMARK_EXPORT IMPORT_ATTR
-#endif  // benchmark_EXPORTS
-#endif  // !BENCHMARK_EXPORT
-
-#ifndef BENCHMARK_NO_EXPORT
-#define BENCHMARK_NO_EXPORT NO_EXPORT_ATTR
-#endif  // !BENCHMARK_NO_EXPORT
-#endif  // BENCHMARK_STATIC_DEFINE
-
-#ifndef BENCHMARK_DEPRECATED
-#define BENCHMARK_DEPRECATED DEPRECATE_ATTR
-#endif  // BENCHMARK_DEPRECATED
-
-#ifndef BENCHMARK_DEPRECATED_EXPORT
-#define BENCHMARK_DEPRECATED_EXPORT BENCHMARK_EXPORT BENCHMARK_DEPRECATED
-#endif  // BENCHMARK_DEPRECATED_EXPORT
-
-#ifndef BENCHMARK_DEPRECATED_NO_EXPORT
-#define BENCHMARK_DEPRECATED_NO_EXPORT BENCHMARK_NO_EXPORT BENCHMARK_DEPRECATED
-#endif  // BENCHMARK_DEPRECATED_EXPORT
-
-#endif /* BENCHMARK_EXPORT_H */
diff --git a/vendor/core/vendor/googlebenchmark/src/CMakeLists.txt b/vendor/core/vendor/googlebenchmark/src/CMakeLists.txt
deleted file mode 100644
index 32126c0d2..000000000
--- a/vendor/core/vendor/googlebenchmark/src/CMakeLists.txt
+++ /dev/null
@@ -1,180 +0,0 @@
-#Allow the source files to find headers in src /
-include(GNUInstallDirs)
-include_directories(${PROJECT_SOURCE_DIR}/src)
-
-if (DEFINED BENCHMARK_CXX_LINKER_FLAGS)
-  list(APPEND CMAKE_SHARED_LINKER_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
-  list(APPEND CMAKE_MODULE_LINKER_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
-endif()
-
-file(GLOB
-  SOURCE_FILES
-    *.cc
-    ${PROJECT_SOURCE_DIR}/include/benchmark/*.h
-    ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
-file(GLOB BENCHMARK_MAIN "benchmark_main.cc")
-foreach(item ${BENCHMARK_MAIN})
-  list(REMOVE_ITEM SOURCE_FILES "${item}")
-endforeach()
-
-add_library(benchmark ${SOURCE_FILES})
-add_library(benchmark::benchmark ALIAS benchmark)
-set_target_properties(benchmark PROPERTIES
-  OUTPUT_NAME "benchmark"
-  VERSION ${GENERIC_LIB_VERSION}
-  SOVERSION ${GENERIC_LIB_SOVERSION}
-)
-target_include_directories(benchmark PUBLIC
-  $
-)
-
-set_property(
-  SOURCE benchmark.cc
-  APPEND
-  PROPERTY COMPILE_DEFINITIONS
-  BENCHMARK_VERSION="${VERSION}"
-)
-
-# libpfm, if available
-if (PFM_FOUND)
-  target_link_libraries(benchmark PRIVATE PFM::libpfm)
-  target_compile_definitions(benchmark PRIVATE -DHAVE_LIBPFM)
-endif()
-
-# pthread affinity, if available
-if(HAVE_PTHREAD_AFFINITY)
-  target_compile_definitions(benchmark PRIVATE -DBENCHMARK_HAS_PTHREAD_AFFINITY)
-endif()
-
-# Link threads.
-target_link_libraries(benchmark PRIVATE Threads::Threads)
-
-target_link_libraries(benchmark PRIVATE ${BENCHMARK_CXX_LIBRARIES})
-
-if(HAVE_LIB_RT)
-  target_link_libraries(benchmark PRIVATE rt)
-endif(HAVE_LIB_RT)
-
-
-# We need extra libraries on Windows
-if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
-  target_link_libraries(benchmark PRIVATE shlwapi)
-endif()
-
-# We need extra libraries on Solaris
-if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
-  target_link_libraries(benchmark PRIVATE kstat)
-  set(BENCHMARK_PRIVATE_LINK_LIBRARIES -lkstat)
-endif()
-
-if (NOT BUILD_SHARED_LIBS)
-  target_compile_definitions(benchmark PUBLIC -DBENCHMARK_STATIC_DEFINE)
-endif()
-
-# Benchmark main library
-add_library(benchmark_main "benchmark_main.cc")
-add_library(benchmark::benchmark_main ALIAS benchmark_main)
-set_target_properties(benchmark_main PROPERTIES
-  OUTPUT_NAME "benchmark_main"
-  VERSION ${GENERIC_LIB_VERSION}
-  SOVERSION ${GENERIC_LIB_SOVERSION}
-  DEFINE_SYMBOL benchmark_EXPORTS
-)
-target_link_libraries(benchmark_main PUBLIC benchmark::benchmark)
-
-set(generated_dir "${PROJECT_BINARY_DIR}")
-
-set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
-set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
-set(pkg_config "${generated_dir}/${PROJECT_NAME}.pc")
-set(pkg_config_main "${generated_dir}/${PROJECT_NAME}_main.pc")
-set(targets_to_export benchmark benchmark_main)
-set(targets_export_name "${PROJECT_NAME}Targets")
-
-set(namespace "${PROJECT_NAME}::")
-
-include(CMakePackageConfigHelpers)
-
-configure_package_config_file (
-  ${PROJECT_SOURCE_DIR}/cmake/Config.cmake.in
-  ${project_config}
-  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
-  NO_SET_AND_CHECK_MACRO
-  NO_CHECK_REQUIRED_COMPONENTS_MACRO
-)
-write_basic_package_version_file(
-  "${version_config}" VERSION ${GENERIC_LIB_VERSION} COMPATIBILITY SameMajorVersion
-)
-
-configure_file("${PROJECT_SOURCE_DIR}/cmake/benchmark.pc.in" "${pkg_config}" @ONLY)
-configure_file("${PROJECT_SOURCE_DIR}/cmake/benchmark_main.pc.in" "${pkg_config_main}" @ONLY)
-
-export (
-  TARGETS ${targets_to_export}
-  NAMESPACE "${namespace}"
-  FILE ${generated_dir}/${targets_export_name}.cmake
-)
-
-if (BENCHMARK_ENABLE_INSTALL)
-  # Install target (will install the library to specified CMAKE_INSTALL_PREFIX variable)
-  install(
-    TARGETS ${targets_to_export}
-    EXPORT ${targets_export_name}
-    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-    INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-
-  install(
-    DIRECTORY "${PROJECT_SOURCE_DIR}/include/benchmark"
-              "${PROJECT_BINARY_DIR}/include/benchmark"
-    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
-    FILES_MATCHING PATTERN "*.*h")
-
-  install(
-      FILES "${project_config}" "${version_config}"
-      DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
-
-  install(
-      FILES "${pkg_config}" "${pkg_config_main}"
-      DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
-
-  install(
-      EXPORT "${targets_export_name}"
-      NAMESPACE "${namespace}"
-      DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
-endif()
-
-if (BENCHMARK_ENABLE_DOXYGEN)
-  find_package(Doxygen REQUIRED)
-  set(DOXYGEN_QUIET YES)
-  set(DOXYGEN_RECURSIVE YES)
-  set(DOXYGEN_GENERATE_HTML YES)
-  set(DOXYGEN_GENERATE_MAN NO)
-  set(DOXYGEN_MARKDOWN_SUPPORT YES)
-  set(DOXYGEN_BUILTIN_STL_SUPPORT YES)
-  set(DOXYGEN_EXTRACT_PACKAGE YES)
-  set(DOXYGEN_EXTRACT_STATIC YES)
-  set(DOXYGEN_SHOW_INCLUDE_FILES YES)
-  set(DOXYGEN_BINARY_TOC YES)
-  set(DOXYGEN_TOC_EXPAND YES)
-  set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "index.md")
-  doxygen_add_docs(benchmark_doxygen
-    docs
-    include
-    src
-    ALL
-    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-    COMMENT "Building documentation with Doxygen.")
-  if (BENCHMARK_ENABLE_INSTALL AND BENCHMARK_INSTALL_DOCS)
-    install(
-      DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html/"
-      DESTINATION ${CMAKE_INSTALL_DOCDIR})
-  endif()
-else()
-  if (BENCHMARK_ENABLE_INSTALL AND BENCHMARK_INSTALL_DOCS)
-    install(
-      DIRECTORY "${PROJECT_SOURCE_DIR}/docs/"
-      DESTINATION ${CMAKE_INSTALL_DOCDIR})
-  endif()
-endif()
diff --git a/vendor/core/vendor/googlebenchmark/src/arraysize.h b/vendor/core/vendor/googlebenchmark/src/arraysize.h
deleted file mode 100644
index 51a50f2df..000000000
--- a/vendor/core/vendor/googlebenchmark/src/arraysize.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef BENCHMARK_ARRAYSIZE_H_
-#define BENCHMARK_ARRAYSIZE_H_
-
-#include "internal_macros.h"
-
-namespace benchmark {
-namespace internal {
-// The arraysize(arr) macro returns the # of elements in an array arr.
-// The expression is a compile-time constant, and therefore can be
-// used in defining new arrays, for example.  If you use arraysize on
-// a pointer by mistake, you will get a compile-time error.
-//
-
-// This template function declaration is used in defining arraysize.
-// Note that the function doesn't need an implementation, as we only
-// use its type.
-template 
-char (&ArraySizeHelper(T (&array)[N]))[N];
-
-// That gcc wants both of these prototypes seems mysterious. VC, for
-// its part, can't decide which to use (another mystery). Matching of
-// template overloads: the final frontier.
-#ifndef COMPILER_MSVC
-template 
-char (&ArraySizeHelper(const T (&array)[N]))[N];
-#endif
-
-#define arraysize(array) (sizeof(::benchmark::internal::ArraySizeHelper(array)))
-
-}  // end namespace internal
-}  // end namespace benchmark
-
-#endif  // BENCHMARK_ARRAYSIZE_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/benchmark.cc b/vendor/core/vendor/googlebenchmark/src/benchmark.cc
deleted file mode 100644
index 2d085447b..000000000
--- a/vendor/core/vendor/googlebenchmark/src/benchmark.cc
+++ /dev/null
@@ -1,812 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark/benchmark.h"
-
-#include "benchmark_api_internal.h"
-#include "benchmark_runner.h"
-#include "internal_macros.h"
-
-#ifndef BENCHMARK_OS_WINDOWS
-#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
-#include 
-#endif
-#include 
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "check.h"
-#include "colorprint.h"
-#include "commandlineflags.h"
-#include "complexity.h"
-#include "counter.h"
-#include "internal_macros.h"
-#include "log.h"
-#include "mutex.h"
-#include "perf_counters.h"
-#include "re.h"
-#include "statistics.h"
-#include "string_util.h"
-#include "thread_manager.h"
-#include "thread_timer.h"
-
-namespace benchmark {
-// Print a list of benchmarks. This option overrides all other options.
-BM_DEFINE_bool(benchmark_list_tests, false);
-
-// A regular expression that specifies the set of benchmarks to execute.  If
-// this flag is empty, or if this flag is the string \"all\", all benchmarks
-// linked into the binary are run.
-BM_DEFINE_string(benchmark_filter, "");
-
-// Specification of how long to run the benchmark.
-//
-// It can be either an exact number of iterations (specified as `x`),
-// or a minimum number of seconds (specified as `s`). If the latter
-// format (ie., min seconds) is used, the system may run the benchmark longer
-// until the results are considered significant.
-//
-// For backward compatibility, the `s` suffix may be omitted, in which case,
-// the specified number is interpreted as the number of seconds.
-//
-// For cpu-time based tests, this is the lower bound
-// on the total cpu time used by all threads that make up the test.  For
-// real-time based tests, this is the lower bound on the elapsed time of the
-// benchmark execution, regardless of number of threads.
-BM_DEFINE_string(benchmark_min_time, kDefaultMinTimeStr);
-
-// Minimum number of seconds a benchmark should be run before results should be
-// taken into account. This e.g can be necessary for benchmarks of code which
-// needs to fill some form of cache before performance is of interest.
-// Note: results gathered within this period are discarded and not used for
-// reported result.
-BM_DEFINE_double(benchmark_min_warmup_time, 0.0);
-
-// The number of runs of each benchmark. If greater than 1, the mean and
-// standard deviation of the runs will be reported.
-BM_DEFINE_int32(benchmark_repetitions, 1);
-
-// If set, enable random interleaving of repetitions of all benchmarks.
-// See http://github.com/google/benchmark/issues/1051 for details.
-BM_DEFINE_bool(benchmark_enable_random_interleaving, false);
-
-// Report the result of each benchmark repetitions. When 'true' is specified
-// only the mean, standard deviation, and other statistics are reported for
-// repeated benchmarks. Affects all reporters.
-BM_DEFINE_bool(benchmark_report_aggregates_only, false);
-
-// Display the result of each benchmark repetitions. When 'true' is specified
-// only the mean, standard deviation, and other statistics are displayed for
-// repeated benchmarks. Unlike benchmark_report_aggregates_only, only affects
-// the display reporter, but  *NOT* file reporter, which will still contain
-// all the output.
-BM_DEFINE_bool(benchmark_display_aggregates_only, false);
-
-// The format to use for console output.
-// Valid values are 'console', 'json', or 'csv'.
-BM_DEFINE_string(benchmark_format, "console");
-
-// The format to use for file output.
-// Valid values are 'console', 'json', or 'csv'.
-BM_DEFINE_string(benchmark_out_format, "json");
-
-// The file to write additional output to.
-BM_DEFINE_string(benchmark_out, "");
-
-// Whether to use colors in the output.  Valid values:
-// 'true'/'yes'/1, 'false'/'no'/0, and 'auto'. 'auto' means to use colors if
-// the output is being sent to a terminal and the TERM environment variable is
-// set to a terminal type that supports colors.
-BM_DEFINE_string(benchmark_color, "auto");
-
-// Whether to use tabular format when printing user counters to the console.
-// Valid values: 'true'/'yes'/1, 'false'/'no'/0.  Defaults to false.
-BM_DEFINE_bool(benchmark_counters_tabular, false);
-
-// List of additional perf counters to collect, in libpfm format. For more
-// information about libpfm: https://man7.org/linux/man-pages/man3/libpfm.3.html
-BM_DEFINE_string(benchmark_perf_counters, "");
-
-// Extra context to include in the output formatted as comma-separated key-value
-// pairs. Kept internal as it's only used for parsing from env/command line.
-BM_DEFINE_kvpairs(benchmark_context, {});
-
-// Set the default time unit to use for reports
-// Valid values are 'ns', 'us', 'ms' or 's'
-BM_DEFINE_string(benchmark_time_unit, "");
-
-// The level of verbose logging to output
-BM_DEFINE_int32(v, 0);
-
-namespace internal {
-
-std::map* global_context = nullptr;
-
-BENCHMARK_EXPORT std::map*& GetGlobalContext() {
-  return global_context;
-}
-
-static void const volatile* volatile global_force_escape_pointer;
-
-// FIXME: Verify if LTO still messes this up?
-void UseCharPointer(char const volatile* const v) {
-  // We want to escape the pointer `v` so that the compiler can not eliminate
-  // computations that produced it. To do that, we escape the pointer by storing
-  // it into a volatile variable, since generally, volatile store, is not
-  // something the compiler is allowed to elide.
-  global_force_escape_pointer = reinterpret_cast(v);
-}
-
-}  // namespace internal
-
-State::State(std::string name, IterationCount max_iters,
-             const std::vector& ranges, int thread_i, int n_threads,
-             internal::ThreadTimer* timer, internal::ThreadManager* manager,
-             internal::PerfCountersMeasurement* perf_counters_measurement)
-    : total_iterations_(0),
-      batch_leftover_(0),
-      max_iterations(max_iters),
-      started_(false),
-      finished_(false),
-      skipped_(internal::NotSkipped),
-      range_(ranges),
-      complexity_n_(0),
-      name_(std::move(name)),
-      thread_index_(thread_i),
-      threads_(n_threads),
-      timer_(timer),
-      manager_(manager),
-      perf_counters_measurement_(perf_counters_measurement) {
-  BM_CHECK(max_iterations != 0) << "At least one iteration must be run";
-  BM_CHECK_LT(thread_index_, threads_)
-      << "thread_index must be less than threads";
-
-  // Add counters with correct flag now.  If added with `counters[name]` in
-  // `PauseTiming`, a new `Counter` will be inserted the first time, which
-  // won't have the flag.  Inserting them now also reduces the allocations
-  // during the benchmark.
-  if (perf_counters_measurement_) {
-    for (const std::string& counter_name :
-         perf_counters_measurement_->names()) {
-      counters[counter_name] = Counter(0.0, Counter::kAvgIterations);
-    }
-  }
-
-  // Note: The use of offsetof below is technically undefined until C++17
-  // because State is not a standard layout type. However, all compilers
-  // currently provide well-defined behavior as an extension (which is
-  // demonstrated since constexpr evaluation must diagnose all undefined
-  // behavior). However, GCC and Clang also warn about this use of offsetof,
-  // which must be suppressed.
-#if defined(__INTEL_COMPILER)
-#pragma warning push
-#pragma warning(disable : 1875)
-#elif defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Winvalid-offsetof"
-#endif
-#if defined(__NVCC__)
-#pragma nv_diagnostic push
-#pragma nv_diag_suppress 1427
-#endif
-#if defined(__NVCOMPILER)
-#pragma diagnostic push
-#pragma diag_suppress offset_in_non_POD_nonstandard
-#endif
-  // Offset tests to ensure commonly accessed data is on the first cache line.
-  const int cache_line_size = 64;
-  static_assert(
-      offsetof(State, skipped_) <= (cache_line_size - sizeof(skipped_)), "");
-#if defined(__INTEL_COMPILER)
-#pragma warning pop
-#elif defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
-#if defined(__NVCC__)
-#pragma nv_diagnostic pop
-#endif
-#if defined(__NVCOMPILER)
-#pragma diagnostic pop
-#endif
-}
-
-void State::PauseTiming() {
-  // Add in time accumulated so far
-  BM_CHECK(started_ && !finished_ && !skipped());
-  timer_->StopTimer();
-  if (perf_counters_measurement_) {
-    std::vector> measurements;
-    if (!perf_counters_measurement_->Stop(measurements)) {
-      BM_CHECK(false) << "Perf counters read the value failed.";
-    }
-    for (const auto& name_and_measurement : measurements) {
-      const std::string& name = name_and_measurement.first;
-      const double measurement = name_and_measurement.second;
-      // Counter was inserted with `kAvgIterations` flag by the constructor.
-      assert(counters.find(name) != counters.end());
-      counters[name].value += measurement;
-    }
-  }
-}
-
-void State::ResumeTiming() {
-  BM_CHECK(started_ && !finished_ && !skipped());
-  timer_->StartTimer();
-  if (perf_counters_measurement_) {
-    perf_counters_measurement_->Start();
-  }
-}
-
-void State::SkipWithMessage(const std::string& msg) {
-  skipped_ = internal::SkippedWithMessage;
-  {
-    MutexLock l(manager_->GetBenchmarkMutex());
-    if (internal::NotSkipped == manager_->results.skipped_) {
-      manager_->results.skip_message_ = msg;
-      manager_->results.skipped_ = skipped_;
-    }
-  }
-  total_iterations_ = 0;
-  if (timer_->running()) timer_->StopTimer();
-}
-
-void State::SkipWithError(const std::string& msg) {
-  skipped_ = internal::SkippedWithError;
-  {
-    MutexLock l(manager_->GetBenchmarkMutex());
-    if (internal::NotSkipped == manager_->results.skipped_) {
-      manager_->results.skip_message_ = msg;
-      manager_->results.skipped_ = skipped_;
-    }
-  }
-  total_iterations_ = 0;
-  if (timer_->running()) timer_->StopTimer();
-}
-
-void State::SetIterationTime(double seconds) {
-  timer_->SetIterationTime(seconds);
-}
-
-void State::SetLabel(const std::string& label) {
-  MutexLock l(manager_->GetBenchmarkMutex());
-  manager_->results.report_label_ = label;
-}
-
-void State::StartKeepRunning() {
-  BM_CHECK(!started_ && !finished_);
-  started_ = true;
-  total_iterations_ = skipped() ? 0 : max_iterations;
-  manager_->StartStopBarrier();
-  if (!skipped()) ResumeTiming();
-}
-
-void State::FinishKeepRunning() {
-  BM_CHECK(started_ && (!finished_ || skipped()));
-  if (!skipped()) {
-    PauseTiming();
-  }
-  // Total iterations has now wrapped around past 0. Fix this.
-  total_iterations_ = 0;
-  finished_ = true;
-  manager_->StartStopBarrier();
-}
-
-namespace internal {
-namespace {
-
-// Flushes streams after invoking reporter methods that write to them. This
-// ensures users get timely updates even when streams are not line-buffered.
-void FlushStreams(BenchmarkReporter* reporter) {
-  if (!reporter) return;
-  std::flush(reporter->GetOutputStream());
-  std::flush(reporter->GetErrorStream());
-}
-
-// Reports in both display and file reporters.
-void Report(BenchmarkReporter* display_reporter,
-            BenchmarkReporter* file_reporter, const RunResults& run_results) {
-  auto report_one = [](BenchmarkReporter* reporter, bool aggregates_only,
-                       const RunResults& results) {
-    assert(reporter);
-    // If there are no aggregates, do output non-aggregates.
-    aggregates_only &= !results.aggregates_only.empty();
-    if (!aggregates_only) reporter->ReportRuns(results.non_aggregates);
-    if (!results.aggregates_only.empty())
-      reporter->ReportRuns(results.aggregates_only);
-  };
-
-  report_one(display_reporter, run_results.display_report_aggregates_only,
-             run_results);
-  if (file_reporter)
-    report_one(file_reporter, run_results.file_report_aggregates_only,
-               run_results);
-
-  FlushStreams(display_reporter);
-  FlushStreams(file_reporter);
-}
-
-void RunBenchmarks(const std::vector& benchmarks,
-                   BenchmarkReporter* display_reporter,
-                   BenchmarkReporter* file_reporter) {
-  // Note the file_reporter can be null.
-  BM_CHECK(display_reporter != nullptr);
-
-  // Determine the width of the name field using a minimum width of 10.
-  bool might_have_aggregates = FLAGS_benchmark_repetitions > 1;
-  size_t name_field_width = 10;
-  size_t stat_field_width = 0;
-  for (const BenchmarkInstance& benchmark : benchmarks) {
-    name_field_width =
-        std::max(name_field_width, benchmark.name().str().size());
-    might_have_aggregates |= benchmark.repetitions() > 1;
-
-    for (const auto& Stat : benchmark.statistics())
-      stat_field_width = std::max(stat_field_width, Stat.name_.size());
-  }
-  if (might_have_aggregates) name_field_width += 1 + stat_field_width;
-
-  // Print header here
-  BenchmarkReporter::Context context;
-  context.name_field_width = name_field_width;
-
-  // Keep track of running times of all instances of each benchmark family.
-  std::map
-      per_family_reports;
-
-  if (display_reporter->ReportContext(context) &&
-      (!file_reporter || file_reporter->ReportContext(context))) {
-    FlushStreams(display_reporter);
-    FlushStreams(file_reporter);
-
-    size_t num_repetitions_total = 0;
-
-    // This perfcounters object needs to be created before the runners vector
-    // below so it outlasts their lifetime.
-    PerfCountersMeasurement perfcounters(
-        StrSplit(FLAGS_benchmark_perf_counters, ','));
-
-    // Vector of benchmarks to run
-    std::vector runners;
-    runners.reserve(benchmarks.size());
-
-    // Count the number of benchmarks with threads to warn the user in case
-    // performance counters are used.
-    int benchmarks_with_threads = 0;
-
-    // Loop through all benchmarks
-    for (const BenchmarkInstance& benchmark : benchmarks) {
-      BenchmarkReporter::PerFamilyRunReports* reports_for_family = nullptr;
-      if (benchmark.complexity() != oNone)
-        reports_for_family = &per_family_reports[benchmark.family_index()];
-      benchmarks_with_threads += (benchmark.threads() > 1);
-      runners.emplace_back(benchmark, &perfcounters, reports_for_family);
-      int num_repeats_of_this_instance = runners.back().GetNumRepeats();
-      num_repetitions_total +=
-          static_cast(num_repeats_of_this_instance);
-      if (reports_for_family)
-        reports_for_family->num_runs_total += num_repeats_of_this_instance;
-    }
-    assert(runners.size() == benchmarks.size() && "Unexpected runner count.");
-
-    // The use of performance counters with threads would be unintuitive for
-    // the average user so we need to warn them about this case
-    if ((benchmarks_with_threads > 0) && (perfcounters.num_counters() > 0)) {
-      GetErrorLogInstance()
-          << "***WARNING*** There are " << benchmarks_with_threads
-          << " benchmarks with threads and " << perfcounters.num_counters()
-          << " performance counters were requested. Beware counters will "
-             "reflect the combined usage across all "
-             "threads.\n";
-    }
-
-    std::vector repetition_indices;
-    repetition_indices.reserve(num_repetitions_total);
-    for (size_t runner_index = 0, num_runners = runners.size();
-         runner_index != num_runners; ++runner_index) {
-      const internal::BenchmarkRunner& runner = runners[runner_index];
-      std::fill_n(std::back_inserter(repetition_indices),
-                  runner.GetNumRepeats(), runner_index);
-    }
-    assert(repetition_indices.size() == num_repetitions_total &&
-           "Unexpected number of repetition indexes.");
-
-    if (FLAGS_benchmark_enable_random_interleaving) {
-      std::random_device rd;
-      std::mt19937 g(rd());
-      std::shuffle(repetition_indices.begin(), repetition_indices.end(), g);
-    }
-
-    for (size_t repetition_index : repetition_indices) {
-      internal::BenchmarkRunner& runner = runners[repetition_index];
-      runner.DoOneRepetition();
-      if (runner.HasRepeatsRemaining()) continue;
-      // FIXME: report each repetition separately, not all of them in bulk.
-
-      display_reporter->ReportRunsConfig(
-          runner.GetMinTime(), runner.HasExplicitIters(), runner.GetIters());
-      if (file_reporter)
-        file_reporter->ReportRunsConfig(
-            runner.GetMinTime(), runner.HasExplicitIters(), runner.GetIters());
-
-      RunResults run_results = runner.GetResults();
-
-      // Maybe calculate complexity report
-      if (const auto* reports_for_family = runner.GetReportsForFamily()) {
-        if (reports_for_family->num_runs_done ==
-            reports_for_family->num_runs_total) {
-          auto additional_run_stats = ComputeBigO(reports_for_family->Runs);
-          run_results.aggregates_only.insert(run_results.aggregates_only.end(),
-                                             additional_run_stats.begin(),
-                                             additional_run_stats.end());
-          per_family_reports.erase(
-              static_cast(reports_for_family->Runs.front().family_index));
-        }
-      }
-
-      Report(display_reporter, file_reporter, run_results);
-    }
-  }
-  display_reporter->Finalize();
-  if (file_reporter) file_reporter->Finalize();
-  FlushStreams(display_reporter);
-  FlushStreams(file_reporter);
-}
-
-// Disable deprecated warnings temporarily because we need to reference
-// CSVReporter but don't want to trigger -Werror=-Wdeprecated-declarations
-BENCHMARK_DISABLE_DEPRECATED_WARNING
-
-std::unique_ptr CreateReporter(
-    std::string const& name, ConsoleReporter::OutputOptions output_opts) {
-  typedef std::unique_ptr PtrType;
-  if (name == "console") {
-    return PtrType(new ConsoleReporter(output_opts));
-  }
-  if (name == "json") {
-    return PtrType(new JSONReporter());
-  }
-  if (name == "csv") {
-    return PtrType(new CSVReporter());
-  }
-  std::cerr << "Unexpected format: '" << name << "'\n";
-  std::exit(1);
-}
-
-BENCHMARK_RESTORE_DEPRECATED_WARNING
-
-}  // end namespace
-
-bool IsZero(double n) {
-  return std::abs(n) < std::numeric_limits::epsilon();
-}
-
-ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) {
-  int output_opts = ConsoleReporter::OO_Defaults;
-  auto is_benchmark_color = [force_no_color]() -> bool {
-    if (force_no_color) {
-      return false;
-    }
-    if (FLAGS_benchmark_color == "auto") {
-      return IsColorTerminal();
-    }
-    return IsTruthyFlagValue(FLAGS_benchmark_color);
-  };
-  if (is_benchmark_color()) {
-    output_opts |= ConsoleReporter::OO_Color;
-  } else {
-    output_opts &= ~ConsoleReporter::OO_Color;
-  }
-  if (FLAGS_benchmark_counters_tabular) {
-    output_opts |= ConsoleReporter::OO_Tabular;
-  } else {
-    output_opts &= ~ConsoleReporter::OO_Tabular;
-  }
-  return static_cast(output_opts);
-}
-
-}  // end namespace internal
-
-BenchmarkReporter* CreateDefaultDisplayReporter() {
-  static auto default_display_reporter =
-      internal::CreateReporter(FLAGS_benchmark_format,
-                               internal::GetOutputOptions())
-          .release();
-  return default_display_reporter;
-}
-
-size_t RunSpecifiedBenchmarks() {
-  return RunSpecifiedBenchmarks(nullptr, nullptr, FLAGS_benchmark_filter);
-}
-
-size_t RunSpecifiedBenchmarks(std::string spec) {
-  return RunSpecifiedBenchmarks(nullptr, nullptr, std::move(spec));
-}
-
-size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter) {
-  return RunSpecifiedBenchmarks(display_reporter, nullptr,
-                                FLAGS_benchmark_filter);
-}
-
-size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
-                              std::string spec) {
-  return RunSpecifiedBenchmarks(display_reporter, nullptr, std::move(spec));
-}
-
-size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
-                              BenchmarkReporter* file_reporter) {
-  return RunSpecifiedBenchmarks(display_reporter, file_reporter,
-                                FLAGS_benchmark_filter);
-}
-
-size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
-                              BenchmarkReporter* file_reporter,
-                              std::string spec) {
-  if (spec.empty() || spec == "all")
-    spec = ".";  // Regexp that matches all benchmarks
-
-  // Setup the reporters
-  std::ofstream output_file;
-  std::unique_ptr default_display_reporter;
-  std::unique_ptr default_file_reporter;
-  if (!display_reporter) {
-    default_display_reporter.reset(CreateDefaultDisplayReporter());
-    display_reporter = default_display_reporter.get();
-  }
-  auto& Out = display_reporter->GetOutputStream();
-  auto& Err = display_reporter->GetErrorStream();
-
-  std::string const& fname = FLAGS_benchmark_out;
-  if (fname.empty() && file_reporter) {
-    Err << "A custom file reporter was provided but "
-           "--benchmark_out= was not specified."
-        << std::endl;
-    Out.flush();
-    Err.flush();
-    std::exit(1);
-  }
-  if (!fname.empty()) {
-    output_file.open(fname);
-    if (!output_file.is_open()) {
-      Err << "invalid file name: '" << fname << "'" << std::endl;
-      Out.flush();
-      Err.flush();
-      std::exit(1);
-    }
-    if (!file_reporter) {
-      default_file_reporter = internal::CreateReporter(
-          FLAGS_benchmark_out_format, FLAGS_benchmark_counters_tabular
-                                          ? ConsoleReporter::OO_Tabular
-                                          : ConsoleReporter::OO_None);
-      file_reporter = default_file_reporter.get();
-    }
-    file_reporter->SetOutputStream(&output_file);
-    file_reporter->SetErrorStream(&output_file);
-  }
-
-  std::vector benchmarks;
-  if (!FindBenchmarksInternal(spec, &benchmarks, &Err)) {
-    Out.flush();
-    Err.flush();
-    return 0;
-  }
-
-  if (benchmarks.empty()) {
-    Err << "Failed to match any benchmarks against regex: " << spec << "\n";
-    Out.flush();
-    Err.flush();
-    return 0;
-  }
-
-  if (FLAGS_benchmark_list_tests) {
-    for (auto const& benchmark : benchmarks)
-      Out << benchmark.name().str() << "\n";
-  } else {
-    internal::RunBenchmarks(benchmarks, display_reporter, file_reporter);
-  }
-
-  Out.flush();
-  Err.flush();
-  return benchmarks.size();
-}
-
-namespace {
-// stores the time unit benchmarks use by default
-TimeUnit default_time_unit = kNanosecond;
-}  // namespace
-
-TimeUnit GetDefaultTimeUnit() { return default_time_unit; }
-
-void SetDefaultTimeUnit(TimeUnit unit) { default_time_unit = unit; }
-
-std::string GetBenchmarkFilter() { return FLAGS_benchmark_filter; }
-
-void SetBenchmarkFilter(std::string value) {
-  FLAGS_benchmark_filter = std::move(value);
-}
-
-int32_t GetBenchmarkVerbosity() { return FLAGS_v; }
-
-void RegisterMemoryManager(MemoryManager* manager) {
-  internal::memory_manager = manager;
-}
-
-void RegisterProfilerManager(ProfilerManager* manager) {
-  internal::profiler_manager = manager;
-}
-
-void AddCustomContext(const std::string& key, const std::string& value) {
-  if (internal::global_context == nullptr) {
-    internal::global_context = new std::map();
-  }
-  if (!internal::global_context->emplace(key, value).second) {
-    std::cerr << "Failed to add custom context \"" << key << "\" as it already "
-              << "exists with value \"" << value << "\"\n";
-  }
-}
-
-namespace internal {
-
-void (*HelperPrintf)();
-
-void PrintUsageAndExit() {
-  HelperPrintf();
-  exit(0);
-}
-
-void SetDefaultTimeUnitFromFlag(const std::string& time_unit_flag) {
-  if (time_unit_flag == "s") {
-    return SetDefaultTimeUnit(kSecond);
-  }
-  if (time_unit_flag == "ms") {
-    return SetDefaultTimeUnit(kMillisecond);
-  }
-  if (time_unit_flag == "us") {
-    return SetDefaultTimeUnit(kMicrosecond);
-  }
-  if (time_unit_flag == "ns") {
-    return SetDefaultTimeUnit(kNanosecond);
-  }
-  if (!time_unit_flag.empty()) {
-    PrintUsageAndExit();
-  }
-}
-
-void ParseCommandLineFlags(int* argc, char** argv) {
-  using namespace benchmark;
-  BenchmarkReporter::Context::executable_name =
-      (argc && *argc > 0) ? argv[0] : "unknown";
-  for (int i = 1; argc && i < *argc; ++i) {
-    if (ParseBoolFlag(argv[i], "benchmark_list_tests",
-                      &FLAGS_benchmark_list_tests) ||
-        ParseStringFlag(argv[i], "benchmark_filter", &FLAGS_benchmark_filter) ||
-        ParseStringFlag(argv[i], "benchmark_min_time",
-                        &FLAGS_benchmark_min_time) ||
-        ParseDoubleFlag(argv[i], "benchmark_min_warmup_time",
-                        &FLAGS_benchmark_min_warmup_time) ||
-        ParseInt32Flag(argv[i], "benchmark_repetitions",
-                       &FLAGS_benchmark_repetitions) ||
-        ParseBoolFlag(argv[i], "benchmark_enable_random_interleaving",
-                      &FLAGS_benchmark_enable_random_interleaving) ||
-        ParseBoolFlag(argv[i], "benchmark_report_aggregates_only",
-                      &FLAGS_benchmark_report_aggregates_only) ||
-        ParseBoolFlag(argv[i], "benchmark_display_aggregates_only",
-                      &FLAGS_benchmark_display_aggregates_only) ||
-        ParseStringFlag(argv[i], "benchmark_format", &FLAGS_benchmark_format) ||
-        ParseStringFlag(argv[i], "benchmark_out", &FLAGS_benchmark_out) ||
-        ParseStringFlag(argv[i], "benchmark_out_format",
-                        &FLAGS_benchmark_out_format) ||
-        ParseStringFlag(argv[i], "benchmark_color", &FLAGS_benchmark_color) ||
-        ParseBoolFlag(argv[i], "benchmark_counters_tabular",
-                      &FLAGS_benchmark_counters_tabular) ||
-        ParseStringFlag(argv[i], "benchmark_perf_counters",
-                        &FLAGS_benchmark_perf_counters) ||
-        ParseKeyValueFlag(argv[i], "benchmark_context",
-                          &FLAGS_benchmark_context) ||
-        ParseStringFlag(argv[i], "benchmark_time_unit",
-                        &FLAGS_benchmark_time_unit) ||
-        ParseInt32Flag(argv[i], "v", &FLAGS_v)) {
-      for (int j = i; j != *argc - 1; ++j) argv[j] = argv[j + 1];
-
-      --(*argc);
-      --i;
-    } else if (IsFlag(argv[i], "help")) {
-      PrintUsageAndExit();
-    }
-  }
-  for (auto const* flag :
-       {&FLAGS_benchmark_format, &FLAGS_benchmark_out_format}) {
-    if (*flag != "console" && *flag != "json" && *flag != "csv") {
-      PrintUsageAndExit();
-    }
-  }
-  SetDefaultTimeUnitFromFlag(FLAGS_benchmark_time_unit);
-  if (FLAGS_benchmark_color.empty()) {
-    PrintUsageAndExit();
-  }
-  for (const auto& kv : FLAGS_benchmark_context) {
-    AddCustomContext(kv.first, kv.second);
-  }
-}
-
-int InitializeStreams() {
-  static std::ios_base::Init init;
-  return 0;
-}
-
-}  // end namespace internal
-
-std::string GetBenchmarkVersion() {
-#ifdef BENCHMARK_VERSION
-  return {BENCHMARK_VERSION};
-#else
-  return {""};
-#endif
-}
-
-void PrintDefaultHelp() {
-  fprintf(stdout,
-          "benchmark"
-          " [--benchmark_list_tests={true|false}]\n"
-          "          [--benchmark_filter=]\n"
-          "          [--benchmark_min_time=`x` OR `s` ]\n"
-          "          [--benchmark_min_warmup_time=]\n"
-          "          [--benchmark_repetitions=]\n"
-          "          [--benchmark_enable_random_interleaving={true|false}]\n"
-          "          [--benchmark_report_aggregates_only={true|false}]\n"
-          "          [--benchmark_display_aggregates_only={true|false}]\n"
-          "          [--benchmark_format=]\n"
-          "          [--benchmark_out=]\n"
-          "          [--benchmark_out_format=]\n"
-          "          [--benchmark_color={auto|true|false}]\n"
-          "          [--benchmark_counters_tabular={true|false}]\n"
-#if defined HAVE_LIBPFM
-          "          [--benchmark_perf_counters=,...]\n"
-#endif
-          "          [--benchmark_context==,...]\n"
-          "          [--benchmark_time_unit={ns|us|ms|s}]\n"
-          "          [--v=]\n");
-}
-
-void Initialize(int* argc, char** argv, void (*HelperPrintf)()) {
-  internal::HelperPrintf = HelperPrintf;
-  internal::ParseCommandLineFlags(argc, argv);
-  internal::LogLevel() = FLAGS_v;
-}
-
-void Shutdown() { delete internal::global_context; }
-
-bool ReportUnrecognizedArguments(int argc, char** argv) {
-  for (int i = 1; i < argc; ++i) {
-    fprintf(stderr, "%s: error: unrecognized command-line flag: %s\n", argv[0],
-            argv[i]);
-  }
-  return argc > 1;
-}
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/benchmark_api_internal.cc b/vendor/core/vendor/googlebenchmark/src/benchmark_api_internal.cc
deleted file mode 100644
index 286f98653..000000000
--- a/vendor/core/vendor/googlebenchmark/src/benchmark_api_internal.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-#include "benchmark_api_internal.h"
-
-#include 
-
-#include "string_util.h"
-
-namespace benchmark {
-namespace internal {
-
-BenchmarkInstance::BenchmarkInstance(Benchmark* benchmark, int family_idx,
-                                     int per_family_instance_idx,
-                                     const std::vector& args,
-                                     int thread_count)
-    : benchmark_(*benchmark),
-      family_index_(family_idx),
-      per_family_instance_index_(per_family_instance_idx),
-      aggregation_report_mode_(benchmark_.aggregation_report_mode_),
-      args_(args),
-      time_unit_(benchmark_.GetTimeUnit()),
-      measure_process_cpu_time_(benchmark_.measure_process_cpu_time_),
-      use_real_time_(benchmark_.use_real_time_),
-      use_manual_time_(benchmark_.use_manual_time_),
-      complexity_(benchmark_.complexity_),
-      complexity_lambda_(benchmark_.complexity_lambda_),
-      statistics_(benchmark_.statistics_),
-      repetitions_(benchmark_.repetitions_),
-      min_time_(benchmark_.min_time_),
-      min_warmup_time_(benchmark_.min_warmup_time_),
-      iterations_(benchmark_.iterations_),
-      threads_(thread_count) {
-  name_.function_name = benchmark_.name_;
-
-  size_t arg_i = 0;
-  for (const auto& arg : args) {
-    if (!name_.args.empty()) {
-      name_.args += '/';
-    }
-
-    if (arg_i < benchmark->arg_names_.size()) {
-      const auto& arg_name = benchmark_.arg_names_[arg_i];
-      if (!arg_name.empty()) {
-        name_.args += StrFormat("%s:", arg_name.c_str());
-      }
-    }
-
-    name_.args += StrFormat("%" PRId64, arg);
-    ++arg_i;
-  }
-
-  if (!IsZero(benchmark->min_time_)) {
-    name_.min_time = StrFormat("min_time:%0.3f", benchmark_.min_time_);
-  }
-
-  if (!IsZero(benchmark->min_warmup_time_)) {
-    name_.min_warmup_time =
-        StrFormat("min_warmup_time:%0.3f", benchmark_.min_warmup_time_);
-  }
-
-  if (benchmark_.iterations_ != 0) {
-    name_.iterations = StrFormat(
-        "iterations:%lu", static_cast(benchmark_.iterations_));
-  }
-
-  if (benchmark_.repetitions_ != 0) {
-    name_.repetitions = StrFormat("repeats:%d", benchmark_.repetitions_);
-  }
-
-  if (benchmark_.measure_process_cpu_time_) {
-    name_.time_type = "process_time";
-  }
-
-  if (benchmark_.use_manual_time_) {
-    if (!name_.time_type.empty()) {
-      name_.time_type += '/';
-    }
-    name_.time_type += "manual_time";
-  } else if (benchmark_.use_real_time_) {
-    if (!name_.time_type.empty()) {
-      name_.time_type += '/';
-    }
-    name_.time_type += "real_time";
-  }
-
-  if (!benchmark_.thread_counts_.empty()) {
-    name_.threads = StrFormat("threads:%d", threads_);
-  }
-
-  setup_ = benchmark_.setup_;
-  teardown_ = benchmark_.teardown_;
-}
-
-State BenchmarkInstance::Run(
-    IterationCount iters, int thread_id, internal::ThreadTimer* timer,
-    internal::ThreadManager* manager,
-    internal::PerfCountersMeasurement* perf_counters_measurement) const {
-  State st(name_.function_name, iters, args_, thread_id, threads_, timer,
-           manager, perf_counters_measurement);
-  benchmark_.Run(st);
-  return st;
-}
-
-void BenchmarkInstance::Setup() const {
-  if (setup_) {
-    State st(name_.function_name, /*iters*/ 1, args_, /*thread_id*/ 0, threads_,
-             nullptr, nullptr, nullptr);
-    setup_(st);
-  }
-}
-
-void BenchmarkInstance::Teardown() const {
-  if (teardown_) {
-    State st(name_.function_name, /*iters*/ 1, args_, /*thread_id*/ 0, threads_,
-             nullptr, nullptr, nullptr);
-    teardown_(st);
-  }
-}
-}  // namespace internal
-}  // namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/benchmark_api_internal.h b/vendor/core/vendor/googlebenchmark/src/benchmark_api_internal.h
deleted file mode 100644
index 94f516531..000000000
--- a/vendor/core/vendor/googlebenchmark/src/benchmark_api_internal.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef BENCHMARK_API_INTERNAL_H
-#define BENCHMARK_API_INTERNAL_H
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-#include "commandlineflags.h"
-
-namespace benchmark {
-namespace internal {
-
-// Information kept per benchmark we may want to run
-class BenchmarkInstance {
- public:
-  BenchmarkInstance(Benchmark* benchmark, int family_index,
-                    int per_family_instance_index,
-                    const std::vector& args, int threads);
-
-  const BenchmarkName& name() const { return name_; }
-  int family_index() const { return family_index_; }
-  int per_family_instance_index() const { return per_family_instance_index_; }
-  AggregationReportMode aggregation_report_mode() const {
-    return aggregation_report_mode_;
-  }
-  TimeUnit time_unit() const { return time_unit_; }
-  bool measure_process_cpu_time() const { return measure_process_cpu_time_; }
-  bool use_real_time() const { return use_real_time_; }
-  bool use_manual_time() const { return use_manual_time_; }
-  BigO complexity() const { return complexity_; }
-  BigOFunc* complexity_lambda() const { return complexity_lambda_; }
-  const std::vector& statistics() const { return statistics_; }
-  int repetitions() const { return repetitions_; }
-  double min_time() const { return min_time_; }
-  double min_warmup_time() const { return min_warmup_time_; }
-  IterationCount iterations() const { return iterations_; }
-  int threads() const { return threads_; }
-  void Setup() const;
-  void Teardown() const;
-
-  State Run(IterationCount iters, int thread_id, internal::ThreadTimer* timer,
-            internal::ThreadManager* manager,
-            internal::PerfCountersMeasurement* perf_counters_measurement) const;
-
- private:
-  BenchmarkName name_;
-  Benchmark& benchmark_;
-  const int family_index_;
-  const int per_family_instance_index_;
-  AggregationReportMode aggregation_report_mode_;
-  const std::vector& args_;
-  TimeUnit time_unit_;
-  bool measure_process_cpu_time_;
-  bool use_real_time_;
-  bool use_manual_time_;
-  BigO complexity_;
-  BigOFunc* complexity_lambda_;
-  UserCounters counters_;
-  const std::vector& statistics_;
-  int repetitions_;
-  double min_time_;
-  double min_warmup_time_;
-  IterationCount iterations_;
-  int threads_;  // Number of concurrent threads to us
-
-  typedef void (*callback_function)(const benchmark::State&);
-  callback_function setup_ = nullptr;
-  callback_function teardown_ = nullptr;
-};
-
-bool FindBenchmarksInternal(const std::string& re,
-                            std::vector* benchmarks,
-                            std::ostream* Err);
-
-bool IsZero(double n);
-
-BENCHMARK_EXPORT
-ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color = false);
-
-}  // end namespace internal
-}  // end namespace benchmark
-
-#endif  // BENCHMARK_API_INTERNAL_H
diff --git a/vendor/core/vendor/googlebenchmark/src/benchmark_main.cc b/vendor/core/vendor/googlebenchmark/src/benchmark_main.cc
deleted file mode 100644
index cd61cd2ad..000000000
--- a/vendor/core/vendor/googlebenchmark/src/benchmark_main.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2018 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark/benchmark.h"
-
-BENCHMARK_EXPORT int main(int, char**);
-BENCHMARK_MAIN();
diff --git a/vendor/core/vendor/googlebenchmark/src/benchmark_name.cc b/vendor/core/vendor/googlebenchmark/src/benchmark_name.cc
deleted file mode 100644
index 01676bbc8..000000000
--- a/vendor/core/vendor/googlebenchmark/src/benchmark_name.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include 
-
-namespace benchmark {
-
-namespace {
-
-// Compute the total size of a pack of std::strings
-size_t size_impl() { return 0; }
-
-template 
-size_t size_impl(const Head& head, const Tail&... tail) {
-  return head.size() + size_impl(tail...);
-}
-
-// Join a pack of std::strings using a delimiter
-// TODO: use absl::StrJoin
-void join_impl(std::string&, char) {}
-
-template 
-void join_impl(std::string& s, const char delimiter, const Head& head,
-               const Tail&... tail) {
-  if (!s.empty() && !head.empty()) {
-    s += delimiter;
-  }
-
-  s += head;
-
-  join_impl(s, delimiter, tail...);
-}
-
-template 
-std::string join(char delimiter, const Ts&... ts) {
-  std::string s;
-  s.reserve(sizeof...(Ts) + size_impl(ts...));
-  join_impl(s, delimiter, ts...);
-  return s;
-}
-}  // namespace
-
-BENCHMARK_EXPORT
-std::string BenchmarkName::str() const {
-  return join('/', function_name, args, min_time, min_warmup_time, iterations,
-              repetitions, time_type, threads);
-}
-}  // namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/benchmark_register.cc b/vendor/core/vendor/googlebenchmark/src/benchmark_register.cc
deleted file mode 100644
index 8ade04822..000000000
--- a/vendor/core/vendor/googlebenchmark/src/benchmark_register.cc
+++ /dev/null
@@ -1,521 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark_register.h"
-
-#ifndef BENCHMARK_OS_WINDOWS
-#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
-#include 
-#endif
-#include 
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-#include "benchmark_api_internal.h"
-#include "check.h"
-#include "commandlineflags.h"
-#include "complexity.h"
-#include "internal_macros.h"
-#include "log.h"
-#include "mutex.h"
-#include "re.h"
-#include "statistics.h"
-#include "string_util.h"
-#include "timers.h"
-
-namespace benchmark {
-
-namespace {
-// For non-dense Range, intermediate values are powers of kRangeMultiplier.
-static constexpr int kRangeMultiplier = 8;
-
-// The size of a benchmark family determines is the number of inputs to repeat
-// the benchmark on. If this is "large" then warn the user during configuration.
-static constexpr size_t kMaxFamilySize = 100;
-
-static constexpr char kDisabledPrefix[] = "DISABLED_";
-}  // end namespace
-
-namespace internal {
-
-//=============================================================================//
-//                         BenchmarkFamilies
-//=============================================================================//
-
-// Class for managing registered benchmarks.  Note that each registered
-// benchmark identifies a family of related benchmarks to run.
-class BenchmarkFamilies {
- public:
-  static BenchmarkFamilies* GetInstance();
-
-  // Registers a benchmark family and returns the index assigned to it.
-  size_t AddBenchmark(std::unique_ptr family);
-
-  // Clear all registered benchmark families.
-  void ClearBenchmarks();
-
-  // Extract the list of benchmark instances that match the specified
-  // regular expression.
-  bool FindBenchmarks(std::string re,
-                      std::vector* benchmarks,
-                      std::ostream* Err);
-
- private:
-  BenchmarkFamilies() {}
-
-  std::vector> families_;
-  Mutex mutex_;
-};
-
-BenchmarkFamilies* BenchmarkFamilies::GetInstance() {
-  static BenchmarkFamilies instance;
-  return &instance;
-}
-
-size_t BenchmarkFamilies::AddBenchmark(std::unique_ptr family) {
-  MutexLock l(mutex_);
-  size_t index = families_.size();
-  families_.push_back(std::move(family));
-  return index;
-}
-
-void BenchmarkFamilies::ClearBenchmarks() {
-  MutexLock l(mutex_);
-  families_.clear();
-  families_.shrink_to_fit();
-}
-
-bool BenchmarkFamilies::FindBenchmarks(
-    std::string spec, std::vector* benchmarks,
-    std::ostream* ErrStream) {
-  BM_CHECK(ErrStream);
-  auto& Err = *ErrStream;
-  // Make regular expression out of command-line flag
-  std::string error_msg;
-  Regex re;
-  bool is_negative_filter = false;
-  if (spec[0] == '-') {
-    spec.replace(0, 1, "");
-    is_negative_filter = true;
-  }
-  if (!re.Init(spec, &error_msg)) {
-    Err << "Could not compile benchmark re: " << error_msg << std::endl;
-    return false;
-  }
-
-  // Special list of thread counts to use when none are specified
-  const std::vector one_thread = {1};
-
-  int next_family_index = 0;
-
-  MutexLock l(mutex_);
-  for (std::unique_ptr& family : families_) {
-    int family_index = next_family_index;
-    int per_family_instance_index = 0;
-
-    // Family was deleted or benchmark doesn't match
-    if (!family) continue;
-
-    if (family->ArgsCnt() == -1) {
-      family->Args({});
-    }
-    const std::vector* thread_counts =
-        (family->thread_counts_.empty()
-             ? &one_thread
-             : &static_cast&>(family->thread_counts_));
-    const size_t family_size = family->args_.size() * thread_counts->size();
-    // The benchmark will be run at least 'family_size' different inputs.
-    // If 'family_size' is very large warn the user.
-    if (family_size > kMaxFamilySize) {
-      Err << "The number of inputs is very large. " << family->name_
-          << " will be repeated at least " << family_size << " times.\n";
-    }
-    // reserve in the special case the regex ".", since we know the final
-    // family size.  this doesn't take into account any disabled benchmarks
-    // so worst case we reserve more than we need.
-    if (spec == ".") benchmarks->reserve(benchmarks->size() + family_size);
-
-    for (auto const& args : family->args_) {
-      for (int num_threads : *thread_counts) {
-        BenchmarkInstance instance(family.get(), family_index,
-                                   per_family_instance_index, args,
-                                   num_threads);
-
-        const auto full_name = instance.name().str();
-        if (full_name.rfind(kDisabledPrefix, 0) != 0 &&
-            ((re.Match(full_name) && !is_negative_filter) ||
-             (!re.Match(full_name) && is_negative_filter))) {
-          benchmarks->push_back(std::move(instance));
-
-          ++per_family_instance_index;
-
-          // Only bump the next family index once we've estabilished that
-          // at least one instance of this family will be run.
-          if (next_family_index == family_index) ++next_family_index;
-        }
-      }
-    }
-  }
-  return true;
-}
-
-Benchmark* RegisterBenchmarkInternal(Benchmark* bench) {
-  std::unique_ptr bench_ptr(bench);
-  BenchmarkFamilies* families = BenchmarkFamilies::GetInstance();
-  families->AddBenchmark(std::move(bench_ptr));
-  return bench;
-}
-
-// FIXME: This function is a hack so that benchmark.cc can access
-// `BenchmarkFamilies`
-bool FindBenchmarksInternal(const std::string& re,
-                            std::vector* benchmarks,
-                            std::ostream* Err) {
-  return BenchmarkFamilies::GetInstance()->FindBenchmarks(re, benchmarks, Err);
-}
-
-//=============================================================================//
-//                               Benchmark
-//=============================================================================//
-
-Benchmark::Benchmark(const std::string& name)
-    : name_(name),
-      aggregation_report_mode_(ARM_Unspecified),
-      time_unit_(GetDefaultTimeUnit()),
-      use_default_time_unit_(true),
-      range_multiplier_(kRangeMultiplier),
-      min_time_(0),
-      min_warmup_time_(0),
-      iterations_(0),
-      repetitions_(0),
-      measure_process_cpu_time_(false),
-      use_real_time_(false),
-      use_manual_time_(false),
-      complexity_(oNone),
-      complexity_lambda_(nullptr),
-      setup_(nullptr),
-      teardown_(nullptr) {
-  ComputeStatistics("mean", StatisticsMean);
-  ComputeStatistics("median", StatisticsMedian);
-  ComputeStatistics("stddev", StatisticsStdDev);
-  ComputeStatistics("cv", StatisticsCV, kPercentage);
-}
-
-Benchmark::~Benchmark() {}
-
-Benchmark* Benchmark::Name(const std::string& name) {
-  SetName(name);
-  return this;
-}
-
-Benchmark* Benchmark::Arg(int64_t x) {
-  BM_CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
-  args_.push_back({x});
-  return this;
-}
-
-Benchmark* Benchmark::Unit(TimeUnit unit) {
-  time_unit_ = unit;
-  use_default_time_unit_ = false;
-  return this;
-}
-
-Benchmark* Benchmark::Range(int64_t start, int64_t limit) {
-  BM_CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
-  std::vector arglist;
-  AddRange(&arglist, start, limit, range_multiplier_);
-
-  for (int64_t i : arglist) {
-    args_.push_back({i});
-  }
-  return this;
-}
-
-Benchmark* Benchmark::Ranges(
-    const std::vector>& ranges) {
-  BM_CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast(ranges.size()));
-  std::vector> arglists(ranges.size());
-  for (std::size_t i = 0; i < ranges.size(); i++) {
-    AddRange(&arglists[i], ranges[i].first, ranges[i].second,
-             range_multiplier_);
-  }
-
-  ArgsProduct(arglists);
-
-  return this;
-}
-
-Benchmark* Benchmark::ArgsProduct(
-    const std::vector>& arglists) {
-  BM_CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast(arglists.size()));
-
-  std::vector indices(arglists.size());
-  const std::size_t total = std::accumulate(
-      std::begin(arglists), std::end(arglists), std::size_t{1},
-      [](const std::size_t res, const std::vector& arglist) {
-        return res * arglist.size();
-      });
-  std::vector args;
-  args.reserve(arglists.size());
-  for (std::size_t i = 0; i < total; i++) {
-    for (std::size_t arg = 0; arg < arglists.size(); arg++) {
-      args.push_back(arglists[arg][indices[arg]]);
-    }
-    args_.push_back(args);
-    args.clear();
-
-    std::size_t arg = 0;
-    do {
-      indices[arg] = (indices[arg] + 1) % arglists[arg].size();
-    } while (indices[arg++] == 0 && arg < arglists.size());
-  }
-
-  return this;
-}
-
-Benchmark* Benchmark::ArgName(const std::string& name) {
-  BM_CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
-  arg_names_ = {name};
-  return this;
-}
-
-Benchmark* Benchmark::ArgNames(const std::vector& names) {
-  BM_CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast(names.size()));
-  arg_names_ = names;
-  return this;
-}
-
-Benchmark* Benchmark::DenseRange(int64_t start, int64_t limit, int step) {
-  BM_CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
-  BM_CHECK_LE(start, limit);
-  for (int64_t arg = start; arg <= limit; arg += step) {
-    args_.push_back({arg});
-  }
-  return this;
-}
-
-Benchmark* Benchmark::Args(const std::vector& args) {
-  BM_CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast(args.size()));
-  args_.push_back(args);
-  return this;
-}
-
-Benchmark* Benchmark::Apply(void (*custom_arguments)(Benchmark* benchmark)) {
-  custom_arguments(this);
-  return this;
-}
-
-Benchmark* Benchmark::Setup(void (*setup)(const benchmark::State&)) {
-  BM_CHECK(setup != nullptr);
-  setup_ = setup;
-  return this;
-}
-
-Benchmark* Benchmark::Teardown(void (*teardown)(const benchmark::State&)) {
-  BM_CHECK(teardown != nullptr);
-  teardown_ = teardown;
-  return this;
-}
-
-Benchmark* Benchmark::RangeMultiplier(int multiplier) {
-  BM_CHECK(multiplier > 1);
-  range_multiplier_ = multiplier;
-  return this;
-}
-
-Benchmark* Benchmark::MinTime(double t) {
-  BM_CHECK(t > 0.0);
-  BM_CHECK(iterations_ == 0);
-  min_time_ = t;
-  return this;
-}
-
-Benchmark* Benchmark::MinWarmUpTime(double t) {
-  BM_CHECK(t >= 0.0);
-  BM_CHECK(iterations_ == 0);
-  min_warmup_time_ = t;
-  return this;
-}
-
-Benchmark* Benchmark::Iterations(IterationCount n) {
-  BM_CHECK(n > 0);
-  BM_CHECK(IsZero(min_time_));
-  BM_CHECK(IsZero(min_warmup_time_));
-  iterations_ = n;
-  return this;
-}
-
-Benchmark* Benchmark::Repetitions(int n) {
-  BM_CHECK(n > 0);
-  repetitions_ = n;
-  return this;
-}
-
-Benchmark* Benchmark::ReportAggregatesOnly(bool value) {
-  aggregation_report_mode_ = value ? ARM_ReportAggregatesOnly : ARM_Default;
-  return this;
-}
-
-Benchmark* Benchmark::DisplayAggregatesOnly(bool value) {
-  // If we were called, the report mode is no longer 'unspecified', in any case.
-  aggregation_report_mode_ = static_cast(
-      aggregation_report_mode_ | ARM_Default);
-
-  if (value) {
-    aggregation_report_mode_ = static_cast(
-        aggregation_report_mode_ | ARM_DisplayReportAggregatesOnly);
-  } else {
-    aggregation_report_mode_ = static_cast(
-        aggregation_report_mode_ & ~ARM_DisplayReportAggregatesOnly);
-  }
-
-  return this;
-}
-
-Benchmark* Benchmark::MeasureProcessCPUTime() {
-  // Can be used together with UseRealTime() / UseManualTime().
-  measure_process_cpu_time_ = true;
-  return this;
-}
-
-Benchmark* Benchmark::UseRealTime() {
-  BM_CHECK(!use_manual_time_)
-      << "Cannot set UseRealTime and UseManualTime simultaneously.";
-  use_real_time_ = true;
-  return this;
-}
-
-Benchmark* Benchmark::UseManualTime() {
-  BM_CHECK(!use_real_time_)
-      << "Cannot set UseRealTime and UseManualTime simultaneously.";
-  use_manual_time_ = true;
-  return this;
-}
-
-Benchmark* Benchmark::Complexity(BigO complexity) {
-  complexity_ = complexity;
-  return this;
-}
-
-Benchmark* Benchmark::Complexity(BigOFunc* complexity) {
-  complexity_lambda_ = complexity;
-  complexity_ = oLambda;
-  return this;
-}
-
-Benchmark* Benchmark::ComputeStatistics(const std::string& name,
-                                        StatisticsFunc* statistics,
-                                        StatisticUnit unit) {
-  statistics_.emplace_back(name, statistics, unit);
-  return this;
-}
-
-Benchmark* Benchmark::Threads(int t) {
-  BM_CHECK_GT(t, 0);
-  thread_counts_.push_back(t);
-  return this;
-}
-
-Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) {
-  BM_CHECK_GT(min_threads, 0);
-  BM_CHECK_GE(max_threads, min_threads);
-
-  AddRange(&thread_counts_, min_threads, max_threads, 2);
-  return this;
-}
-
-Benchmark* Benchmark::DenseThreadRange(int min_threads, int max_threads,
-                                       int stride) {
-  BM_CHECK_GT(min_threads, 0);
-  BM_CHECK_GE(max_threads, min_threads);
-  BM_CHECK_GE(stride, 1);
-
-  for (auto i = min_threads; i < max_threads; i += stride) {
-    thread_counts_.push_back(i);
-  }
-  thread_counts_.push_back(max_threads);
-  return this;
-}
-
-Benchmark* Benchmark::ThreadPerCpu() {
-  thread_counts_.push_back(CPUInfo::Get().num_cpus);
-  return this;
-}
-
-void Benchmark::SetName(const std::string& name) { name_ = name; }
-
-const char* Benchmark::GetName() const { return name_.c_str(); }
-
-int Benchmark::ArgsCnt() const {
-  if (args_.empty()) {
-    if (arg_names_.empty()) return -1;
-    return static_cast(arg_names_.size());
-  }
-  return static_cast(args_.front().size());
-}
-
-const char* Benchmark::GetArgName(int arg) const {
-  BM_CHECK_GE(arg, 0);
-  size_t uarg = static_cast(arg);
-  BM_CHECK_LT(uarg, arg_names_.size());
-  return arg_names_[uarg].c_str();
-}
-
-TimeUnit Benchmark::GetTimeUnit() const {
-  return use_default_time_unit_ ? GetDefaultTimeUnit() : time_unit_;
-}
-
-//=============================================================================//
-//                            FunctionBenchmark
-//=============================================================================//
-
-void FunctionBenchmark::Run(State& st) { func_(st); }
-
-}  // end namespace internal
-
-void ClearRegisteredBenchmarks() {
-  internal::BenchmarkFamilies::GetInstance()->ClearBenchmarks();
-}
-
-std::vector CreateRange(int64_t lo, int64_t hi, int multi) {
-  std::vector args;
-  internal::AddRange(&args, lo, hi, multi);
-  return args;
-}
-
-std::vector CreateDenseRange(int64_t start, int64_t limit, int step) {
-  BM_CHECK_LE(start, limit);
-  std::vector args;
-  for (int64_t arg = start; arg <= limit; arg += step) {
-    args.push_back(arg);
-  }
-  return args;
-}
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/benchmark_register.h b/vendor/core/vendor/googlebenchmark/src/benchmark_register.h
deleted file mode 100644
index be50265f7..000000000
--- a/vendor/core/vendor/googlebenchmark/src/benchmark_register.h
+++ /dev/null
@@ -1,109 +0,0 @@
-#ifndef BENCHMARK_REGISTER_H
-#define BENCHMARK_REGISTER_H
-
-#include 
-#include 
-#include 
-
-#include "check.h"
-
-namespace benchmark {
-namespace internal {
-
-// Append the powers of 'mult' in the closed interval [lo, hi].
-// Returns iterator to the start of the inserted range.
-template 
-typename std::vector::iterator AddPowers(std::vector* dst, T lo, T hi,
-                                            int mult) {
-  BM_CHECK_GE(lo, 0);
-  BM_CHECK_GE(hi, lo);
-  BM_CHECK_GE(mult, 2);
-
-  const size_t start_offset = dst->size();
-
-  static const T kmax = std::numeric_limits::max();
-
-  // Space out the values in multiples of "mult"
-  for (T i = static_cast(1); i <= hi; i = static_cast(i * mult)) {
-    if (i >= lo) {
-      dst->push_back(i);
-    }
-    // Break the loop here since multiplying by
-    // 'mult' would move outside of the range of T
-    if (i > kmax / mult) break;
-  }
-
-  return dst->begin() + static_cast(start_offset);
-}
-
-template 
-void AddNegatedPowers(std::vector* dst, T lo, T hi, int mult) {
-  // We negate lo and hi so we require that they cannot be equal to 'min'.
-  BM_CHECK_GT(lo, std::numeric_limits::min());
-  BM_CHECK_GT(hi, std::numeric_limits::min());
-  BM_CHECK_GE(hi, lo);
-  BM_CHECK_LE(hi, 0);
-
-  // Add positive powers, then negate and reverse.
-  // Casts necessary since small integers get promoted
-  // to 'int' when negating.
-  const auto lo_complement = static_cast(-lo);
-  const auto hi_complement = static_cast(-hi);
-
-  const auto it = AddPowers(dst, hi_complement, lo_complement, mult);
-
-  std::for_each(it, dst->end(), [](T& t) { t = static_cast(t * -1); });
-  std::reverse(it, dst->end());
-}
-
-template 
-void AddRange(std::vector* dst, T lo, T hi, int mult) {
-  static_assert(std::is_integral::value && std::is_signed::value,
-                "Args type must be a signed integer");
-
-  BM_CHECK_GE(hi, lo);
-  BM_CHECK_GE(mult, 2);
-
-  // Add "lo"
-  dst->push_back(lo);
-
-  // Handle lo == hi as a special case, so we then know
-  // lo < hi and so it is safe to add 1 to lo and subtract 1
-  // from hi without falling outside of the range of T.
-  if (lo == hi) return;
-
-  // Ensure that lo_inner <= hi_inner below.
-  if (lo + 1 == hi) {
-    dst->push_back(hi);
-    return;
-  }
-
-  // Add all powers of 'mult' in the range [lo+1, hi-1] (inclusive).
-  const auto lo_inner = static_cast(lo + 1);
-  const auto hi_inner = static_cast(hi - 1);
-
-  // Insert negative values
-  if (lo_inner < 0) {
-    AddNegatedPowers(dst, lo_inner, std::min(hi_inner, T{-1}), mult);
-  }
-
-  // Treat 0 as a special case (see discussion on #762).
-  if (lo < 0 && hi >= 0) {
-    dst->push_back(0);
-  }
-
-  // Insert positive values
-  if (hi_inner > 0) {
-    AddPowers(dst, std::max(lo_inner, T{1}), hi_inner, mult);
-  }
-
-  // Add "hi" (if different from last value).
-  if (hi != dst->back()) {
-    dst->push_back(hi);
-  }
-}
-
-}  // namespace internal
-}  // namespace benchmark
-
-#endif  // BENCHMARK_REGISTER_H
diff --git a/vendor/core/vendor/googlebenchmark/src/benchmark_runner.cc b/vendor/core/vendor/googlebenchmark/src/benchmark_runner.cc
deleted file mode 100644
index 3a8c3076a..000000000
--- a/vendor/core/vendor/googlebenchmark/src/benchmark_runner.cc
+++ /dev/null
@@ -1,525 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark_runner.h"
-
-#include "benchmark/benchmark.h"
-#include "benchmark_api_internal.h"
-#include "internal_macros.h"
-
-#ifndef BENCHMARK_OS_WINDOWS
-#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
-#include 
-#endif
-#include 
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "check.h"
-#include "colorprint.h"
-#include "commandlineflags.h"
-#include "complexity.h"
-#include "counter.h"
-#include "internal_macros.h"
-#include "log.h"
-#include "mutex.h"
-#include "perf_counters.h"
-#include "re.h"
-#include "statistics.h"
-#include "string_util.h"
-#include "thread_manager.h"
-#include "thread_timer.h"
-
-namespace benchmark {
-
-namespace internal {
-
-MemoryManager* memory_manager = nullptr;
-
-ProfilerManager* profiler_manager = nullptr;
-
-namespace {
-
-static constexpr IterationCount kMaxIterations = 1000000000000;
-const double kDefaultMinTime =
-    std::strtod(::benchmark::kDefaultMinTimeStr, /*p_end*/ nullptr);
-
-BenchmarkReporter::Run CreateRunReport(
-    const benchmark::internal::BenchmarkInstance& b,
-    const internal::ThreadManager::Result& results,
-    IterationCount memory_iterations,
-    const MemoryManager::Result* memory_result, double seconds,
-    int64_t repetition_index, int64_t repeats) {
-  // Create report about this benchmark run.
-  BenchmarkReporter::Run report;
-
-  report.run_name = b.name();
-  report.family_index = b.family_index();
-  report.per_family_instance_index = b.per_family_instance_index();
-  report.skipped = results.skipped_;
-  report.skip_message = results.skip_message_;
-  report.report_label = results.report_label_;
-  // This is the total iterations across all threads.
-  report.iterations = results.iterations;
-  report.time_unit = b.time_unit();
-  report.threads = b.threads();
-  report.repetition_index = repetition_index;
-  report.repetitions = repeats;
-
-  if (!report.skipped) {
-    if (b.use_manual_time()) {
-      report.real_accumulated_time = results.manual_time_used;
-    } else {
-      report.real_accumulated_time = results.real_time_used;
-    }
-    report.use_real_time_for_initial_big_o = b.use_manual_time();
-    report.cpu_accumulated_time = results.cpu_time_used;
-    report.complexity_n = results.complexity_n;
-    report.complexity = b.complexity();
-    report.complexity_lambda = b.complexity_lambda();
-    report.statistics = &b.statistics();
-    report.counters = results.counters;
-
-    if (memory_iterations > 0) {
-      assert(memory_result != nullptr);
-      report.memory_result = memory_result;
-      report.allocs_per_iter =
-          memory_iterations ? static_cast(memory_result->num_allocs) /
-                                  static_cast(memory_iterations)
-                            : 0;
-    }
-
-    internal::Finish(&report.counters, results.iterations, seconds,
-                     b.threads());
-  }
-  return report;
-}
-
-// Execute one thread of benchmark b for the specified number of iterations.
-// Adds the stats collected for the thread into manager->results.
-void RunInThread(const BenchmarkInstance* b, IterationCount iters,
-                 int thread_id, ThreadManager* manager,
-                 PerfCountersMeasurement* perf_counters_measurement) {
-  internal::ThreadTimer timer(
-      b->measure_process_cpu_time()
-          ? internal::ThreadTimer::CreateProcessCpuTime()
-          : internal::ThreadTimer::Create());
-
-  State st =
-      b->Run(iters, thread_id, &timer, manager, perf_counters_measurement);
-  BM_CHECK(st.skipped() || st.iterations() >= st.max_iterations)
-      << "Benchmark returned before State::KeepRunning() returned false!";
-  {
-    MutexLock l(manager->GetBenchmarkMutex());
-    internal::ThreadManager::Result& results = manager->results;
-    results.iterations += st.iterations();
-    results.cpu_time_used += timer.cpu_time_used();
-    results.real_time_used += timer.real_time_used();
-    results.manual_time_used += timer.manual_time_used();
-    results.complexity_n += st.complexity_length_n();
-    internal::Increment(&results.counters, st.counters);
-  }
-  manager->NotifyThreadComplete();
-}
-
-double ComputeMinTime(const benchmark::internal::BenchmarkInstance& b,
-                      const BenchTimeType& iters_or_time) {
-  if (!IsZero(b.min_time())) return b.min_time();
-  // If the flag was used to specify number of iters, then return the default
-  // min_time.
-  if (iters_or_time.tag == BenchTimeType::ITERS) return kDefaultMinTime;
-
-  return iters_or_time.time;
-}
-
-IterationCount ComputeIters(const benchmark::internal::BenchmarkInstance& b,
-                            const BenchTimeType& iters_or_time) {
-  if (b.iterations() != 0) return b.iterations();
-
-  // We've already concluded that this flag is currently used to pass
-  // iters but do a check here again anyway.
-  BM_CHECK(iters_or_time.tag == BenchTimeType::ITERS);
-  return iters_or_time.iters;
-}
-
-}  // end namespace
-
-BenchTimeType ParseBenchMinTime(const std::string& value) {
-  BenchTimeType ret;
-
-  if (value.empty()) {
-    ret.tag = BenchTimeType::TIME;
-    ret.time = 0.0;
-    return ret;
-  }
-
-  if (value.back() == 'x') {
-    char* p_end;
-    // Reset errno before it's changed by strtol.
-    errno = 0;
-    IterationCount num_iters = std::strtol(value.c_str(), &p_end, 10);
-
-    // After a valid parse, p_end should have been set to
-    // point to the 'x' suffix.
-    BM_CHECK(errno == 0 && p_end != nullptr && *p_end == 'x')
-        << "Malformed iters value passed to --benchmark_min_time: `" << value
-        << "`. Expected --benchmark_min_time=x.";
-
-    ret.tag = BenchTimeType::ITERS;
-    ret.iters = num_iters;
-    return ret;
-  }
-
-  bool has_suffix = value.back() == 's';
-  if (!has_suffix) {
-    BM_VLOG(0) << "Value passed to --benchmark_min_time should have a suffix. "
-                  "Eg., `30s` for 30-seconds.";
-  }
-
-  char* p_end;
-  // Reset errno before it's changed by strtod.
-  errno = 0;
-  double min_time = std::strtod(value.c_str(), &p_end);
-
-  // After a successful parse, p_end should point to the suffix 's',
-  // or the end of the string if the suffix was omitted.
-  BM_CHECK(errno == 0 && p_end != nullptr &&
-           ((has_suffix && *p_end == 's') || *p_end == '\0'))
-      << "Malformed seconds value passed to --benchmark_min_time: `" << value
-      << "`. Expected --benchmark_min_time=x.";
-
-  ret.tag = BenchTimeType::TIME;
-  ret.time = min_time;
-
-  return ret;
-}
-
-BenchmarkRunner::BenchmarkRunner(
-    const benchmark::internal::BenchmarkInstance& b_,
-    PerfCountersMeasurement* pcm_,
-    BenchmarkReporter::PerFamilyRunReports* reports_for_family_)
-    : b(b_),
-      reports_for_family(reports_for_family_),
-      parsed_benchtime_flag(ParseBenchMinTime(FLAGS_benchmark_min_time)),
-      min_time(ComputeMinTime(b_, parsed_benchtime_flag)),
-      min_warmup_time((!IsZero(b.min_time()) && b.min_warmup_time() > 0.0)
-                          ? b.min_warmup_time()
-                          : FLAGS_benchmark_min_warmup_time),
-      warmup_done(!(min_warmup_time > 0.0)),
-      repeats(b.repetitions() != 0 ? b.repetitions()
-                                   : FLAGS_benchmark_repetitions),
-      has_explicit_iteration_count(b.iterations() != 0 ||
-                                   parsed_benchtime_flag.tag ==
-                                       BenchTimeType::ITERS),
-      pool(static_cast(b.threads() - 1)),
-      iters(has_explicit_iteration_count
-                ? ComputeIters(b_, parsed_benchtime_flag)
-                : 1),
-      perf_counters_measurement_ptr(pcm_) {
-  run_results.display_report_aggregates_only =
-      (FLAGS_benchmark_report_aggregates_only ||
-       FLAGS_benchmark_display_aggregates_only);
-  run_results.file_report_aggregates_only =
-      FLAGS_benchmark_report_aggregates_only;
-  if (b.aggregation_report_mode() != internal::ARM_Unspecified) {
-    run_results.display_report_aggregates_only =
-        (b.aggregation_report_mode() &
-         internal::ARM_DisplayReportAggregatesOnly);
-    run_results.file_report_aggregates_only =
-        (b.aggregation_report_mode() & internal::ARM_FileReportAggregatesOnly);
-    BM_CHECK(FLAGS_benchmark_perf_counters.empty() ||
-             (perf_counters_measurement_ptr->num_counters() == 0))
-        << "Perf counters were requested but could not be set up.";
-  }
-}
-
-BenchmarkRunner::IterationResults BenchmarkRunner::DoNIterations() {
-  BM_VLOG(2) << "Running " << b.name().str() << " for " << iters << "\n";
-
-  std::unique_ptr manager;
-  manager.reset(new internal::ThreadManager(b.threads()));
-
-  // Run all but one thread in separate threads
-  for (std::size_t ti = 0; ti < pool.size(); ++ti) {
-    pool[ti] = std::thread(&RunInThread, &b, iters, static_cast(ti + 1),
-                           manager.get(), perf_counters_measurement_ptr);
-  }
-  // And run one thread here directly.
-  // (If we were asked to run just one thread, we don't create new threads.)
-  // Yes, we need to do this here *after* we start the separate threads.
-  RunInThread(&b, iters, 0, manager.get(), perf_counters_measurement_ptr);
-
-  // The main thread has finished. Now let's wait for the other threads.
-  manager->WaitForAllThreads();
-  for (std::thread& thread : pool) thread.join();
-
-  IterationResults i;
-  // Acquire the measurements/counters from the manager, UNDER THE LOCK!
-  {
-    MutexLock l(manager->GetBenchmarkMutex());
-    i.results = manager->results;
-  }
-
-  // And get rid of the manager.
-  manager.reset();
-
-  // Adjust real/manual time stats since they were reported per thread.
-  i.results.real_time_used /= b.threads();
-  i.results.manual_time_used /= b.threads();
-  // If we were measuring whole-process CPU usage, adjust the CPU time too.
-  if (b.measure_process_cpu_time()) i.results.cpu_time_used /= b.threads();
-
-  BM_VLOG(2) << "Ran in " << i.results.cpu_time_used << "/"
-             << i.results.real_time_used << "\n";
-
-  // By using KeepRunningBatch a benchmark can iterate more times than
-  // requested, so take the iteration count from i.results.
-  i.iters = i.results.iterations / b.threads();
-
-  // Base decisions off of real time if requested by this benchmark.
-  i.seconds = i.results.cpu_time_used;
-  if (b.use_manual_time()) {
-    i.seconds = i.results.manual_time_used;
-  } else if (b.use_real_time()) {
-    i.seconds = i.results.real_time_used;
-  }
-
-  return i;
-}
-
-IterationCount BenchmarkRunner::PredictNumItersNeeded(
-    const IterationResults& i) const {
-  // See how much iterations should be increased by.
-  // Note: Avoid division by zero with max(seconds, 1ns).
-  double multiplier = GetMinTimeToApply() * 1.4 / std::max(i.seconds, 1e-9);
-  // If our last run was at least 10% of FLAGS_benchmark_min_time then we
-  // use the multiplier directly.
-  // Otherwise we use at most 10 times expansion.
-  // NOTE: When the last run was at least 10% of the min time the max
-  // expansion should be 14x.
-  const bool is_significant = (i.seconds / GetMinTimeToApply()) > 0.1;
-  multiplier = is_significant ? multiplier : 10.0;
-
-  // So what seems to be the sufficiently-large iteration count? Round up.
-  const IterationCount max_next_iters = static_cast(
-      std::llround(std::max(multiplier * static_cast(i.iters),
-                            static_cast(i.iters) + 1.0)));
-  // But we do have *some* limits though..
-  const IterationCount next_iters = std::min(max_next_iters, kMaxIterations);
-
-  BM_VLOG(3) << "Next iters: " << next_iters << ", " << multiplier << "\n";
-  return next_iters;  // round up before conversion to integer.
-}
-
-bool BenchmarkRunner::ShouldReportIterationResults(
-    const IterationResults& i) const {
-  // Determine if this run should be reported;
-  // Either it has run for a sufficient amount of time
-  // or because an error was reported.
-  return i.results.skipped_ ||
-         i.iters >= kMaxIterations ||  // Too many iterations already.
-         i.seconds >=
-             GetMinTimeToApply() ||  // The elapsed time is large enough.
-         // CPU time is specified but the elapsed real time greatly exceeds
-         // the minimum time.
-         // Note that user provided timers are except from this test.
-         ((i.results.real_time_used >= 5 * GetMinTimeToApply()) &&
-          !b.use_manual_time());
-}
-
-double BenchmarkRunner::GetMinTimeToApply() const {
-  // In order to re-use functionality to run and measure benchmarks for running
-  // a warmup phase of the benchmark, we need a way of telling whether to apply
-  // min_time or min_warmup_time. This function will figure out if we are in the
-  // warmup phase and therefore need to apply min_warmup_time or if we already
-  // in the benchmarking phase and min_time needs to be applied.
-  return warmup_done ? min_time : min_warmup_time;
-}
-
-void BenchmarkRunner::FinishWarmUp(const IterationCount& i) {
-  warmup_done = true;
-  iters = i;
-}
-
-void BenchmarkRunner::RunWarmUp() {
-  // Use the same mechanisms for warming up the benchmark as used for actually
-  // running and measuring the benchmark.
-  IterationResults i_warmup;
-  // Dont use the iterations determined in the warmup phase for the actual
-  // measured benchmark phase. While this may be a good starting point for the
-  // benchmark and it would therefore get rid of the need to figure out how many
-  // iterations are needed if min_time is set again, this may also be a complete
-  // wrong guess since the warmup loops might be considerably slower (e.g
-  // because of caching effects).
-  const IterationCount i_backup = iters;
-
-  for (;;) {
-    b.Setup();
-    i_warmup = DoNIterations();
-    b.Teardown();
-
-    const bool finish = ShouldReportIterationResults(i_warmup);
-
-    if (finish) {
-      FinishWarmUp(i_backup);
-      break;
-    }
-
-    // Although we are running "only" a warmup phase where running enough
-    // iterations at once without measuring time isn't as important as it is for
-    // the benchmarking phase, we still do it the same way as otherwise it is
-    // very confusing for the user to know how to choose a proper value for
-    // min_warmup_time if a different approach on running it is used.
-    iters = PredictNumItersNeeded(i_warmup);
-    assert(iters > i_warmup.iters &&
-           "if we did more iterations than we want to do the next time, "
-           "then we should have accepted the current iteration run.");
-  }
-}
-
-MemoryManager::Result* BenchmarkRunner::RunMemoryManager(
-    IterationCount memory_iterations) {
-  // TODO(vyng): Consider making BenchmarkReporter::Run::memory_result an
-  // optional so we don't have to own the Result here.
-  // Can't do it now due to cxx03.
-  memory_results.push_back(MemoryManager::Result());
-  MemoryManager::Result* memory_result = &memory_results.back();
-  memory_manager->Start();
-  std::unique_ptr manager;
-  manager.reset(new internal::ThreadManager(1));
-  b.Setup();
-  RunInThread(&b, memory_iterations, 0, manager.get(),
-              perf_counters_measurement_ptr);
-  manager->WaitForAllThreads();
-  manager.reset();
-  b.Teardown();
-  memory_manager->Stop(*memory_result);
-  return memory_result;
-}
-
-void BenchmarkRunner::RunProfilerManager() {
-  // TODO: Provide a way to specify the number of iterations.
-  IterationCount profile_iterations = 1;
-  std::unique_ptr manager;
-  manager.reset(new internal::ThreadManager(1));
-  b.Setup();
-  profiler_manager->AfterSetupStart();
-  RunInThread(&b, profile_iterations, 0, manager.get(),
-              /*perf_counters_measurement_ptr=*/nullptr);
-  manager->WaitForAllThreads();
-  profiler_manager->BeforeTeardownStop();
-  manager.reset();
-  b.Teardown();
-}
-
-void BenchmarkRunner::DoOneRepetition() {
-  assert(HasRepeatsRemaining() && "Already done all repetitions?");
-
-  const bool is_the_first_repetition = num_repetitions_done == 0;
-
-  // In case a warmup phase is requested by the benchmark, run it now.
-  // After running the warmup phase the BenchmarkRunner should be in a state as
-  // this warmup never happened except the fact that warmup_done is set. Every
-  // other manipulation of the BenchmarkRunner instance would be a bug! Please
-  // fix it.
-  if (!warmup_done) RunWarmUp();
-
-  IterationResults i;
-  // We *may* be gradually increasing the length (iteration count)
-  // of the benchmark until we decide the results are significant.
-  // And once we do, we report those last results and exit.
-  // Please do note that the if there are repetitions, the iteration count
-  // is *only* calculated for the *first* repetition, and other repetitions
-  // simply use that precomputed iteration count.
-  for (;;) {
-    b.Setup();
-    i = DoNIterations();
-    b.Teardown();
-
-    // Do we consider the results to be significant?
-    // If we are doing repetitions, and the first repetition was already done,
-    // it has calculated the correct iteration time, so we have run that very
-    // iteration count just now. No need to calculate anything. Just report.
-    // Else, the normal rules apply.
-    const bool results_are_significant = !is_the_first_repetition ||
-                                         has_explicit_iteration_count ||
-                                         ShouldReportIterationResults(i);
-
-    if (results_are_significant) break;  // Good, let's report them!
-
-    // Nope, bad iteration. Let's re-estimate the hopefully-sufficient
-    // iteration count, and run the benchmark again...
-
-    iters = PredictNumItersNeeded(i);
-    assert(iters > i.iters &&
-           "if we did more iterations than we want to do the next time, "
-           "then we should have accepted the current iteration run.");
-  }
-
-  // Produce memory measurements if requested.
-  MemoryManager::Result* memory_result = nullptr;
-  IterationCount memory_iterations = 0;
-  if (memory_manager != nullptr) {
-    // Only run a few iterations to reduce the impact of one-time
-    // allocations in benchmarks that are not properly managed.
-    memory_iterations = std::min(16, iters);
-    memory_result = RunMemoryManager(memory_iterations);
-  }
-
-  if (profiler_manager != nullptr) {
-    RunProfilerManager();
-  }
-
-  // Ok, now actually report.
-  BenchmarkReporter::Run report =
-      CreateRunReport(b, i.results, memory_iterations, memory_result, i.seconds,
-                      num_repetitions_done, repeats);
-
-  if (reports_for_family) {
-    ++reports_for_family->num_runs_done;
-    if (!report.skipped) reports_for_family->Runs.push_back(report);
-  }
-
-  run_results.non_aggregates.push_back(report);
-
-  ++num_repetitions_done;
-}
-
-RunResults&& BenchmarkRunner::GetResults() {
-  assert(!HasRepeatsRemaining() && "Did not run all repetitions yet?");
-
-  // Calculate additional statistics over the repetitions of this instance.
-  run_results.aggregates_only = ComputeStats(run_results.non_aggregates);
-
-  return std::move(run_results);
-}
-
-}  // end namespace internal
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/benchmark_runner.h b/vendor/core/vendor/googlebenchmark/src/benchmark_runner.h
deleted file mode 100644
index cd34d2d5b..000000000
--- a/vendor/core/vendor/googlebenchmark/src/benchmark_runner.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef BENCHMARK_RUNNER_H_
-#define BENCHMARK_RUNNER_H_
-
-#include 
-#include 
-
-#include "benchmark_api_internal.h"
-#include "internal_macros.h"
-#include "perf_counters.h"
-#include "thread_manager.h"
-
-namespace benchmark {
-
-BM_DECLARE_string(benchmark_min_time);
-BM_DECLARE_double(benchmark_min_warmup_time);
-BM_DECLARE_int32(benchmark_repetitions);
-BM_DECLARE_bool(benchmark_report_aggregates_only);
-BM_DECLARE_bool(benchmark_display_aggregates_only);
-BM_DECLARE_string(benchmark_perf_counters);
-
-namespace internal {
-
-extern MemoryManager* memory_manager;
-extern ProfilerManager* profiler_manager;
-
-struct RunResults {
-  std::vector non_aggregates;
-  std::vector aggregates_only;
-
-  bool display_report_aggregates_only = false;
-  bool file_report_aggregates_only = false;
-};
-
-struct BENCHMARK_EXPORT BenchTimeType {
-  enum { ITERS, TIME } tag;
-  union {
-    IterationCount iters;
-    double time;
-  };
-};
-
-BENCHMARK_EXPORT
-BenchTimeType ParseBenchMinTime(const std::string& value);
-
-class BenchmarkRunner {
- public:
-  BenchmarkRunner(const benchmark::internal::BenchmarkInstance& b_,
-                  benchmark::internal::PerfCountersMeasurement* pmc_,
-                  BenchmarkReporter::PerFamilyRunReports* reports_for_family);
-
-  int GetNumRepeats() const { return repeats; }
-
-  bool HasRepeatsRemaining() const {
-    return GetNumRepeats() != num_repetitions_done;
-  }
-
-  void DoOneRepetition();
-
-  RunResults&& GetResults();
-
-  BenchmarkReporter::PerFamilyRunReports* GetReportsForFamily() const {
-    return reports_for_family;
-  }
-
-  double GetMinTime() const { return min_time; }
-
-  bool HasExplicitIters() const { return has_explicit_iteration_count; }
-
-  IterationCount GetIters() const { return iters; }
-
- private:
-  RunResults run_results;
-
-  const benchmark::internal::BenchmarkInstance& b;
-  BenchmarkReporter::PerFamilyRunReports* reports_for_family;
-
-  BenchTimeType parsed_benchtime_flag;
-  const double min_time;
-  const double min_warmup_time;
-  bool warmup_done;
-  const int repeats;
-  const bool has_explicit_iteration_count;
-
-  int num_repetitions_done = 0;
-
-  std::vector pool;
-
-  std::vector memory_results;
-
-  IterationCount iters;  // preserved between repetitions!
-  // So only the first repetition has to find/calculate it,
-  // the other repetitions will just use that precomputed iteration count.
-
-  PerfCountersMeasurement* const perf_counters_measurement_ptr = nullptr;
-
-  struct IterationResults {
-    internal::ThreadManager::Result results;
-    IterationCount iters;
-    double seconds;
-  };
-  IterationResults DoNIterations();
-
-  MemoryManager::Result* RunMemoryManager(IterationCount memory_iterations);
-
-  void RunProfilerManager();
-
-  IterationCount PredictNumItersNeeded(const IterationResults& i) const;
-
-  bool ShouldReportIterationResults(const IterationResults& i) const;
-
-  double GetMinTimeToApply() const;
-
-  void FinishWarmUp(const IterationCount& i);
-
-  void RunWarmUp();
-};
-
-}  // namespace internal
-
-}  // end namespace benchmark
-
-#endif  // BENCHMARK_RUNNER_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/check.cc b/vendor/core/vendor/googlebenchmark/src/check.cc
deleted file mode 100644
index 5f7526e08..000000000
--- a/vendor/core/vendor/googlebenchmark/src/check.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "check.h"
-
-namespace benchmark {
-namespace internal {
-
-static AbortHandlerT* handler = &std::abort;
-
-BENCHMARK_EXPORT AbortHandlerT*& GetAbortHandler() { return handler; }
-
-}  // namespace internal
-}  // namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/check.h b/vendor/core/vendor/googlebenchmark/src/check.h
deleted file mode 100644
index c1cd5e85e..000000000
--- a/vendor/core/vendor/googlebenchmark/src/check.h
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef CHECK_H_
-#define CHECK_H_
-
-#include 
-#include 
-#include 
-
-#include "benchmark/export.h"
-#include "internal_macros.h"
-#include "log.h"
-
-#if defined(__GNUC__) || defined(__clang__)
-#define BENCHMARK_NOEXCEPT noexcept
-#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
-#elif defined(_MSC_VER) && !defined(__clang__)
-#if _MSC_VER >= 1900
-#define BENCHMARK_NOEXCEPT noexcept
-#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
-#else
-#define BENCHMARK_NOEXCEPT
-#define BENCHMARK_NOEXCEPT_OP(x)
-#endif
-#define __func__ __FUNCTION__
-#else
-#define BENCHMARK_NOEXCEPT
-#define BENCHMARK_NOEXCEPT_OP(x)
-#endif
-
-namespace benchmark {
-namespace internal {
-
-typedef void(AbortHandlerT)();
-
-BENCHMARK_EXPORT
-AbortHandlerT*& GetAbortHandler();
-
-BENCHMARK_NORETURN inline void CallAbortHandler() {
-  GetAbortHandler()();
-  std::abort();  // fallback to enforce noreturn
-}
-
-// CheckHandler is the class constructed by failing BM_CHECK macros.
-// CheckHandler will log information about the failures and abort when it is
-// destructed.
-class CheckHandler {
- public:
-  CheckHandler(const char* check, const char* file, const char* func, int line)
-      : log_(GetErrorLogInstance()) {
-    log_ << file << ":" << line << ": " << func << ": Check `" << check
-         << "' failed. ";
-  }
-
-  LogType& GetLog() { return log_; }
-
-#if defined(COMPILER_MSVC)
-#pragma warning(push)
-#pragma warning(disable : 4722)
-#endif
-  BENCHMARK_NORETURN ~CheckHandler() BENCHMARK_NOEXCEPT_OP(false) {
-    log_ << std::endl;
-    CallAbortHandler();
-  }
-#if defined(COMPILER_MSVC)
-#pragma warning(pop)
-#endif
-
-  CheckHandler& operator=(const CheckHandler&) = delete;
-  CheckHandler(const CheckHandler&) = delete;
-  CheckHandler() = delete;
-
- private:
-  LogType& log_;
-};
-
-}  // end namespace internal
-}  // end namespace benchmark
-
-// The BM_CHECK macro returns a std::ostream object that can have extra
-// information written to it.
-#ifndef NDEBUG
-#define BM_CHECK(b)                                                          \
-  (b ? ::benchmark::internal::GetNullLogInstance()                           \
-     : ::benchmark::internal::CheckHandler(#b, __FILE__, __func__, __LINE__) \
-           .GetLog())
-#else
-#define BM_CHECK(b) ::benchmark::internal::GetNullLogInstance()
-#endif
-
-// clang-format off
-// preserve whitespacing between operators for alignment
-#define BM_CHECK_EQ(a, b) BM_CHECK((a) == (b))
-#define BM_CHECK_NE(a, b) BM_CHECK((a) != (b))
-#define BM_CHECK_GE(a, b) BM_CHECK((a) >= (b))
-#define BM_CHECK_LE(a, b) BM_CHECK((a) <= (b))
-#define BM_CHECK_GT(a, b) BM_CHECK((a) > (b))
-#define BM_CHECK_LT(a, b) BM_CHECK((a) < (b))
-
-#define BM_CHECK_FLOAT_EQ(a, b, eps) BM_CHECK(std::fabs((a) - (b)) <  (eps))
-#define BM_CHECK_FLOAT_NE(a, b, eps) BM_CHECK(std::fabs((a) - (b)) >= (eps))
-#define BM_CHECK_FLOAT_GE(a, b, eps) BM_CHECK((a) - (b) > -(eps))
-#define BM_CHECK_FLOAT_LE(a, b, eps) BM_CHECK((b) - (a) > -(eps))
-#define BM_CHECK_FLOAT_GT(a, b, eps) BM_CHECK((a) - (b) >  (eps))
-#define BM_CHECK_FLOAT_LT(a, b, eps) BM_CHECK((b) - (a) >  (eps))
-//clang-format on
-
-#endif  // CHECK_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/colorprint.cc b/vendor/core/vendor/googlebenchmark/src/colorprint.cc
deleted file mode 100644
index abc71492f..000000000
--- a/vendor/core/vendor/googlebenchmark/src/colorprint.cc
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "colorprint.h"
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "check.h"
-#include "internal_macros.h"
-
-#ifdef BENCHMARK_OS_WINDOWS
-#include 
-#include 
-#else
-#include 
-#endif  // BENCHMARK_OS_WINDOWS
-
-namespace benchmark {
-namespace {
-#ifdef BENCHMARK_OS_WINDOWS
-typedef WORD PlatformColorCode;
-#else
-typedef const char* PlatformColorCode;
-#endif
-
-PlatformColorCode GetPlatformColorCode(LogColor color) {
-#ifdef BENCHMARK_OS_WINDOWS
-  switch (color) {
-    case COLOR_RED:
-      return FOREGROUND_RED;
-    case COLOR_GREEN:
-      return FOREGROUND_GREEN;
-    case COLOR_YELLOW:
-      return FOREGROUND_RED | FOREGROUND_GREEN;
-    case COLOR_BLUE:
-      return FOREGROUND_BLUE;
-    case COLOR_MAGENTA:
-      return FOREGROUND_BLUE | FOREGROUND_RED;
-    case COLOR_CYAN:
-      return FOREGROUND_BLUE | FOREGROUND_GREEN;
-    case COLOR_WHITE:  // fall through to default
-    default:
-      return 0;
-  }
-#else
-  switch (color) {
-    case COLOR_RED:
-      return "1";
-    case COLOR_GREEN:
-      return "2";
-    case COLOR_YELLOW:
-      return "3";
-    case COLOR_BLUE:
-      return "4";
-    case COLOR_MAGENTA:
-      return "5";
-    case COLOR_CYAN:
-      return "6";
-    case COLOR_WHITE:
-      return "7";
-    default:
-      return nullptr;
-  };
-#endif
-}
-
-}  // end namespace
-
-std::string FormatString(const char* msg, va_list args) {
-  // we might need a second shot at this, so pre-emptivly make a copy
-  va_list args_cp;
-  va_copy(args_cp, args);
-
-  std::size_t size = 256;
-  char local_buff[256];
-  auto ret = vsnprintf(local_buff, size, msg, args_cp);
-
-  va_end(args_cp);
-
-  // currently there is no error handling for failure, so this is hack.
-  BM_CHECK(ret >= 0);
-
-  if (ret == 0) {  // handle empty expansion
-    return {};
-  }
-  if (static_cast(ret) < size) {
-    return local_buff;
-  }
-  // we did not provide a long enough buffer on our first attempt.
-  size = static_cast(ret) + 1;  // + 1 for the null byte
-  std::unique_ptr buff(new char[size]);
-  ret = vsnprintf(buff.get(), size, msg, args);
-  BM_CHECK(ret > 0 && (static_cast(ret)) < size);
-  return buff.get();
-}
-
-std::string FormatString(const char* msg, ...) {
-  va_list args;
-  va_start(args, msg);
-  auto tmp = FormatString(msg, args);
-  va_end(args);
-  return tmp;
-}
-
-void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...) {
-  va_list args;
-  va_start(args, fmt);
-  ColorPrintf(out, color, fmt, args);
-  va_end(args);
-}
-
-void ColorPrintf(std::ostream& out, LogColor color, const char* fmt,
-                 va_list args) {
-#ifdef BENCHMARK_OS_WINDOWS
-  ((void)out);  // suppress unused warning
-
-  const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
-
-  // Gets the current text color.
-  CONSOLE_SCREEN_BUFFER_INFO buffer_info;
-  GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
-  const WORD old_color_attrs = buffer_info.wAttributes;
-
-  // We need to flush the stream buffers into the console before each
-  // SetConsoleTextAttribute call lest it affect the text that is already
-  // printed but has not yet reached the console.
-  out.flush();
-  SetConsoleTextAttribute(stdout_handle,
-                          GetPlatformColorCode(color) | FOREGROUND_INTENSITY);
-  out << FormatString(fmt, args);
-
-  out.flush();
-  // Restores the text color.
-  SetConsoleTextAttribute(stdout_handle, old_color_attrs);
-#else
-  const char* color_code = GetPlatformColorCode(color);
-  if (color_code) out << FormatString("\033[0;3%sm", color_code);
-  out << FormatString(fmt, args) << "\033[m";
-#endif
-}
-
-bool IsColorTerminal() {
-#if BENCHMARK_OS_WINDOWS
-  // On Windows the TERM variable is usually not set, but the
-  // console there does support colors.
-  return 0 != _isatty(_fileno(stdout));
-#else
-  // On non-Windows platforms, we rely on the TERM variable. This list of
-  // supported TERM values is copied from Google Test:
-  // .
-  const char* const SUPPORTED_TERM_VALUES[] = {
-      "xterm",
-      "xterm-color",
-      "xterm-256color",
-      "screen",
-      "screen-256color",
-      "tmux",
-      "tmux-256color",
-      "rxvt-unicode",
-      "rxvt-unicode-256color",
-      "linux",
-      "cygwin",
-      "xterm-kitty",
-      "alacritty",
-      "foot",
-      "foot-extra",
-      "wezterm",
-  };
-
-  const char* const term = getenv("TERM");
-
-  bool term_supports_color = false;
-  for (const char* candidate : SUPPORTED_TERM_VALUES) {
-    if (term && 0 == strcmp(term, candidate)) {
-      term_supports_color = true;
-      break;
-    }
-  }
-
-  return 0 != isatty(fileno(stdout)) && term_supports_color;
-#endif  // BENCHMARK_OS_WINDOWS
-}
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/colorprint.h b/vendor/core/vendor/googlebenchmark/src/colorprint.h
deleted file mode 100644
index 9f6fab9b3..000000000
--- a/vendor/core/vendor/googlebenchmark/src/colorprint.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef BENCHMARK_COLORPRINT_H_
-#define BENCHMARK_COLORPRINT_H_
-
-#include 
-#include 
-#include 
-
-namespace benchmark {
-enum LogColor {
-  COLOR_DEFAULT,
-  COLOR_RED,
-  COLOR_GREEN,
-  COLOR_YELLOW,
-  COLOR_BLUE,
-  COLOR_MAGENTA,
-  COLOR_CYAN,
-  COLOR_WHITE
-};
-
-std::string FormatString(const char* msg, va_list args);
-std::string FormatString(const char* msg, ...);
-
-void ColorPrintf(std::ostream& out, LogColor color, const char* fmt,
-                 va_list args);
-void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...);
-
-// Returns true if stdout appears to be a terminal that supports colored
-// output, false otherwise.
-bool IsColorTerminal();
-
-}  // end namespace benchmark
-
-#endif  // BENCHMARK_COLORPRINT_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/commandlineflags.cc b/vendor/core/vendor/googlebenchmark/src/commandlineflags.cc
deleted file mode 100644
index dcb414959..000000000
--- a/vendor/core/vendor/googlebenchmark/src/commandlineflags.cc
+++ /dev/null
@@ -1,298 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "commandlineflags.h"
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "../src/string_util.h"
-
-namespace benchmark {
-namespace {
-
-// Parses 'str' for a 32-bit signed integer.  If successful, writes
-// the result to *value and returns true; otherwise leaves *value
-// unchanged and returns false.
-bool ParseInt32(const std::string& src_text, const char* str, int32_t* value) {
-  // Parses the environment variable as a decimal integer.
-  char* end = nullptr;
-  const long long_value = strtol(str, &end, 10);  // NOLINT
-
-  // Has strtol() consumed all characters in the string?
-  if (*end != '\0') {
-    // No - an invalid character was encountered.
-    std::cerr << src_text << " is expected to be a 32-bit integer, "
-              << "but actually has value \"" << str << "\".\n";
-    return false;
-  }
-
-  // Is the parsed value in the range of an Int32?
-  const int32_t result = static_cast(long_value);
-  if (long_value == std::numeric_limits::max() ||
-      long_value == std::numeric_limits::min() ||
-      // The parsed value overflows as a long.  (strtol() returns
-      // LONG_MAX or LONG_MIN when the input overflows.)
-      result != long_value
-      // The parsed value overflows as an Int32.
-  ) {
-    std::cerr << src_text << " is expected to be a 32-bit integer, "
-              << "but actually has value \"" << str << "\", "
-              << "which overflows.\n";
-    return false;
-  }
-
-  *value = result;
-  return true;
-}
-
-// Parses 'str' for a double.  If successful, writes the result to *value and
-// returns true; otherwise leaves *value unchanged and returns false.
-bool ParseDouble(const std::string& src_text, const char* str, double* value) {
-  // Parses the environment variable as a decimal integer.
-  char* end = nullptr;
-  const double double_value = strtod(str, &end);  // NOLINT
-
-  // Has strtol() consumed all characters in the string?
-  if (*end != '\0') {
-    // No - an invalid character was encountered.
-    std::cerr << src_text << " is expected to be a double, "
-              << "but actually has value \"" << str << "\".\n";
-    return false;
-  }
-
-  *value = double_value;
-  return true;
-}
-
-// Parses 'str' into KV pairs. If successful, writes the result to *value and
-// returns true; otherwise leaves *value unchanged and returns false.
-bool ParseKvPairs(const std::string& src_text, const char* str,
-                  std::map* value) {
-  std::map kvs;
-  for (const auto& kvpair : StrSplit(str, ',')) {
-    const auto kv = StrSplit(kvpair, '=');
-    if (kv.size() != 2) {
-      std::cerr << src_text << " is expected to be a comma-separated list of "
-                << "= strings, but actually has value \"" << str
-                << "\".\n";
-      return false;
-    }
-    if (!kvs.emplace(kv[0], kv[1]).second) {
-      std::cerr << src_text << " is expected to contain unique keys but key \""
-                << kv[0] << "\" was repeated.\n";
-      return false;
-    }
-  }
-
-  *value = kvs;
-  return true;
-}
-
-// Returns the name of the environment variable corresponding to the
-// given flag.  For example, FlagToEnvVar("foo") will return
-// "BENCHMARK_FOO" in the open-source version.
-static std::string FlagToEnvVar(const char* flag) {
-  const std::string flag_str(flag);
-
-  std::string env_var;
-  for (size_t i = 0; i != flag_str.length(); ++i)
-    env_var += static_cast(::toupper(flag_str.c_str()[i]));
-
-  return env_var;
-}
-
-}  // namespace
-
-BENCHMARK_EXPORT
-bool BoolFromEnv(const char* flag, bool default_val) {
-  const std::string env_var = FlagToEnvVar(flag);
-  const char* const value_str = getenv(env_var.c_str());
-  return value_str == nullptr ? default_val : IsTruthyFlagValue(value_str);
-}
-
-BENCHMARK_EXPORT
-int32_t Int32FromEnv(const char* flag, int32_t default_val) {
-  const std::string env_var = FlagToEnvVar(flag);
-  const char* const value_str = getenv(env_var.c_str());
-  int32_t value = default_val;
-  if (value_str == nullptr ||
-      !ParseInt32(std::string("Environment variable ") + env_var, value_str,
-                  &value)) {
-    return default_val;
-  }
-  return value;
-}
-
-BENCHMARK_EXPORT
-double DoubleFromEnv(const char* flag, double default_val) {
-  const std::string env_var = FlagToEnvVar(flag);
-  const char* const value_str = getenv(env_var.c_str());
-  double value = default_val;
-  if (value_str == nullptr ||
-      !ParseDouble(std::string("Environment variable ") + env_var, value_str,
-                   &value)) {
-    return default_val;
-  }
-  return value;
-}
-
-BENCHMARK_EXPORT
-const char* StringFromEnv(const char* flag, const char* default_val) {
-  const std::string env_var = FlagToEnvVar(flag);
-  const char* const value = getenv(env_var.c_str());
-  return value == nullptr ? default_val : value;
-}
-
-BENCHMARK_EXPORT
-std::map KvPairsFromEnv(
-    const char* flag, std::map default_val) {
-  const std::string env_var = FlagToEnvVar(flag);
-  const char* const value_str = getenv(env_var.c_str());
-
-  if (value_str == nullptr) return default_val;
-
-  std::map value;
-  if (!ParseKvPairs("Environment variable " + env_var, value_str, &value)) {
-    return default_val;
-  }
-  return value;
-}
-
-// Parses a string as a command line flag.  The string should have
-// the format "--flag=value".  When def_optional is true, the "=value"
-// part can be omitted.
-//
-// Returns the value of the flag, or nullptr if the parsing failed.
-const char* ParseFlagValue(const char* str, const char* flag,
-                           bool def_optional) {
-  // str and flag must not be nullptr.
-  if (str == nullptr || flag == nullptr) return nullptr;
-
-  // The flag must start with "--".
-  const std::string flag_str = std::string("--") + std::string(flag);
-  const size_t flag_len = flag_str.length();
-  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return nullptr;
-
-  // Skips the flag name.
-  const char* flag_end = str + flag_len;
-
-  // When def_optional is true, it's OK to not have a "=value" part.
-  if (def_optional && (flag_end[0] == '\0')) return flag_end;
-
-  // If def_optional is true and there are more characters after the
-  // flag name, or if def_optional is false, there must be a '=' after
-  // the flag name.
-  if (flag_end[0] != '=') return nullptr;
-
-  // Returns the string after "=".
-  return flag_end + 1;
-}
-
-BENCHMARK_EXPORT
-bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
-  // Gets the value of the flag as a string.
-  const char* const value_str = ParseFlagValue(str, flag, true);
-
-  // Aborts if the parsing failed.
-  if (value_str == nullptr) return false;
-
-  // Converts the string value to a bool.
-  *value = IsTruthyFlagValue(value_str);
-  return true;
-}
-
-BENCHMARK_EXPORT
-bool ParseInt32Flag(const char* str, const char* flag, int32_t* value) {
-  // Gets the value of the flag as a string.
-  const char* const value_str = ParseFlagValue(str, flag, false);
-
-  // Aborts if the parsing failed.
-  if (value_str == nullptr) return false;
-
-  // Sets *value to the value of the flag.
-  return ParseInt32(std::string("The value of flag --") + flag, value_str,
-                    value);
-}
-
-BENCHMARK_EXPORT
-bool ParseDoubleFlag(const char* str, const char* flag, double* value) {
-  // Gets the value of the flag as a string.
-  const char* const value_str = ParseFlagValue(str, flag, false);
-
-  // Aborts if the parsing failed.
-  if (value_str == nullptr) return false;
-
-  // Sets *value to the value of the flag.
-  return ParseDouble(std::string("The value of flag --") + flag, value_str,
-                     value);
-}
-
-BENCHMARK_EXPORT
-bool ParseStringFlag(const char* str, const char* flag, std::string* value) {
-  // Gets the value of the flag as a string.
-  const char* const value_str = ParseFlagValue(str, flag, false);
-
-  // Aborts if the parsing failed.
-  if (value_str == nullptr) return false;
-
-  *value = value_str;
-  return true;
-}
-
-BENCHMARK_EXPORT
-bool ParseKeyValueFlag(const char* str, const char* flag,
-                       std::map* value) {
-  const char* const value_str = ParseFlagValue(str, flag, false);
-
-  if (value_str == nullptr) return false;
-
-  for (const auto& kvpair : StrSplit(value_str, ',')) {
-    const auto kv = StrSplit(kvpair, '=');
-    if (kv.size() != 2) return false;
-    value->emplace(kv[0], kv[1]);
-  }
-
-  return true;
-}
-
-BENCHMARK_EXPORT
-bool IsFlag(const char* str, const char* flag) {
-  return (ParseFlagValue(str, flag, true) != nullptr);
-}
-
-BENCHMARK_EXPORT
-bool IsTruthyFlagValue(const std::string& value) {
-  if (value.size() == 1) {
-    char v = value[0];
-    return isalnum(v) &&
-           !(v == '0' || v == 'f' || v == 'F' || v == 'n' || v == 'N');
-  }
-  if (!value.empty()) {
-    std::string value_lower(value);
-    std::transform(value_lower.begin(), value_lower.end(), value_lower.begin(),
-                   [](char c) { return static_cast(::tolower(c)); });
-    return !(value_lower == "false" || value_lower == "no" ||
-             value_lower == "off");
-  }
-  return true;
-}
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/commandlineflags.h b/vendor/core/vendor/googlebenchmark/src/commandlineflags.h
deleted file mode 100644
index 788262897..000000000
--- a/vendor/core/vendor/googlebenchmark/src/commandlineflags.h
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef BENCHMARK_COMMANDLINEFLAGS_H_
-#define BENCHMARK_COMMANDLINEFLAGS_H_
-
-#include 
-#include 
-#include 
-
-#include "benchmark/export.h"
-
-// Macro for referencing flags.
-#define FLAG(name) FLAGS_##name
-
-// Macros for declaring flags.
-#define BM_DECLARE_bool(name) BENCHMARK_EXPORT extern bool FLAG(name)
-#define BM_DECLARE_int32(name) BENCHMARK_EXPORT extern int32_t FLAG(name)
-#define BM_DECLARE_double(name) BENCHMARK_EXPORT extern double FLAG(name)
-#define BM_DECLARE_string(name) BENCHMARK_EXPORT extern std::string FLAG(name)
-#define BM_DECLARE_kvpairs(name) \
-  BENCHMARK_EXPORT extern std::map FLAG(name)
-
-// Macros for defining flags.
-#define BM_DEFINE_bool(name, default_val) \
-  BENCHMARK_EXPORT bool FLAG(name) = benchmark::BoolFromEnv(#name, default_val)
-#define BM_DEFINE_int32(name, default_val) \
-  BENCHMARK_EXPORT int32_t FLAG(name) =    \
-      benchmark::Int32FromEnv(#name, default_val)
-#define BM_DEFINE_double(name, default_val) \
-  BENCHMARK_EXPORT double FLAG(name) =      \
-      benchmark::DoubleFromEnv(#name, default_val)
-#define BM_DEFINE_string(name, default_val) \
-  BENCHMARK_EXPORT std::string FLAG(name) = \
-      benchmark::StringFromEnv(#name, default_val)
-#define BM_DEFINE_kvpairs(name, default_val)                       \
-  BENCHMARK_EXPORT std::map FLAG(name) = \
-      benchmark::KvPairsFromEnv(#name, default_val)
-
-namespace benchmark {
-
-// Parses a bool from the environment variable corresponding to the given flag.
-//
-// If the variable exists, returns IsTruthyFlagValue() value;  if not,
-// returns the given default value.
-BENCHMARK_EXPORT
-bool BoolFromEnv(const char* flag, bool default_val);
-
-// Parses an Int32 from the environment variable corresponding to the given
-// flag.
-//
-// If the variable exists, returns ParseInt32() value;  if not, returns
-// the given default value.
-BENCHMARK_EXPORT
-int32_t Int32FromEnv(const char* flag, int32_t default_val);
-
-// Parses an Double from the environment variable corresponding to the given
-// flag.
-//
-// If the variable exists, returns ParseDouble();  if not, returns
-// the given default value.
-BENCHMARK_EXPORT
-double DoubleFromEnv(const char* flag, double default_val);
-
-// Parses a string from the environment variable corresponding to the given
-// flag.
-//
-// If variable exists, returns its value;  if not, returns
-// the given default value.
-BENCHMARK_EXPORT
-const char* StringFromEnv(const char* flag, const char* default_val);
-
-// Parses a set of kvpairs from the environment variable corresponding to the
-// given flag.
-//
-// If variable exists, returns its value;  if not, returns
-// the given default value.
-BENCHMARK_EXPORT
-std::map KvPairsFromEnv(
-    const char* flag, std::map default_val);
-
-// Parses a string for a bool flag, in the form of either
-// "--flag=value" or "--flag".
-//
-// In the former case, the value is taken as true if it passes IsTruthyValue().
-//
-// In the latter case, the value is taken as true.
-//
-// On success, stores the value of the flag in *value, and returns
-// true.  On failure, returns false without changing *value.
-BENCHMARK_EXPORT
-bool ParseBoolFlag(const char* str, const char* flag, bool* value);
-
-// Parses a string for an Int32 flag, in the form of "--flag=value".
-//
-// On success, stores the value of the flag in *value, and returns
-// true.  On failure, returns false without changing *value.
-BENCHMARK_EXPORT
-bool ParseInt32Flag(const char* str, const char* flag, int32_t* value);
-
-// Parses a string for a Double flag, in the form of "--flag=value".
-//
-// On success, stores the value of the flag in *value, and returns
-// true.  On failure, returns false without changing *value.
-BENCHMARK_EXPORT
-bool ParseDoubleFlag(const char* str, const char* flag, double* value);
-
-// Parses a string for a string flag, in the form of "--flag=value".
-//
-// On success, stores the value of the flag in *value, and returns
-// true.  On failure, returns false without changing *value.
-BENCHMARK_EXPORT
-bool ParseStringFlag(const char* str, const char* flag, std::string* value);
-
-// Parses a string for a kvpairs flag in the form "--flag=key=value,key=value"
-//
-// On success, stores the value of the flag in *value and returns true. On
-// failure returns false, though *value may have been mutated.
-BENCHMARK_EXPORT
-bool ParseKeyValueFlag(const char* str, const char* flag,
-                       std::map* value);
-
-// Returns true if the string matches the flag.
-BENCHMARK_EXPORT
-bool IsFlag(const char* str, const char* flag);
-
-// Returns true unless value starts with one of: '0', 'f', 'F', 'n' or 'N', or
-// some non-alphanumeric character. Also returns false if the value matches
-// one of 'no', 'false', 'off' (case-insensitive). As a special case, also
-// returns true if value is the empty string.
-BENCHMARK_EXPORT
-bool IsTruthyFlagValue(const std::string& value);
-
-}  // end namespace benchmark
-
-#endif  // BENCHMARK_COMMANDLINEFLAGS_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/complexity.cc b/vendor/core/vendor/googlebenchmark/src/complexity.cc
deleted file mode 100644
index 63acd504d..000000000
--- a/vendor/core/vendor/googlebenchmark/src/complexity.cc
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright 2016 Ismael Jimenez Martinez. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Source project : https://github.com/ismaelJimenez/cpp.leastsq
-// Adapted to be used with google benchmark
-
-#include "complexity.h"
-
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-#include "check.h"
-
-namespace benchmark {
-
-// Internal function to calculate the different scalability forms
-BigOFunc* FittingCurve(BigO complexity) {
-  switch (complexity) {
-    case oN:
-      return [](IterationCount n) -> double { return static_cast(n); };
-    case oNSquared:
-      return [](IterationCount n) -> double { return std::pow(n, 2); };
-    case oNCubed:
-      return [](IterationCount n) -> double { return std::pow(n, 3); };
-    case oLogN:
-      return [](IterationCount n) -> double {
-        return std::log2(static_cast(n));
-      };
-    case oNLogN:
-      return [](IterationCount n) -> double {
-        return static_cast(n) * std::log2(static_cast(n));
-      };
-    case o1:
-    default:
-      return [](IterationCount) { return 1.0; };
-  }
-}
-
-// Function to return an string for the calculated complexity
-std::string GetBigOString(BigO complexity) {
-  switch (complexity) {
-    case oN:
-      return "N";
-    case oNSquared:
-      return "N^2";
-    case oNCubed:
-      return "N^3";
-    case oLogN:
-      return "lgN";
-    case oNLogN:
-      return "NlgN";
-    case o1:
-      return "(1)";
-    default:
-      return "f(N)";
-  }
-}
-
-// Find the coefficient for the high-order term in the running time, by
-// minimizing the sum of squares of relative error, for the fitting curve
-// given by the lambda expression.
-//   - n             : Vector containing the size of the benchmark tests.
-//   - time          : Vector containing the times for the benchmark tests.
-//   - fitting_curve : lambda expression (e.g. [](ComplexityN n) {return n; };).
-
-// For a deeper explanation on the algorithm logic, please refer to
-// https://en.wikipedia.org/wiki/Least_squares#Least_squares,_regression_analysis_and_statistics
-
-LeastSq MinimalLeastSq(const std::vector& n,
-                       const std::vector& time,
-                       BigOFunc* fitting_curve) {
-  double sigma_gn_squared = 0.0;
-  double sigma_time = 0.0;
-  double sigma_time_gn = 0.0;
-
-  // Calculate least square fitting parameter
-  for (size_t i = 0; i < n.size(); ++i) {
-    double gn_i = fitting_curve(n[i]);
-    sigma_gn_squared += gn_i * gn_i;
-    sigma_time += time[i];
-    sigma_time_gn += time[i] * gn_i;
-  }
-
-  LeastSq result;
-  result.complexity = oLambda;
-
-  // Calculate complexity.
-  result.coef = sigma_time_gn / sigma_gn_squared;
-
-  // Calculate RMS
-  double rms = 0.0;
-  for (size_t i = 0; i < n.size(); ++i) {
-    double fit = result.coef * fitting_curve(n[i]);
-    rms += std::pow((time[i] - fit), 2);
-  }
-
-  // Normalized RMS by the mean of the observed values
-  double mean = sigma_time / static_cast(n.size());
-  result.rms = std::sqrt(rms / static_cast(n.size())) / mean;
-
-  return result;
-}
-
-// Find the coefficient for the high-order term in the running time, by
-// minimizing the sum of squares of relative error.
-//   - n          : Vector containing the size of the benchmark tests.
-//   - time       : Vector containing the times for the benchmark tests.
-//   - complexity : If different than oAuto, the fitting curve will stick to
-//                  this one. If it is oAuto, it will be calculated the best
-//                  fitting curve.
-LeastSq MinimalLeastSq(const std::vector& n,
-                       const std::vector& time, const BigO complexity) {
-  BM_CHECK_EQ(n.size(), time.size());
-  BM_CHECK_GE(n.size(), 2);  // Do not compute fitting curve is less than two
-                             // benchmark runs are given
-  BM_CHECK_NE(complexity, oNone);
-
-  LeastSq best_fit;
-
-  if (complexity == oAuto) {
-    std::vector fit_curves = {oLogN, oN, oNLogN, oNSquared, oNCubed};
-
-    // Take o1 as default best fitting curve
-    best_fit = MinimalLeastSq(n, time, FittingCurve(o1));
-    best_fit.complexity = o1;
-
-    // Compute all possible fitting curves and stick to the best one
-    for (const auto& fit : fit_curves) {
-      LeastSq current_fit = MinimalLeastSq(n, time, FittingCurve(fit));
-      if (current_fit.rms < best_fit.rms) {
-        best_fit = current_fit;
-        best_fit.complexity = fit;
-      }
-    }
-  } else {
-    best_fit = MinimalLeastSq(n, time, FittingCurve(complexity));
-    best_fit.complexity = complexity;
-  }
-
-  return best_fit;
-}
-
-std::vector ComputeBigO(
-    const std::vector& reports) {
-  typedef BenchmarkReporter::Run Run;
-  std::vector results;
-
-  if (reports.size() < 2) return results;
-
-  // Accumulators.
-  std::vector n;
-  std::vector real_time;
-  std::vector cpu_time;
-
-  // Populate the accumulators.
-  for (const Run& run : reports) {
-    BM_CHECK_GT(run.complexity_n, 0)
-        << "Did you forget to call SetComplexityN?";
-    n.push_back(run.complexity_n);
-    real_time.push_back(run.real_accumulated_time /
-                        static_cast(run.iterations));
-    cpu_time.push_back(run.cpu_accumulated_time /
-                       static_cast(run.iterations));
-  }
-
-  LeastSq result_cpu;
-  LeastSq result_real;
-
-  if (reports[0].complexity == oLambda) {
-    result_cpu = MinimalLeastSq(n, cpu_time, reports[0].complexity_lambda);
-    result_real = MinimalLeastSq(n, real_time, reports[0].complexity_lambda);
-  } else {
-    const BigO* InitialBigO = &reports[0].complexity;
-    const bool use_real_time_for_initial_big_o =
-        reports[0].use_real_time_for_initial_big_o;
-    if (use_real_time_for_initial_big_o) {
-      result_real = MinimalLeastSq(n, real_time, *InitialBigO);
-      InitialBigO = &result_real.complexity;
-      // The Big-O complexity for CPU time must have the same Big-O function!
-    }
-    result_cpu = MinimalLeastSq(n, cpu_time, *InitialBigO);
-    InitialBigO = &result_cpu.complexity;
-    if (!use_real_time_for_initial_big_o) {
-      result_real = MinimalLeastSq(n, real_time, *InitialBigO);
-    }
-  }
-
-  // Drop the 'args' when reporting complexity.
-  auto run_name = reports[0].run_name;
-  run_name.args.clear();
-
-  // Get the data from the accumulator to BenchmarkReporter::Run's.
-  Run big_o;
-  big_o.run_name = run_name;
-  big_o.family_index = reports[0].family_index;
-  big_o.per_family_instance_index = reports[0].per_family_instance_index;
-  big_o.run_type = BenchmarkReporter::Run::RT_Aggregate;
-  big_o.repetitions = reports[0].repetitions;
-  big_o.repetition_index = Run::no_repetition_index;
-  big_o.threads = reports[0].threads;
-  big_o.aggregate_name = "BigO";
-  big_o.aggregate_unit = StatisticUnit::kTime;
-  big_o.report_label = reports[0].report_label;
-  big_o.iterations = 0;
-  big_o.real_accumulated_time = result_real.coef;
-  big_o.cpu_accumulated_time = result_cpu.coef;
-  big_o.report_big_o = true;
-  big_o.complexity = result_cpu.complexity;
-
-  // All the time results are reported after being multiplied by the
-  // time unit multiplier. But since RMS is a relative quantity it
-  // should not be multiplied at all. So, here, we _divide_ it by the
-  // multiplier so that when it is multiplied later the result is the
-  // correct one.
-  double multiplier = GetTimeUnitMultiplier(reports[0].time_unit);
-
-  // Only add label to mean/stddev if it is same for all runs
-  Run rms;
-  rms.run_name = run_name;
-  rms.family_index = reports[0].family_index;
-  rms.per_family_instance_index = reports[0].per_family_instance_index;
-  rms.run_type = BenchmarkReporter::Run::RT_Aggregate;
-  rms.aggregate_name = "RMS";
-  rms.aggregate_unit = StatisticUnit::kPercentage;
-  rms.report_label = big_o.report_label;
-  rms.iterations = 0;
-  rms.repetition_index = Run::no_repetition_index;
-  rms.repetitions = reports[0].repetitions;
-  rms.threads = reports[0].threads;
-  rms.real_accumulated_time = result_real.rms / multiplier;
-  rms.cpu_accumulated_time = result_cpu.rms / multiplier;
-  rms.report_rms = true;
-  rms.complexity = result_cpu.complexity;
-  // don't forget to keep the time unit, or we won't be able to
-  // recover the correct value.
-  rms.time_unit = reports[0].time_unit;
-
-  results.push_back(big_o);
-  results.push_back(rms);
-  return results;
-}
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/complexity.h b/vendor/core/vendor/googlebenchmark/src/complexity.h
deleted file mode 100644
index 0a0679b48..000000000
--- a/vendor/core/vendor/googlebenchmark/src/complexity.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2016 Ismael Jimenez Martinez. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Source project : https://github.com/ismaelJimenez/cpp.leastsq
-// Adapted to be used with google benchmark
-
-#ifndef COMPLEXITY_H_
-#define COMPLEXITY_H_
-
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-
-namespace benchmark {
-
-// Return a vector containing the bigO and RMS information for the specified
-// list of reports. If 'reports.size() < 2' an empty vector is returned.
-std::vector ComputeBigO(
-    const std::vector& reports);
-
-// This data structure will contain the result returned by MinimalLeastSq
-//   - coef        : Estimated coefficient for the high-order term as
-//                   interpolated from data.
-//   - rms         : Normalized Root Mean Squared Error.
-//   - complexity  : Scalability form (e.g. oN, oNLogN). In case a scalability
-//                   form has been provided to MinimalLeastSq this will return
-//                   the same value. In case BigO::oAuto has been selected, this
-//                   parameter will return the best fitting curve detected.
-
-struct LeastSq {
-  LeastSq() : coef(0.0), rms(0.0), complexity(oNone) {}
-
-  double coef;
-  double rms;
-  BigO complexity;
-};
-
-// Function to return an string for the calculated complexity
-std::string GetBigOString(BigO complexity);
-
-}  // end namespace benchmark
-
-#endif  // COMPLEXITY_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/console_reporter.cc b/vendor/core/vendor/googlebenchmark/src/console_reporter.cc
deleted file mode 100644
index 35c3de2a4..000000000
--- a/vendor/core/vendor/googlebenchmark/src/console_reporter.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-#include "check.h"
-#include "colorprint.h"
-#include "commandlineflags.h"
-#include "complexity.h"
-#include "counter.h"
-#include "internal_macros.h"
-#include "string_util.h"
-#include "timers.h"
-
-namespace benchmark {
-
-BENCHMARK_EXPORT
-bool ConsoleReporter::ReportContext(const Context& context) {
-  name_field_width_ = context.name_field_width;
-  printed_header_ = false;
-  prev_counters_.clear();
-
-  PrintBasicContext(&GetErrorStream(), context);
-
-#ifdef BENCHMARK_OS_WINDOWS
-  if ((output_options_ & OO_Color)) {
-    auto stdOutBuf = std::cout.rdbuf();
-    auto outStreamBuf = GetOutputStream().rdbuf();
-    if (stdOutBuf != outStreamBuf) {
-      GetErrorStream()
-          << "Color printing is only supported for stdout on windows."
-             " Disabling color printing\n";
-      output_options_ = static_cast(output_options_ & ~OO_Color);
-    }
-  }
-#endif
-
-  return true;
-}
-
-BENCHMARK_EXPORT
-void ConsoleReporter::PrintHeader(const Run& run) {
-  std::string str =
-      FormatString("%-*s %13s %15s %12s", static_cast(name_field_width_),
-                   "Benchmark", "Time", "CPU", "Iterations");
-  if (!run.counters.empty()) {
-    if (output_options_ & OO_Tabular) {
-      for (auto const& c : run.counters) {
-        str += FormatString(" %10s", c.first.c_str());
-      }
-    } else {
-      str += " UserCounters...";
-    }
-  }
-  std::string line = std::string(str.length(), '-');
-  GetOutputStream() << line << "\n" << str << "\n" << line << "\n";
-}
-
-BENCHMARK_EXPORT
-void ConsoleReporter::ReportRuns(const std::vector& reports) {
-  for (const auto& run : reports) {
-    // print the header:
-    // --- if none was printed yet
-    bool print_header = !printed_header_;
-    // --- or if the format is tabular and this run
-    //     has different fields from the prev header
-    print_header |= (output_options_ & OO_Tabular) &&
-                    (!internal::SameNames(run.counters, prev_counters_));
-    if (print_header) {
-      printed_header_ = true;
-      prev_counters_ = run.counters;
-      PrintHeader(run);
-    }
-    // As an alternative to printing the headers like this, we could sort
-    // the benchmarks by header and then print. But this would require
-    // waiting for the full results before printing, or printing twice.
-    PrintRunData(run);
-  }
-}
-
-static void IgnoreColorPrint(std::ostream& out, LogColor, const char* fmt,
-                             ...) {
-  va_list args;
-  va_start(args, fmt);
-  out << FormatString(fmt, args);
-  va_end(args);
-}
-
-static std::string FormatTime(double time) {
-  // For the time columns of the console printer 13 digits are reserved. One of
-  // them is a space and max two of them are the time unit (e.g ns). That puts
-  // us at 10 digits usable for the number.
-  // Align decimal places...
-  if (time < 1.0) {
-    return FormatString("%10.3f", time);
-  }
-  if (time < 10.0) {
-    return FormatString("%10.2f", time);
-  }
-  if (time < 100.0) {
-    return FormatString("%10.1f", time);
-  }
-  // Assuming the time is at max 9.9999e+99 and we have 10 digits for the
-  // number, we get 10-1(.)-1(e)-1(sign)-2(exponent) = 5 digits to print.
-  if (time > 9999999999 /*max 10 digit number*/) {
-    return FormatString("%1.4e", time);
-  }
-  return FormatString("%10.0f", time);
-}
-
-BENCHMARK_EXPORT
-void ConsoleReporter::PrintRunData(const Run& result) {
-  typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...);
-  auto& Out = GetOutputStream();
-  PrinterFn* printer = (output_options_ & OO_Color)
-                           ? static_cast(ColorPrintf)
-                           : IgnoreColorPrint;
-  auto name_color =
-      (result.report_big_o || result.report_rms) ? COLOR_BLUE : COLOR_GREEN;
-  printer(Out, name_color, "%-*s ", name_field_width_,
-          result.benchmark_name().c_str());
-
-  if (internal::SkippedWithError == result.skipped) {
-    printer(Out, COLOR_RED, "ERROR OCCURRED: \'%s\'",
-            result.skip_message.c_str());
-    printer(Out, COLOR_DEFAULT, "\n");
-    return;
-  } else if (internal::SkippedWithMessage == result.skipped) {
-    printer(Out, COLOR_WHITE, "SKIPPED: \'%s\'", result.skip_message.c_str());
-    printer(Out, COLOR_DEFAULT, "\n");
-    return;
-  }
-
-  const double real_time = result.GetAdjustedRealTime();
-  const double cpu_time = result.GetAdjustedCPUTime();
-  const std::string real_time_str = FormatTime(real_time);
-  const std::string cpu_time_str = FormatTime(cpu_time);
-
-  if (result.report_big_o) {
-    std::string big_o = GetBigOString(result.complexity);
-    printer(Out, COLOR_YELLOW, "%10.2f %-4s %10.2f %-4s ", real_time,
-            big_o.c_str(), cpu_time, big_o.c_str());
-  } else if (result.report_rms) {
-    printer(Out, COLOR_YELLOW, "%10.0f %-4s %10.0f %-4s ", real_time * 100, "%",
-            cpu_time * 100, "%");
-  } else if (result.run_type != Run::RT_Aggregate ||
-             result.aggregate_unit == StatisticUnit::kTime) {
-    const char* timeLabel = GetTimeUnitString(result.time_unit);
-    printer(Out, COLOR_YELLOW, "%s %-4s %s %-4s ", real_time_str.c_str(),
-            timeLabel, cpu_time_str.c_str(), timeLabel);
-  } else {
-    assert(result.aggregate_unit == StatisticUnit::kPercentage);
-    printer(Out, COLOR_YELLOW, "%10.2f %-4s %10.2f %-4s ",
-            (100. * result.real_accumulated_time), "%",
-            (100. * result.cpu_accumulated_time), "%");
-  }
-
-  if (!result.report_big_o && !result.report_rms) {
-    printer(Out, COLOR_CYAN, "%10lld", result.iterations);
-  }
-
-  for (auto& c : result.counters) {
-    const std::size_t cNameLen =
-        std::max(std::string::size_type(10), c.first.length());
-    std::string s;
-    const char* unit = "";
-    if (result.run_type == Run::RT_Aggregate &&
-        result.aggregate_unit == StatisticUnit::kPercentage) {
-      s = StrFormat("%.2f", 100. * c.second.value);
-      unit = "%";
-    } else {
-      s = HumanReadableNumber(c.second.value, c.second.oneK);
-      if (c.second.flags & Counter::kIsRate)
-        unit = (c.second.flags & Counter::kInvert) ? "s" : "/s";
-    }
-    if (output_options_ & OO_Tabular) {
-      printer(Out, COLOR_DEFAULT, " %*s%s", cNameLen - strlen(unit), s.c_str(),
-              unit);
-    } else {
-      printer(Out, COLOR_DEFAULT, " %s=%s%s", c.first.c_str(), s.c_str(), unit);
-    }
-  }
-
-  if (!result.report_label.empty()) {
-    printer(Out, COLOR_DEFAULT, " %s", result.report_label.c_str());
-  }
-
-  printer(Out, COLOR_DEFAULT, "\n");
-}
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/counter.cc b/vendor/core/vendor/googlebenchmark/src/counter.cc
deleted file mode 100644
index aa14cd809..000000000
--- a/vendor/core/vendor/googlebenchmark/src/counter.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "counter.h"
-
-namespace benchmark {
-namespace internal {
-
-double Finish(Counter const& c, IterationCount iterations, double cpu_time,
-              double num_threads) {
-  double v = c.value;
-  if (c.flags & Counter::kIsRate) {
-    v /= cpu_time;
-  }
-  if (c.flags & Counter::kAvgThreads) {
-    v /= num_threads;
-  }
-  if (c.flags & Counter::kIsIterationInvariant) {
-    v *= static_cast(iterations);
-  }
-  if (c.flags & Counter::kAvgIterations) {
-    v /= static_cast(iterations);
-  }
-
-  if (c.flags & Counter::kInvert) {  // Invert is *always* last.
-    v = 1.0 / v;
-  }
-  return v;
-}
-
-void Finish(UserCounters* l, IterationCount iterations, double cpu_time,
-            double num_threads) {
-  for (auto& c : *l) {
-    c.second.value = Finish(c.second, iterations, cpu_time, num_threads);
-  }
-}
-
-void Increment(UserCounters* l, UserCounters const& r) {
-  // add counters present in both or just in *l
-  for (auto& c : *l) {
-    auto it = r.find(c.first);
-    if (it != r.end()) {
-      c.second.value = c.second + it->second;
-    }
-  }
-  // add counters present in r, but not in *l
-  for (auto const& tc : r) {
-    auto it = l->find(tc.first);
-    if (it == l->end()) {
-      (*l)[tc.first] = tc.second;
-    }
-  }
-}
-
-bool SameNames(UserCounters const& l, UserCounters const& r) {
-  if (&l == &r) return true;
-  if (l.size() != r.size()) {
-    return false;
-  }
-  for (auto const& c : l) {
-    if (r.find(c.first) == r.end()) {
-      return false;
-    }
-  }
-  return true;
-}
-
-}  // end namespace internal
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/counter.h b/vendor/core/vendor/googlebenchmark/src/counter.h
deleted file mode 100644
index 1f5a58e31..000000000
--- a/vendor/core/vendor/googlebenchmark/src/counter.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef BENCHMARK_COUNTER_H_
-#define BENCHMARK_COUNTER_H_
-
-#include "benchmark/benchmark.h"
-
-namespace benchmark {
-
-// these counter-related functions are hidden to reduce API surface.
-namespace internal {
-void Finish(UserCounters* l, IterationCount iterations, double time,
-            double num_threads);
-void Increment(UserCounters* l, UserCounters const& r);
-bool SameNames(UserCounters const& l, UserCounters const& r);
-}  // end namespace internal
-
-}  // end namespace benchmark
-
-#endif  // BENCHMARK_COUNTER_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/csv_reporter.cc b/vendor/core/vendor/googlebenchmark/src/csv_reporter.cc
deleted file mode 100644
index 4b39e2c52..000000000
--- a/vendor/core/vendor/googlebenchmark/src/csv_reporter.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-#include "check.h"
-#include "complexity.h"
-#include "string_util.h"
-#include "timers.h"
-
-// File format reference: http://edoceo.com/utilitas/csv-file-format.
-
-namespace benchmark {
-
-namespace {
-std::vector elements = {
-    "name",           "iterations",       "real_time",        "cpu_time",
-    "time_unit",      "bytes_per_second", "items_per_second", "label",
-    "error_occurred", "error_message"};
-}  // namespace
-
-std::string CsvEscape(const std::string& s) {
-  std::string tmp;
-  tmp.reserve(s.size() + 2);
-  for (char c : s) {
-    switch (c) {
-      case '"':
-        tmp += "\"\"";
-        break;
-      default:
-        tmp += c;
-        break;
-    }
-  }
-  return '"' + tmp + '"';
-}
-
-BENCHMARK_EXPORT
-bool CSVReporter::ReportContext(const Context& context) {
-  PrintBasicContext(&GetErrorStream(), context);
-  return true;
-}
-
-BENCHMARK_EXPORT
-void CSVReporter::ReportRuns(const std::vector& reports) {
-  std::ostream& Out = GetOutputStream();
-
-  if (!printed_header_) {
-    // save the names of all the user counters
-    for (const auto& run : reports) {
-      for (const auto& cnt : run.counters) {
-        if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second")
-          continue;
-        user_counter_names_.insert(cnt.first);
-      }
-    }
-
-    // print the header
-    for (auto B = elements.begin(); B != elements.end();) {
-      Out << *B++;
-      if (B != elements.end()) Out << ",";
-    }
-    for (auto B = user_counter_names_.begin();
-         B != user_counter_names_.end();) {
-      Out << ",\"" << *B++ << "\"";
-    }
-    Out << "\n";
-
-    printed_header_ = true;
-  } else {
-    // check that all the current counters are saved in the name set
-    for (const auto& run : reports) {
-      for (const auto& cnt : run.counters) {
-        if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second")
-          continue;
-        BM_CHECK(user_counter_names_.find(cnt.first) !=
-                 user_counter_names_.end())
-            << "All counters must be present in each run. "
-            << "Counter named \"" << cnt.first
-            << "\" was not in a run after being added to the header";
-      }
-    }
-  }
-
-  // print results for each run
-  for (const auto& run : reports) {
-    PrintRunData(run);
-  }
-}
-
-BENCHMARK_EXPORT
-void CSVReporter::PrintRunData(const Run& run) {
-  std::ostream& Out = GetOutputStream();
-  Out << CsvEscape(run.benchmark_name()) << ",";
-  if (run.skipped) {
-    Out << std::string(elements.size() - 3, ',');
-    Out << std::boolalpha << (internal::SkippedWithError == run.skipped) << ",";
-    Out << CsvEscape(run.skip_message) << "\n";
-    return;
-  }
-
-  // Do not print iteration on bigO and RMS report
-  if (!run.report_big_o && !run.report_rms) {
-    Out << run.iterations;
-  }
-  Out << ",";
-
-  if (run.run_type != Run::RT_Aggregate ||
-      run.aggregate_unit == StatisticUnit::kTime) {
-    Out << run.GetAdjustedRealTime() << ",";
-    Out << run.GetAdjustedCPUTime() << ",";
-  } else {
-    assert(run.aggregate_unit == StatisticUnit::kPercentage);
-    Out << run.real_accumulated_time << ",";
-    Out << run.cpu_accumulated_time << ",";
-  }
-
-  // Do not print timeLabel on bigO and RMS report
-  if (run.report_big_o) {
-    Out << GetBigOString(run.complexity);
-  } else if (!run.report_rms &&
-             run.aggregate_unit != StatisticUnit::kPercentage) {
-    Out << GetTimeUnitString(run.time_unit);
-  }
-  Out << ",";
-
-  if (run.counters.find("bytes_per_second") != run.counters.end()) {
-    Out << run.counters.at("bytes_per_second");
-  }
-  Out << ",";
-  if (run.counters.find("items_per_second") != run.counters.end()) {
-    Out << run.counters.at("items_per_second");
-  }
-  Out << ",";
-  if (!run.report_label.empty()) {
-    Out << CsvEscape(run.report_label);
-  }
-  Out << ",,";  // for error_occurred and error_message
-
-  // Print user counters
-  for (const auto& ucn : user_counter_names_) {
-    auto it = run.counters.find(ucn);
-    if (it == run.counters.end()) {
-      Out << ",";
-    } else {
-      Out << "," << it->second;
-    }
-  }
-  Out << '\n';
-}
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/cycleclock.h b/vendor/core/vendor/googlebenchmark/src/cycleclock.h
deleted file mode 100644
index bd62f5d7e..000000000
--- a/vendor/core/vendor/googlebenchmark/src/cycleclock.h
+++ /dev/null
@@ -1,243 +0,0 @@
-// ----------------------------------------------------------------------
-// CycleClock
-//    A CycleClock tells you the current time in Cycles.  The "time"
-//    is actually time since power-on.  This is like time() but doesn't
-//    involve a system call and is much more precise.
-//
-// NOTE: Not all cpu/platform/kernel combinations guarantee that this
-// clock increments at a constant rate or is synchronized across all logical
-// cpus in a system.
-//
-// If you need the above guarantees, please consider using a different
-// API. There are efforts to provide an interface which provides a millisecond
-// granularity and implemented as a memory read. A memory read is generally
-// cheaper than the CycleClock for many architectures.
-//
-// Also, in some out of order CPU implementations, the CycleClock is not
-// serializing. So if you're trying to count at cycles granularity, your
-// data might be inaccurate due to out of order instruction execution.
-// ----------------------------------------------------------------------
-
-#ifndef BENCHMARK_CYCLECLOCK_H_
-#define BENCHMARK_CYCLECLOCK_H_
-
-#include 
-
-#include "benchmark/benchmark.h"
-#include "internal_macros.h"
-
-#if defined(BENCHMARK_OS_MACOSX)
-#include 
-#endif
-// For MSVC, we want to use '_asm rdtsc' when possible (since it works
-// with even ancient MSVC compilers), and when not possible the
-// __rdtsc intrinsic, declared in .  Unfortunately, in some
-// environments,  and  have conflicting
-// declarations of some other intrinsics, breaking compilation.
-// Therefore, we simply declare __rdtsc ourselves. See also
-// http://connect.microsoft.com/VisualStudio/feedback/details/262047
-#if defined(COMPILER_MSVC) && !defined(_M_IX86) && !defined(_M_ARM64) && \
-    !defined(_M_ARM64EC)
-extern "C" uint64_t __rdtsc();
-#pragma intrinsic(__rdtsc)
-#endif
-
-#if !defined(BENCHMARK_OS_WINDOWS) || defined(BENCHMARK_OS_MINGW)
-#include 
-#include 
-#endif
-
-#ifdef BENCHMARK_OS_EMSCRIPTEN
-#include 
-#endif
-
-namespace benchmark {
-// NOTE: only i386 and x86_64 have been well tested.
-// PPC, sparc, alpha, and ia64 are based on
-//    http://peter.kuscsik.com/wordpress/?p=14
-// with modifications by m3b.  See also
-//    https://setisvn.ssl.berkeley.edu/svn/lib/fftw-3.0.1/kernel/cycle.h
-namespace cycleclock {
-// This should return the number of cycles since power-on.  Thread-safe.
-inline BENCHMARK_ALWAYS_INLINE int64_t Now() {
-#if defined(BENCHMARK_OS_MACOSX)
-  // this goes at the top because we need ALL Macs, regardless of
-  // architecture, to return the number of "mach time units" that
-  // have passed since startup.  See sysinfo.cc where
-  // InitializeSystemInfo() sets the supposed cpu clock frequency of
-  // macs to the number of mach time units per second, not actual
-  // CPU clock frequency (which can change in the face of CPU
-  // frequency scaling).  Also note that when the Mac sleeps, this
-  // counter pauses; it does not continue counting, nor does it
-  // reset to zero.
-  return static_cast(mach_absolute_time());
-#elif defined(BENCHMARK_OS_EMSCRIPTEN)
-  // this goes above x86-specific code because old versions of Emscripten
-  // define __x86_64__, although they have nothing to do with it.
-  return static_cast(emscripten_get_now() * 1e+6);
-#elif defined(__i386__)
-  int64_t ret;
-  __asm__ volatile("rdtsc" : "=A"(ret));
-  return ret;
-#elif defined(__x86_64__) || defined(__amd64__)
-  uint64_t low, high;
-  __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
-  return static_cast((high << 32) | low);
-#elif defined(__powerpc__) || defined(__ppc__)
-  // This returns a time-base, which is not always precisely a cycle-count.
-#if defined(__powerpc64__) || defined(__ppc64__)
-  int64_t tb;
-  asm volatile("mfspr %0, 268" : "=r"(tb));
-  return tb;
-#else
-  uint32_t tbl, tbu0, tbu1;
-  asm volatile(
-      "mftbu %0\n"
-      "mftb %1\n"
-      "mftbu %2"
-      : "=r"(tbu0), "=r"(tbl), "=r"(tbu1));
-  tbl &= -static_cast(tbu0 == tbu1);
-  // high 32 bits in tbu1; low 32 bits in tbl  (tbu0 is no longer needed)
-  return (static_cast(tbu1) << 32) | tbl;
-#endif
-#elif defined(__sparc__)
-  int64_t tick;
-  asm(".byte 0x83, 0x41, 0x00, 0x00");
-  asm("mov   %%g1, %0" : "=r"(tick));
-  return tick;
-#elif defined(__ia64__)
-  int64_t itc;
-  asm("mov %0 = ar.itc" : "=r"(itc));
-  return itc;
-#elif defined(COMPILER_MSVC) && defined(_M_IX86)
-  // Older MSVC compilers (like 7.x) don't seem to support the
-  // __rdtsc intrinsic properly, so I prefer to use _asm instead
-  // when I know it will work.  Otherwise, I'll use __rdtsc and hope
-  // the code is being compiled with a non-ancient compiler.
-  _asm rdtsc
-#elif defined(COMPILER_MSVC) && (defined(_M_ARM64) || defined(_M_ARM64EC))
-  // See // https://docs.microsoft.com/en-us/cpp/intrinsics/arm64-intrinsics
-  // and https://reviews.llvm.org/D53115
-  int64_t virtual_timer_value;
-  virtual_timer_value = _ReadStatusReg(ARM64_CNTVCT);
-  return virtual_timer_value;
-#elif defined(COMPILER_MSVC)
-  return __rdtsc();
-#elif defined(BENCHMARK_OS_NACL)
-  // Native Client validator on x86/x86-64 allows RDTSC instructions,
-  // and this case is handled above. Native Client validator on ARM
-  // rejects MRC instructions (used in the ARM-specific sequence below),
-  // so we handle it here. Portable Native Client compiles to
-  // architecture-agnostic bytecode, which doesn't provide any
-  // cycle counter access mnemonics.
-
-  // Native Client does not provide any API to access cycle counter.
-  // Use clock_gettime(CLOCK_MONOTONIC, ...) instead of gettimeofday
-  // because is provides nanosecond resolution (which is noticeable at
-  // least for PNaCl modules running on x86 Mac & Linux).
-  // Initialize to always return 0 if clock_gettime fails.
-  struct timespec ts = {0, 0};
-  clock_gettime(CLOCK_MONOTONIC, &ts);
-  return static_cast(ts.tv_sec) * 1000000000 + ts.tv_nsec;
-#elif defined(__aarch64__)
-  // System timer of ARMv8 runs at a different frequency than the CPU's.
-  // The frequency is fixed, typically in the range 1-50MHz.  It can be
-  // read at CNTFRQ special register.  We assume the OS has set up
-  // the virtual timer properly.
-  int64_t virtual_timer_value;
-  asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
-  return virtual_timer_value;
-#elif defined(__ARM_ARCH)
-  // V6 is the earliest arch that has a standard cyclecount
-  // Native Client validator doesn't allow MRC instructions.
-#if (__ARM_ARCH >= 6)
-  uint32_t pmccntr;
-  uint32_t pmuseren;
-  uint32_t pmcntenset;
-  // Read the user mode perf monitor counter access permissions.
-  asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren));
-  if (pmuseren & 1) {  // Allows reading perfmon counters for user mode code.
-    asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset));
-    if (pmcntenset & 0x80000000ul) {  // Is it counting?
-      asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));
-      // The counter is set up to count every 64th cycle
-      return static_cast(pmccntr) * 64;  // Should optimize to << 6
-    }
-  }
-#endif
-  struct timeval tv;
-  gettimeofday(&tv, nullptr);
-  return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec;
-#elif defined(__mips__) || defined(__m68k__)
-  // mips apparently only allows rdtsc for superusers, so we fall
-  // back to gettimeofday.  It's possible clock_gettime would be better.
-  struct timeval tv;
-  gettimeofday(&tv, nullptr);
-  return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec;
-#elif defined(__loongarch__) || defined(__csky__)
-  struct timeval tv;
-  gettimeofday(&tv, nullptr);
-  return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec;
-#elif defined(__s390__)  // Covers both s390 and s390x.
-  // Return the CPU clock.
-  uint64_t tsc;
-#if defined(BENCHMARK_OS_ZOS)
-  // z/OS HLASM syntax.
-  asm(" stck %0" : "=m"(tsc) : : "cc");
-#else
-  // Linux on Z syntax.
-  asm("stck %0" : "=Q"(tsc) : : "cc");
-#endif
-  return tsc;
-#elif defined(__riscv)  // RISC-V
-  // Use RDTIME (and RDTIMEH on riscv32).
-  // RDCYCLE is a privileged instruction since Linux 6.6.
-#if __riscv_xlen == 32
-  uint32_t cycles_lo, cycles_hi0, cycles_hi1;
-  // This asm also includes the PowerPC overflow handling strategy, as above.
-  // Implemented in assembly because Clang insisted on branching.
-  asm volatile(
-      "rdtimeh %0\n"
-      "rdtime %1\n"
-      "rdtimeh %2\n"
-      "sub %0, %0, %2\n"
-      "seqz %0, %0\n"
-      "sub %0, zero, %0\n"
-      "and %1, %1, %0\n"
-      : "=r"(cycles_hi0), "=r"(cycles_lo), "=r"(cycles_hi1));
-  return static_cast((static_cast(cycles_hi1) << 32) |
-                              cycles_lo);
-#else
-  uint64_t cycles;
-  asm volatile("rdtime %0" : "=r"(cycles));
-  return static_cast(cycles);
-#endif
-#elif defined(__e2k__) || defined(__elbrus__)
-  struct timeval tv;
-  gettimeofday(&tv, nullptr);
-  return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec;
-#elif defined(__hexagon__)
-  uint64_t pcycle;
-  asm volatile("%0 = C15:14" : "=r"(pcycle));
-  return static_cast(pcycle);
-#elif defined(__alpha__)
-  // Alpha has a cycle counter, the PCC register, but it is an unsigned 32-bit
-  // integer and thus wraps every ~4s, making using it for tick counts
-  // unreliable beyond this time range.  The real-time clock is low-precision,
-  // roughtly ~1ms, but it is the only option that can reasonable count
-  // indefinitely.
-  struct timeval tv;
-  gettimeofday(&tv, nullptr);
-  return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec;
-#else
-  // The soft failover to a generic implementation is automatic only for ARM.
-  // For other platforms the developer is expected to make an attempt to create
-  // a fast implementation and use generic version if nothing better is
-  // available.
-#error You need to define CycleTimer for your OS and CPU
-#endif
-}
-}  // end namespace cycleclock
-}  // end namespace benchmark
-
-#endif  // BENCHMARK_CYCLECLOCK_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/internal_macros.h b/vendor/core/vendor/googlebenchmark/src/internal_macros.h
deleted file mode 100644
index f4894ba8e..000000000
--- a/vendor/core/vendor/googlebenchmark/src/internal_macros.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifndef BENCHMARK_INTERNAL_MACROS_H_
-#define BENCHMARK_INTERNAL_MACROS_H_
-
-/* Needed to detect STL */
-#include 
-
-// clang-format off
-
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-
-#if defined(__clang__)
-  #if !defined(COMPILER_CLANG)
-    #define COMPILER_CLANG
-  #endif
-#elif defined(_MSC_VER)
-  #if !defined(COMPILER_MSVC)
-    #define COMPILER_MSVC
-  #endif
-#elif defined(__GNUC__)
-  #if !defined(COMPILER_GCC)
-    #define COMPILER_GCC
-  #endif
-#endif
-
-#if __has_feature(cxx_attributes)
-  #define BENCHMARK_NORETURN [[noreturn]]
-#elif defined(__GNUC__)
-  #define BENCHMARK_NORETURN __attribute__((noreturn))
-#elif defined(COMPILER_MSVC)
-  #define BENCHMARK_NORETURN __declspec(noreturn)
-#else
-  #define BENCHMARK_NORETURN
-#endif
-
-#if defined(__CYGWIN__)
-  #define BENCHMARK_OS_CYGWIN 1
-#elif defined(_WIN32)
-  #define BENCHMARK_OS_WINDOWS 1
-  // WINAPI_FAMILY_PARTITION is defined in winapifamily.h.
-  // We include windows.h which implicitly includes winapifamily.h for compatibility.
-  #ifndef NOMINMAX
-    #define NOMINMAX
-  #endif
-  #include 
-  #if defined(WINAPI_FAMILY_PARTITION)
-    #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
-      #define BENCHMARK_OS_WINDOWS_WIN32 1
-    #elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
-      #define BENCHMARK_OS_WINDOWS_RT 1
-    #endif
-  #endif
-  #if defined(__MINGW32__)
-    #define BENCHMARK_OS_MINGW 1
-  #endif
-#elif defined(__APPLE__)
-  #define BENCHMARK_OS_APPLE 1
-  #include "TargetConditionals.h"
-  #if defined(TARGET_OS_MAC)
-    #define BENCHMARK_OS_MACOSX 1
-    #if defined(TARGET_OS_IPHONE)
-      #define BENCHMARK_OS_IOS 1
-    #endif
-  #endif
-#elif defined(__FreeBSD__)
-  #define BENCHMARK_OS_FREEBSD 1
-#elif defined(__NetBSD__)
-  #define BENCHMARK_OS_NETBSD 1
-#elif defined(__OpenBSD__)
-  #define BENCHMARK_OS_OPENBSD 1
-#elif defined(__DragonFly__)
-  #define BENCHMARK_OS_DRAGONFLY 1
-#elif defined(__linux__)
-  #define BENCHMARK_OS_LINUX 1
-#elif defined(__native_client__)
-  #define BENCHMARK_OS_NACL 1
-#elif defined(__EMSCRIPTEN__)
-  #define BENCHMARK_OS_EMSCRIPTEN 1
-#elif defined(__rtems__)
-  #define BENCHMARK_OS_RTEMS 1
-#elif defined(__Fuchsia__)
-#define BENCHMARK_OS_FUCHSIA 1
-#elif defined (__SVR4) && defined (__sun)
-#define BENCHMARK_OS_SOLARIS 1
-#elif defined(__QNX__)
-#define BENCHMARK_OS_QNX 1
-#elif defined(__MVS__)
-#define BENCHMARK_OS_ZOS 1
-#elif defined(__hexagon__)
-#define BENCHMARK_OS_QURT 1
-#endif
-
-#if defined(__ANDROID__) && defined(__GLIBCXX__)
-#define BENCHMARK_STL_ANDROID_GNUSTL 1
-#endif
-
-#if !__has_feature(cxx_exceptions) && !defined(__cpp_exceptions) \
-     && !defined(__EXCEPTIONS)
-  #define BENCHMARK_HAS_NO_EXCEPTIONS
-#endif
-
-#if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
-  #define BENCHMARK_MAYBE_UNUSED __attribute__((unused))
-#else
-  #define BENCHMARK_MAYBE_UNUSED
-#endif
-
-// clang-format on
-
-#endif  // BENCHMARK_INTERNAL_MACROS_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/json_reporter.cc b/vendor/core/vendor/googlebenchmark/src/json_reporter.cc
deleted file mode 100644
index b8c8c94c0..000000000
--- a/vendor/core/vendor/googlebenchmark/src/json_reporter.cc
+++ /dev/null
@@ -1,327 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include 
-#include 
-#include 
-#include   // for setprecision
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-#include "complexity.h"
-#include "string_util.h"
-#include "timers.h"
-
-namespace benchmark {
-namespace {
-
-std::string StrEscape(const std::string& s) {
-  std::string tmp;
-  tmp.reserve(s.size());
-  for (char c : s) {
-    switch (c) {
-      case '\b':
-        tmp += "\\b";
-        break;
-      case '\f':
-        tmp += "\\f";
-        break;
-      case '\n':
-        tmp += "\\n";
-        break;
-      case '\r':
-        tmp += "\\r";
-        break;
-      case '\t':
-        tmp += "\\t";
-        break;
-      case '\\':
-        tmp += "\\\\";
-        break;
-      case '"':
-        tmp += "\\\"";
-        break;
-      default:
-        tmp += c;
-        break;
-    }
-  }
-  return tmp;
-}
-
-std::string FormatKV(std::string const& key, std::string const& value) {
-  return StrFormat("\"%s\": \"%s\"", StrEscape(key).c_str(),
-                   StrEscape(value).c_str());
-}
-
-std::string FormatKV(std::string const& key, const char* value) {
-  return StrFormat("\"%s\": \"%s\"", StrEscape(key).c_str(),
-                   StrEscape(value).c_str());
-}
-
-std::string FormatKV(std::string const& key, bool value) {
-  return StrFormat("\"%s\": %s", StrEscape(key).c_str(),
-                   value ? "true" : "false");
-}
-
-std::string FormatKV(std::string const& key, int64_t value) {
-  std::stringstream ss;
-  ss << '"' << StrEscape(key) << "\": " << value;
-  return ss.str();
-}
-
-std::string FormatKV(std::string const& key, double value) {
-  std::stringstream ss;
-  ss << '"' << StrEscape(key) << "\": ";
-
-  if (std::isnan(value))
-    ss << (value < 0 ? "-" : "") << "NaN";
-  else if (std::isinf(value))
-    ss << (value < 0 ? "-" : "") << "Infinity";
-  else {
-    const auto max_digits10 =
-        std::numeric_limits::max_digits10;
-    const auto max_fractional_digits10 = max_digits10 - 1;
-    ss << std::scientific << std::setprecision(max_fractional_digits10)
-       << value;
-  }
-  return ss.str();
-}
-
-int64_t RoundDouble(double v) { return std::lround(v); }
-
-}  // end namespace
-
-bool JSONReporter::ReportContext(const Context& context) {
-  std::ostream& out = GetOutputStream();
-
-  out << "{\n";
-  std::string inner_indent(2, ' ');
-
-  // Open context block and print context information.
-  out << inner_indent << "\"context\": {\n";
-  std::string indent(4, ' ');
-
-  std::string walltime_value = LocalDateTimeString();
-  out << indent << FormatKV("date", walltime_value) << ",\n";
-
-  out << indent << FormatKV("host_name", context.sys_info.name) << ",\n";
-
-  if (Context::executable_name) {
-    out << indent << FormatKV("executable", Context::executable_name) << ",\n";
-  }
-
-  CPUInfo const& info = context.cpu_info;
-  out << indent << FormatKV("num_cpus", static_cast(info.num_cpus))
-      << ",\n";
-  out << indent
-      << FormatKV("mhz_per_cpu",
-                  RoundDouble(info.cycles_per_second / 1000000.0))
-      << ",\n";
-  if (CPUInfo::Scaling::UNKNOWN != info.scaling) {
-    out << indent
-        << FormatKV("cpu_scaling_enabled",
-                    info.scaling == CPUInfo::Scaling::ENABLED ? true : false)
-        << ",\n";
-  }
-
-  out << indent << "\"caches\": [\n";
-  indent = std::string(6, ' ');
-  std::string cache_indent(8, ' ');
-  for (size_t i = 0; i < info.caches.size(); ++i) {
-    auto& CI = info.caches[i];
-    out << indent << "{\n";
-    out << cache_indent << FormatKV("type", CI.type) << ",\n";
-    out << cache_indent << FormatKV("level", static_cast(CI.level))
-        << ",\n";
-    out << cache_indent << FormatKV("size", static_cast(CI.size))
-        << ",\n";
-    out << cache_indent
-        << FormatKV("num_sharing", static_cast(CI.num_sharing))
-        << "\n";
-    out << indent << "}";
-    if (i != info.caches.size() - 1) out << ",";
-    out << "\n";
-  }
-  indent = std::string(4, ' ');
-  out << indent << "],\n";
-  out << indent << "\"load_avg\": [";
-  for (auto it = info.load_avg.begin(); it != info.load_avg.end();) {
-    out << *it++;
-    if (it != info.load_avg.end()) out << ",";
-  }
-  out << "],\n";
-
-  out << indent << FormatKV("library_version", GetBenchmarkVersion());
-  out << ",\n";
-
-#if defined(NDEBUG)
-  const char build_type[] = "release";
-#else
-  const char build_type[] = "debug";
-#endif
-  out << indent << FormatKV("library_build_type", build_type);
-  out << ",\n";
-
-  // NOTE: our json schema is not strictly tied to the library version!
-  out << indent << FormatKV("json_schema_version", int64_t(1));
-
-  std::map* global_context =
-      internal::GetGlobalContext();
-
-  if (global_context != nullptr) {
-    for (const auto& kv : *global_context) {
-      out << ",\n";
-      out << indent << FormatKV(kv.first, kv.second);
-    }
-  }
-  out << "\n";
-
-  // Close context block and open the list of benchmarks.
-  out << inner_indent << "},\n";
-  out << inner_indent << "\"benchmarks\": [\n";
-  return true;
-}
-
-void JSONReporter::ReportRuns(std::vector const& reports) {
-  if (reports.empty()) {
-    return;
-  }
-  std::string indent(4, ' ');
-  std::ostream& out = GetOutputStream();
-  if (!first_report_) {
-    out << ",\n";
-  }
-  first_report_ = false;
-
-  for (auto it = reports.begin(); it != reports.end(); ++it) {
-    out << indent << "{\n";
-    PrintRunData(*it);
-    out << indent << '}';
-    auto it_cp = it;
-    if (++it_cp != reports.end()) {
-      out << ",\n";
-    }
-  }
-}
-
-void JSONReporter::Finalize() {
-  // Close the list of benchmarks and the top level object.
-  GetOutputStream() << "\n  ]\n}\n";
-}
-
-void JSONReporter::PrintRunData(Run const& run) {
-  std::string indent(6, ' ');
-  std::ostream& out = GetOutputStream();
-  out << indent << FormatKV("name", run.benchmark_name()) << ",\n";
-  out << indent << FormatKV("family_index", run.family_index) << ",\n";
-  out << indent
-      << FormatKV("per_family_instance_index", run.per_family_instance_index)
-      << ",\n";
-  out << indent << FormatKV("run_name", run.run_name.str()) << ",\n";
-  out << indent << FormatKV("run_type", [&run]() -> const char* {
-    switch (run.run_type) {
-      case BenchmarkReporter::Run::RT_Iteration:
-        return "iteration";
-      case BenchmarkReporter::Run::RT_Aggregate:
-        return "aggregate";
-    }
-    BENCHMARK_UNREACHABLE();
-  }()) << ",\n";
-  out << indent << FormatKV("repetitions", run.repetitions) << ",\n";
-  if (run.run_type != BenchmarkReporter::Run::RT_Aggregate) {
-    out << indent << FormatKV("repetition_index", run.repetition_index)
-        << ",\n";
-  }
-  out << indent << FormatKV("threads", run.threads) << ",\n";
-  if (run.run_type == BenchmarkReporter::Run::RT_Aggregate) {
-    out << indent << FormatKV("aggregate_name", run.aggregate_name) << ",\n";
-    out << indent << FormatKV("aggregate_unit", [&run]() -> const char* {
-      switch (run.aggregate_unit) {
-        case StatisticUnit::kTime:
-          return "time";
-        case StatisticUnit::kPercentage:
-          return "percentage";
-      }
-      BENCHMARK_UNREACHABLE();
-    }()) << ",\n";
-  }
-  if (internal::SkippedWithError == run.skipped) {
-    out << indent << FormatKV("error_occurred", true) << ",\n";
-    out << indent << FormatKV("error_message", run.skip_message) << ",\n";
-  } else if (internal::SkippedWithMessage == run.skipped) {
-    out << indent << FormatKV("skipped", true) << ",\n";
-    out << indent << FormatKV("skip_message", run.skip_message) << ",\n";
-  }
-  if (!run.report_big_o && !run.report_rms) {
-    out << indent << FormatKV("iterations", run.iterations) << ",\n";
-    if (run.run_type != Run::RT_Aggregate ||
-        run.aggregate_unit == StatisticUnit::kTime) {
-      out << indent << FormatKV("real_time", run.GetAdjustedRealTime())
-          << ",\n";
-      out << indent << FormatKV("cpu_time", run.GetAdjustedCPUTime());
-    } else {
-      assert(run.aggregate_unit == StatisticUnit::kPercentage);
-      out << indent << FormatKV("real_time", run.real_accumulated_time)
-          << ",\n";
-      out << indent << FormatKV("cpu_time", run.cpu_accumulated_time);
-    }
-    out << ",\n"
-        << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit));
-  } else if (run.report_big_o) {
-    out << indent << FormatKV("cpu_coefficient", run.GetAdjustedCPUTime())
-        << ",\n";
-    out << indent << FormatKV("real_coefficient", run.GetAdjustedRealTime())
-        << ",\n";
-    out << indent << FormatKV("big_o", GetBigOString(run.complexity)) << ",\n";
-    out << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit));
-  } else if (run.report_rms) {
-    out << indent << FormatKV("rms", run.GetAdjustedCPUTime());
-  }
-
-  for (auto& c : run.counters) {
-    out << ",\n" << indent << FormatKV(c.first, c.second);
-  }
-
-  if (run.memory_result) {
-    const MemoryManager::Result memory_result = *run.memory_result;
-    out << ",\n" << indent << FormatKV("allocs_per_iter", run.allocs_per_iter);
-    out << ",\n"
-        << indent << FormatKV("max_bytes_used", memory_result.max_bytes_used);
-
-    auto report_if_present = [&out, &indent](const std::string& label,
-                                             int64_t val) {
-      if (val != MemoryManager::TombstoneValue)
-        out << ",\n" << indent << FormatKV(label, val);
-    };
-
-    report_if_present("total_allocated_bytes",
-                      memory_result.total_allocated_bytes);
-    report_if_present("net_heap_growth", memory_result.net_heap_growth);
-  }
-
-  if (!run.report_label.empty()) {
-    out << ",\n" << indent << FormatKV("label", run.report_label);
-  }
-  out << '\n';
-}
-
-const int64_t MemoryManager::TombstoneValue =
-    std::numeric_limits::max();
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/log.h b/vendor/core/vendor/googlebenchmark/src/log.h
deleted file mode 100644
index 9a21400b0..000000000
--- a/vendor/core/vendor/googlebenchmark/src/log.h
+++ /dev/null
@@ -1,88 +0,0 @@
-#ifndef BENCHMARK_LOG_H_
-#define BENCHMARK_LOG_H_
-
-#include 
-#include 
-
-// NOTE: this is also defined in benchmark.h but we're trying to avoid a
-// dependency.
-// The _MSVC_LANG check should detect Visual Studio 2015 Update 3 and newer.
-#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
-#define BENCHMARK_HAS_CXX11
-#endif
-
-namespace benchmark {
-namespace internal {
-
-typedef std::basic_ostream&(EndLType)(std::basic_ostream&);
-
-class LogType {
-  friend LogType& GetNullLogInstance();
-  friend LogType& GetErrorLogInstance();
-
-  // FIXME: Add locking to output.
-  template 
-  friend LogType& operator<<(LogType&, Tp const&);
-  friend LogType& operator<<(LogType&, EndLType*);
-
- private:
-  LogType(std::ostream* out) : out_(out) {}
-  std::ostream* out_;
-
-  // NOTE: we could use BENCHMARK_DISALLOW_COPY_AND_ASSIGN but we shouldn't have
-  // a dependency on benchmark.h from here.
-#ifndef BENCHMARK_HAS_CXX11
-  LogType(const LogType&);
-  LogType& operator=(const LogType&);
-#else
-  LogType(const LogType&) = delete;
-  LogType& operator=(const LogType&) = delete;
-#endif
-};
-
-template 
-LogType& operator<<(LogType& log, Tp const& value) {
-  if (log.out_) {
-    *log.out_ << value;
-  }
-  return log;
-}
-
-inline LogType& operator<<(LogType& log, EndLType* m) {
-  if (log.out_) {
-    *log.out_ << m;
-  }
-  return log;
-}
-
-inline int& LogLevel() {
-  static int log_level = 0;
-  return log_level;
-}
-
-inline LogType& GetNullLogInstance() {
-  static LogType null_log(static_cast(nullptr));
-  return null_log;
-}
-
-inline LogType& GetErrorLogInstance() {
-  static LogType error_log(&std::clog);
-  return error_log;
-}
-
-inline LogType& GetLogInstanceForLevel(int level) {
-  if (level <= LogLevel()) {
-    return GetErrorLogInstance();
-  }
-  return GetNullLogInstance();
-}
-
-}  // end namespace internal
-}  // end namespace benchmark
-
-// clang-format off
-#define BM_VLOG(x)                                                               \
-  (::benchmark::internal::GetLogInstanceForLevel(x) << "-- LOG(" << x << "):" \
-                                                                         " ")
-// clang-format on
-#endif
diff --git a/vendor/core/vendor/googlebenchmark/src/mutex.h b/vendor/core/vendor/googlebenchmark/src/mutex.h
deleted file mode 100644
index bec78d9e5..000000000
--- a/vendor/core/vendor/googlebenchmark/src/mutex.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#ifndef BENCHMARK_MUTEX_H_
-#define BENCHMARK_MUTEX_H_
-
-#include 
-#include 
-
-#include "check.h"
-
-// Enable thread safety attributes only with clang.
-// The attributes can be safely erased when compiling with other compilers.
-#if defined(HAVE_THREAD_SAFETY_ATTRIBUTES)
-#define THREAD_ANNOTATION_ATTRIBUTE_(x) __attribute__((x))
-#else
-#define THREAD_ANNOTATION_ATTRIBUTE_(x)  // no-op
-#endif
-
-#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(capability(x))
-
-#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE_(scoped_lockable)
-
-#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE_(guarded_by(x))
-
-#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE_(pt_guarded_by(x))
-
-#define ACQUIRED_BEFORE(...) \
-  THREAD_ANNOTATION_ATTRIBUTE_(acquired_before(__VA_ARGS__))
-
-#define ACQUIRED_AFTER(...) \
-  THREAD_ANNOTATION_ATTRIBUTE_(acquired_after(__VA_ARGS__))
-
-#define REQUIRES(...) \
-  THREAD_ANNOTATION_ATTRIBUTE_(requires_capability(__VA_ARGS__))
-
-#define REQUIRES_SHARED(...) \
-  THREAD_ANNOTATION_ATTRIBUTE_(requires_shared_capability(__VA_ARGS__))
-
-#define ACQUIRE(...) \
-  THREAD_ANNOTATION_ATTRIBUTE_(acquire_capability(__VA_ARGS__))
-
-#define ACQUIRE_SHARED(...) \
-  THREAD_ANNOTATION_ATTRIBUTE_(acquire_shared_capability(__VA_ARGS__))
-
-#define RELEASE(...) \
-  THREAD_ANNOTATION_ATTRIBUTE_(release_capability(__VA_ARGS__))
-
-#define RELEASE_SHARED(...) \
-  THREAD_ANNOTATION_ATTRIBUTE_(release_shared_capability(__VA_ARGS__))
-
-#define TRY_ACQUIRE(...) \
-  THREAD_ANNOTATION_ATTRIBUTE_(try_acquire_capability(__VA_ARGS__))
-
-#define TRY_ACQUIRE_SHARED(...) \
-  THREAD_ANNOTATION_ATTRIBUTE_(try_acquire_shared_capability(__VA_ARGS__))
-
-#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE_(locks_excluded(__VA_ARGS__))
-
-#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(assert_capability(x))
-
-#define ASSERT_SHARED_CAPABILITY(x) \
-  THREAD_ANNOTATION_ATTRIBUTE_(assert_shared_capability(x))
-
-#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE_(lock_returned(x))
-
-#define NO_THREAD_SAFETY_ANALYSIS \
-  THREAD_ANNOTATION_ATTRIBUTE_(no_thread_safety_analysis)
-
-namespace benchmark {
-
-typedef std::condition_variable Condition;
-
-// NOTE: Wrappers for std::mutex and std::unique_lock are provided so that
-// we can annotate them with thread safety attributes and use the
-// -Wthread-safety warning with clang. The standard library types cannot be
-// used directly because they do not provide the required annotations.
-class CAPABILITY("mutex") Mutex {
- public:
-  Mutex() {}
-
-  void lock() ACQUIRE() { mut_.lock(); }
-  void unlock() RELEASE() { mut_.unlock(); }
-  std::mutex& native_handle() { return mut_; }
-
- private:
-  std::mutex mut_;
-};
-
-class SCOPED_CAPABILITY MutexLock {
-  typedef std::unique_lock MutexLockImp;
-
- public:
-  MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle()) {}
-  ~MutexLock() RELEASE() {}
-  MutexLockImp& native_handle() { return ml_; }
-
- private:
-  MutexLockImp ml_;
-};
-
-class Barrier {
- public:
-  Barrier(int num_threads) : running_threads_(num_threads) {}
-
-  // Called by each thread
-  bool wait() EXCLUDES(lock_) {
-    bool last_thread = false;
-    {
-      MutexLock ml(lock_);
-      last_thread = createBarrier(ml);
-    }
-    if (last_thread) phase_condition_.notify_all();
-    return last_thread;
-  }
-
-  void removeThread() EXCLUDES(lock_) {
-    MutexLock ml(lock_);
-    --running_threads_;
-    if (entered_ != 0) phase_condition_.notify_all();
-  }
-
- private:
-  Mutex lock_;
-  Condition phase_condition_;
-  int running_threads_;
-
-  // State for barrier management
-  int phase_number_ = 0;
-  int entered_ = 0;  // Number of threads that have entered this barrier
-
-  // Enter the barrier and wait until all other threads have also
-  // entered the barrier.  Returns iff this is the last thread to
-  // enter the barrier.
-  bool createBarrier(MutexLock& ml) REQUIRES(lock_) {
-    BM_CHECK_LT(entered_, running_threads_);
-    entered_++;
-    if (entered_ < running_threads_) {
-      // Wait for all threads to enter
-      int phase_number_cp = phase_number_;
-      auto cb = [this, phase_number_cp]() {
-        return this->phase_number_ > phase_number_cp ||
-               entered_ == running_threads_;  // A thread has aborted in error
-      };
-      phase_condition_.wait(ml.native_handle(), cb);
-      if (phase_number_ > phase_number_cp) return false;
-      // else (running_threads_ == entered_) and we are the last thread.
-    }
-    // Last thread has reached the barrier
-    phase_number_++;
-    entered_ = 0;
-    return true;
-  }
-};
-
-}  // end namespace benchmark
-
-#endif  // BENCHMARK_MUTEX_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/perf_counters.cc b/vendor/core/vendor/googlebenchmark/src/perf_counters.cc
deleted file mode 100644
index fa1cbb0e8..000000000
--- a/vendor/core/vendor/googlebenchmark/src/perf_counters.cc
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "perf_counters.h"
-
-#include 
-#include 
-#include 
-
-#if defined HAVE_LIBPFM
-#include "perfmon/pfmlib.h"
-#include "perfmon/pfmlib_perf_event.h"
-#endif
-
-namespace benchmark {
-namespace internal {
-
-constexpr size_t PerfCounterValues::kMaxCounters;
-
-#if defined HAVE_LIBPFM
-
-size_t PerfCounterValues::Read(const std::vector& leaders) {
-  // Create a pointer for multiple reads
-  const size_t bufsize = values_.size() * sizeof(values_[0]);
-  char* ptr = reinterpret_cast(values_.data());
-  size_t size = bufsize;
-  for (int lead : leaders) {
-    auto read_bytes = ::read(lead, ptr, size);
-    if (read_bytes >= ssize_t(sizeof(uint64_t))) {
-      // Actual data bytes are all bytes minus initial padding
-      std::size_t data_bytes =
-          static_cast(read_bytes) - sizeof(uint64_t);
-      // This should be very cheap since it's in hot cache
-      std::memmove(ptr, ptr + sizeof(uint64_t), data_bytes);
-      // Increment our counters
-      ptr += data_bytes;
-      size -= data_bytes;
-    } else {
-      int err = errno;
-      GetErrorLogInstance() << "Error reading lead " << lead << " errno:" << err
-                            << " " << ::strerror(err) << "\n";
-      return 0;
-    }
-  }
-  return (bufsize - size) / sizeof(uint64_t);
-}
-
-const bool PerfCounters::kSupported = true;
-
-// Initializes libpfm only on the first call.  Returns whether that single
-// initialization was successful.
-bool PerfCounters::Initialize() {
-  // Function-scope static gets initialized only once on first call.
-  static const bool success = []() {
-    return pfm_initialize() == PFM_SUCCESS;
-  }();
-  return success;
-}
-
-bool PerfCounters::IsCounterSupported(const std::string& name) {
-  Initialize();
-  perf_event_attr_t attr;
-  std::memset(&attr, 0, sizeof(attr));
-  pfm_perf_encode_arg_t arg;
-  std::memset(&arg, 0, sizeof(arg));
-  arg.attr = &attr;
-  const int mode = PFM_PLM3;  // user mode only
-  int ret = pfm_get_os_event_encoding(name.c_str(), mode, PFM_OS_PERF_EVENT_EXT,
-                                      &arg);
-  return (ret == PFM_SUCCESS);
-}
-
-PerfCounters PerfCounters::Create(
-    const std::vector& counter_names) {
-  if (!counter_names.empty()) {
-    Initialize();
-  }
-
-  // Valid counters will populate these arrays but we start empty
-  std::vector valid_names;
-  std::vector counter_ids;
-  std::vector leader_ids;
-
-  // Resize to the maximum possible
-  valid_names.reserve(counter_names.size());
-  counter_ids.reserve(counter_names.size());
-
-  const int kCounterMode = PFM_PLM3;  // user mode only
-
-  // Group leads will be assigned on demand. The idea is that once we cannot
-  // create a counter descriptor, the reason is that this group has maxed out
-  // so we set the group_id again to -1 and retry - giving the algorithm a
-  // chance to create a new group leader to hold the next set of counters.
-  int group_id = -1;
-
-  // Loop through all performance counters
-  for (size_t i = 0; i < counter_names.size(); ++i) {
-    // we are about to push into the valid names vector
-    // check if we did not reach the maximum
-    if (valid_names.size() == PerfCounterValues::kMaxCounters) {
-      // Log a message if we maxed out and stop adding
-      GetErrorLogInstance()
-          << counter_names.size() << " counters were requested. The maximum is "
-          << PerfCounterValues::kMaxCounters << " and " << valid_names.size()
-          << " were already added. All remaining counters will be ignored\n";
-      // stop the loop and return what we have already
-      break;
-    }
-
-    // Check if this name is empty
-    const auto& name = counter_names[i];
-    if (name.empty()) {
-      GetErrorLogInstance()
-          << "A performance counter name was the empty string\n";
-      continue;
-    }
-
-    // Here first means first in group, ie the group leader
-    const bool is_first = (group_id < 0);
-
-    // This struct will be populated by libpfm from the counter string
-    // and then fed into the syscall perf_event_open
-    struct perf_event_attr attr {};
-    attr.size = sizeof(attr);
-
-    // This is the input struct to libpfm.
-    pfm_perf_encode_arg_t arg{};
-    arg.attr = &attr;
-    const int pfm_get = pfm_get_os_event_encoding(name.c_str(), kCounterMode,
-                                                  PFM_OS_PERF_EVENT, &arg);
-    if (pfm_get != PFM_SUCCESS) {
-      GetErrorLogInstance()
-          << "Unknown performance counter name: " << name << "\n";
-      continue;
-    }
-
-    // We then proceed to populate the remaining fields in our attribute struct
-    // Note: the man page for perf_event_create suggests inherit = true and
-    // read_format = PERF_FORMAT_GROUP don't work together, but that's not the
-    // case.
-    attr.disabled = is_first;
-    attr.inherit = true;
-    attr.pinned = is_first;
-    attr.exclude_kernel = true;
-    attr.exclude_user = false;
-    attr.exclude_hv = true;
-
-    // Read all counters in a group in one read.
-    attr.read_format = PERF_FORMAT_GROUP;  //| PERF_FORMAT_TOTAL_TIME_ENABLED |
-                                           // PERF_FORMAT_TOTAL_TIME_RUNNING;
-
-    int id = -1;
-    while (id < 0) {
-      static constexpr size_t kNrOfSyscallRetries = 5;
-      // Retry syscall as it was interrupted often (b/64774091).
-      for (size_t num_retries = 0; num_retries < kNrOfSyscallRetries;
-           ++num_retries) {
-        id = perf_event_open(&attr, 0, -1, group_id, 0);
-        if (id >= 0 || errno != EINTR) {
-          break;
-        }
-      }
-      if (id < 0) {
-        // If the file descriptor is negative we might have reached a limit
-        // in the current group. Set the group_id to -1 and retry
-        if (group_id >= 0) {
-          // Create a new group
-          group_id = -1;
-        } else {
-          // At this point we have already retried to set a new group id and
-          // failed. We then give up.
-          break;
-        }
-      }
-    }
-
-    // We failed to get a new file descriptor. We might have reached a hard
-    // hardware limit that cannot be resolved even with group multiplexing
-    if (id < 0) {
-      GetErrorLogInstance() << "***WARNING** Failed to get a file descriptor "
-                               "for performance counter "
-                            << name << ". Ignoring\n";
-
-      // We give up on this counter but try to keep going
-      // as the others would be fine
-      continue;
-    }
-    if (group_id < 0) {
-      // This is a leader, store and assign it to the current file descriptor
-      leader_ids.push_back(id);
-      group_id = id;
-    }
-    // This is a valid counter, add it to our descriptor's list
-    counter_ids.push_back(id);
-    valid_names.push_back(name);
-  }
-
-  // Loop through all group leaders activating them
-  // There is another option of starting ALL counters in a process but
-  // that would be far reaching an intrusion. If the user is using PMCs
-  // by themselves then this would have a side effect on them. It is
-  // friendlier to loop through all groups individually.
-  for (int lead : leader_ids) {
-    if (ioctl(lead, PERF_EVENT_IOC_ENABLE) != 0) {
-      // This should never happen but if it does, we give up on the
-      // entire batch as recovery would be a mess.
-      GetErrorLogInstance() << "***WARNING*** Failed to start counters. "
-                               "Claring out all counters.\n";
-
-      // Close all peformance counters
-      for (int id : counter_ids) {
-        ::close(id);
-      }
-
-      // Return an empty object so our internal state is still good and
-      // the process can continue normally without impact
-      return NoCounters();
-    }
-  }
-
-  return PerfCounters(std::move(valid_names), std::move(counter_ids),
-                      std::move(leader_ids));
-}
-
-void PerfCounters::CloseCounters() const {
-  if (counter_ids_.empty()) {
-    return;
-  }
-  for (int lead : leader_ids_) {
-    ioctl(lead, PERF_EVENT_IOC_DISABLE);
-  }
-  for (int fd : counter_ids_) {
-    close(fd);
-  }
-}
-#else   // defined HAVE_LIBPFM
-size_t PerfCounterValues::Read(const std::vector&) { return 0; }
-
-const bool PerfCounters::kSupported = false;
-
-bool PerfCounters::Initialize() { return false; }
-
-bool PerfCounters::IsCounterSupported(const std::string&) { return false; }
-
-PerfCounters PerfCounters::Create(
-    const std::vector& counter_names) {
-  if (!counter_names.empty()) {
-    GetErrorLogInstance() << "Performance counters not supported.\n";
-  }
-  return NoCounters();
-}
-
-void PerfCounters::CloseCounters() const {}
-#endif  // defined HAVE_LIBPFM
-
-PerfCountersMeasurement::PerfCountersMeasurement(
-    const std::vector& counter_names)
-    : start_values_(counter_names.size()), end_values_(counter_names.size()) {
-  counters_ = PerfCounters::Create(counter_names);
-}
-
-PerfCounters& PerfCounters::operator=(PerfCounters&& other) noexcept {
-  if (this != &other) {
-    CloseCounters();
-
-    counter_ids_ = std::move(other.counter_ids_);
-    leader_ids_ = std::move(other.leader_ids_);
-    counter_names_ = std::move(other.counter_names_);
-  }
-  return *this;
-}
-}  // namespace internal
-}  // namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/perf_counters.h b/vendor/core/vendor/googlebenchmark/src/perf_counters.h
deleted file mode 100644
index bf5eb6bc3..000000000
--- a/vendor/core/vendor/googlebenchmark/src/perf_counters.h
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright 2021 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef BENCHMARK_PERF_COUNTERS_H
-#define BENCHMARK_PERF_COUNTERS_H
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-#include "check.h"
-#include "log.h"
-#include "mutex.h"
-
-#ifndef BENCHMARK_OS_WINDOWS
-#include 
-#endif
-
-#if defined(_MSC_VER)
-#pragma warning(push)
-// C4251:  needs to have dll-interface to be used by clients of class
-#pragma warning(disable : 4251)
-#endif
-
-namespace benchmark {
-namespace internal {
-
-// Typically, we can only read a small number of counters. There is also a
-// padding preceding counter values, when reading multiple counters with one
-// syscall (which is desirable). PerfCounterValues abstracts these details.
-// The implementation ensures the storage is inlined, and allows 0-based
-// indexing into the counter values.
-// The object is used in conjunction with a PerfCounters object, by passing it
-// to Snapshot(). The Read() method relocates individual reads, discarding
-// the initial padding from each group leader in the values buffer such that
-// all user accesses through the [] operator are correct.
-class BENCHMARK_EXPORT PerfCounterValues {
- public:
-  explicit PerfCounterValues(size_t nr_counters) : nr_counters_(nr_counters) {
-    BM_CHECK_LE(nr_counters_, kMaxCounters);
-  }
-
-  // We are reading correctly now so the values don't need to skip padding
-  uint64_t operator[](size_t pos) const { return values_[pos]; }
-
-  // Increased the maximum to 32 only since the buffer
-  // is std::array<> backed
-  static constexpr size_t kMaxCounters = 32;
-
- private:
-  friend class PerfCounters;
-  // Get the byte buffer in which perf counters can be captured.
-  // This is used by PerfCounters::Read
-  std::pair get_data_buffer() {
-    return {reinterpret_cast(values_.data()),
-            sizeof(uint64_t) * (kPadding + nr_counters_)};
-  }
-
-  // This reading is complex and as the goal of this class is to
-  // abstract away the intrincacies of the reading process, this is
-  // a better place for it
-  size_t Read(const std::vector& leaders);
-
-  // Move the padding to 2 due to the reading algorithm (1st padding plus a
-  // current read padding)
-  static constexpr size_t kPadding = 2;
-  std::array values_;
-  const size_t nr_counters_;
-};
-
-// Collect PMU counters. The object, once constructed, is ready to be used by
-// calling read(). PMU counter collection is enabled from the time create() is
-// called, to obtain the object, until the object's destructor is called.
-class BENCHMARK_EXPORT PerfCounters final {
- public:
-  // True iff this platform supports performance counters.
-  static const bool kSupported;
-
-  // Returns an empty object
-  static PerfCounters NoCounters() { return PerfCounters(); }
-
-  ~PerfCounters() { CloseCounters(); }
-  PerfCounters() = default;
-  PerfCounters(PerfCounters&&) = default;
-  PerfCounters(const PerfCounters&) = delete;
-  PerfCounters& operator=(PerfCounters&&) noexcept;
-  PerfCounters& operator=(const PerfCounters&) = delete;
-
-  // Platform-specific implementations may choose to do some library
-  // initialization here.
-  static bool Initialize();
-
-  // Check if the given counter is supported, if the app wants to
-  // check before passing
-  static bool IsCounterSupported(const std::string& name);
-
-  // Return a PerfCounters object ready to read the counters with the names
-  // specified. The values are user-mode only. The counter name format is
-  // implementation and OS specific.
-  // In case of failure, this method will in the worst case return an
-  // empty object whose state will still be valid.
-  static PerfCounters Create(const std::vector& counter_names);
-
-  // Take a snapshot of the current value of the counters into the provided
-  // valid PerfCounterValues storage. The values are populated such that:
-  // names()[i]'s value is (*values)[i]
-  BENCHMARK_ALWAYS_INLINE bool Snapshot(PerfCounterValues* values) const {
-#ifndef BENCHMARK_OS_WINDOWS
-    assert(values != nullptr);
-    return values->Read(leader_ids_) == counter_ids_.size();
-#else
-    (void)values;
-    return false;
-#endif
-  }
-
-  const std::vector& names() const { return counter_names_; }
-  size_t num_counters() const { return counter_names_.size(); }
-
- private:
-  PerfCounters(const std::vector& counter_names,
-               std::vector&& counter_ids, std::vector&& leader_ids)
-      : counter_ids_(std::move(counter_ids)),
-        leader_ids_(std::move(leader_ids)),
-        counter_names_(counter_names) {}
-
-  void CloseCounters() const;
-
-  std::vector counter_ids_;
-  std::vector leader_ids_;
-  std::vector counter_names_;
-};
-
-// Typical usage of the above primitives.
-class BENCHMARK_EXPORT PerfCountersMeasurement final {
- public:
-  PerfCountersMeasurement(const std::vector& counter_names);
-
-  size_t num_counters() const { return counters_.num_counters(); }
-
-  std::vector names() const { return counters_.names(); }
-
-  BENCHMARK_ALWAYS_INLINE bool Start() {
-    if (num_counters() == 0) return true;
-    // Tell the compiler to not move instructions above/below where we take
-    // the snapshot.
-    ClobberMemory();
-    valid_read_ &= counters_.Snapshot(&start_values_);
-    ClobberMemory();
-
-    return valid_read_;
-  }
-
-  BENCHMARK_ALWAYS_INLINE bool Stop(
-      std::vector>& measurements) {
-    if (num_counters() == 0) return true;
-    // Tell the compiler to not move instructions above/below where we take
-    // the snapshot.
-    ClobberMemory();
-    valid_read_ &= counters_.Snapshot(&end_values_);
-    ClobberMemory();
-
-    for (size_t i = 0; i < counters_.names().size(); ++i) {
-      double measurement = static_cast(end_values_[i]) -
-                           static_cast(start_values_[i]);
-      measurements.push_back({counters_.names()[i], measurement});
-    }
-
-    return valid_read_;
-  }
-
- private:
-  PerfCounters counters_;
-  bool valid_read_ = true;
-  PerfCounterValues start_values_;
-  PerfCounterValues end_values_;
-};
-
-}  // namespace internal
-}  // namespace benchmark
-
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
-
-#endif  // BENCHMARK_PERF_COUNTERS_H
diff --git a/vendor/core/vendor/googlebenchmark/src/re.h b/vendor/core/vendor/googlebenchmark/src/re.h
deleted file mode 100644
index 9afb869be..000000000
--- a/vendor/core/vendor/googlebenchmark/src/re.h
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef BENCHMARK_RE_H_
-#define BENCHMARK_RE_H_
-
-#include "internal_macros.h"
-
-// clang-format off
-
-#if !defined(HAVE_STD_REGEX) && \
-    !defined(HAVE_GNU_POSIX_REGEX) && \
-    !defined(HAVE_POSIX_REGEX)
-  // No explicit regex selection; detect based on builtin hints.
-  #if defined(BENCHMARK_OS_LINUX) || defined(BENCHMARK_OS_APPLE)
-    #define HAVE_POSIX_REGEX 1
-  #elif __cplusplus >= 199711L
-    #define HAVE_STD_REGEX 1
-  #endif
-#endif
-
-// Prefer C regex libraries when compiling w/o exceptions so that we can
-// correctly report errors.
-#if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && \
-    defined(HAVE_STD_REGEX) && \
-    (defined(HAVE_GNU_POSIX_REGEX) || defined(HAVE_POSIX_REGEX))
-  #undef HAVE_STD_REGEX
-#endif
-
-#if defined(HAVE_STD_REGEX)
-  #include 
-#elif defined(HAVE_GNU_POSIX_REGEX)
-  #include 
-#elif defined(HAVE_POSIX_REGEX)
-  #include 
-#else
-#error No regular expression backend was found!
-#endif
-
-// clang-format on
-
-#include 
-
-#include "check.h"
-
-namespace benchmark {
-
-// A wrapper around the POSIX regular expression API that provides automatic
-// cleanup
-class Regex {
- public:
-  Regex() : init_(false) {}
-
-  ~Regex();
-
-  // Compile a regular expression matcher from spec.  Returns true on success.
-  //
-  // On failure (and if error is not nullptr), error is populated with a human
-  // readable error message if an error occurs.
-  bool Init(const std::string& spec, std::string* error);
-
-  // Returns whether str matches the compiled regular expression.
-  bool Match(const std::string& str);
-
- private:
-  bool init_;
-// Underlying regular expression object
-#if defined(HAVE_STD_REGEX)
-  std::regex re_;
-#elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX)
-  regex_t re_;
-#else
-#error No regular expression backend implementation available
-#endif
-};
-
-#if defined(HAVE_STD_REGEX)
-
-inline bool Regex::Init(const std::string& spec, std::string* error) {
-#ifdef BENCHMARK_HAS_NO_EXCEPTIONS
-  ((void)error);  // suppress unused warning
-#else
-  try {
-#endif
-  re_ = std::regex(spec, std::regex_constants::extended);
-  init_ = true;
-#ifndef BENCHMARK_HAS_NO_EXCEPTIONS
-}
-catch (const std::regex_error& e) {
-  if (error) {
-    *error = e.what();
-  }
-}
-#endif
-return init_;
-}
-
-inline Regex::~Regex() {}
-
-inline bool Regex::Match(const std::string& str) {
-  if (!init_) {
-    return false;
-  }
-  return std::regex_search(str, re_);
-}
-
-#else
-inline bool Regex::Init(const std::string& spec, std::string* error) {
-  int ec = regcomp(&re_, spec.c_str(), REG_EXTENDED | REG_NOSUB);
-  if (ec != 0) {
-    if (error) {
-      size_t needed = regerror(ec, &re_, nullptr, 0);
-      char* errbuf = new char[needed];
-      regerror(ec, &re_, errbuf, needed);
-
-      // regerror returns the number of bytes necessary to null terminate
-      // the string, so we move that when assigning to error.
-      BM_CHECK_NE(needed, 0);
-      error->assign(errbuf, needed - 1);
-
-      delete[] errbuf;
-    }
-
-    return false;
-  }
-
-  init_ = true;
-  return true;
-}
-
-inline Regex::~Regex() {
-  if (init_) {
-    regfree(&re_);
-  }
-}
-
-inline bool Regex::Match(const std::string& str) {
-  if (!init_) {
-    return false;
-  }
-  return regexec(&re_, str.c_str(), 0, nullptr, 0) == 0;
-}
-#endif
-
-}  // end namespace benchmark
-
-#endif  // BENCHMARK_RE_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/reporter.cc b/vendor/core/vendor/googlebenchmark/src/reporter.cc
deleted file mode 100644
index 076bc31a2..000000000
--- a/vendor/core/vendor/googlebenchmark/src/reporter.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-#include "check.h"
-#include "string_util.h"
-#include "timers.h"
-
-namespace benchmark {
-
-BenchmarkReporter::BenchmarkReporter()
-    : output_stream_(&std::cout), error_stream_(&std::cerr) {}
-
-BenchmarkReporter::~BenchmarkReporter() {}
-
-void BenchmarkReporter::PrintBasicContext(std::ostream *out,
-                                          Context const &context) {
-  BM_CHECK(out) << "cannot be null";
-  auto &Out = *out;
-
-#ifndef BENCHMARK_OS_QURT
-  // Date/time information is not available on QuRT.
-  // Attempting to get it via this call cause the binary to crash.
-  Out << LocalDateTimeString() << "\n";
-#endif
-
-  if (context.executable_name)
-    Out << "Running " << context.executable_name << "\n";
-
-  const CPUInfo &info = context.cpu_info;
-  Out << "Run on (" << info.num_cpus << " X "
-      << (info.cycles_per_second / 1000000.0) << " MHz CPU "
-      << ((info.num_cpus > 1) ? "s" : "") << ")\n";
-  if (info.caches.size() != 0) {
-    Out << "CPU Caches:\n";
-    for (auto &CInfo : info.caches) {
-      Out << "  L" << CInfo.level << " " << CInfo.type << " "
-          << (CInfo.size / 1024) << " KiB";
-      if (CInfo.num_sharing != 0)
-        Out << " (x" << (info.num_cpus / CInfo.num_sharing) << ")";
-      Out << "\n";
-    }
-  }
-  if (!info.load_avg.empty()) {
-    Out << "Load Average: ";
-    for (auto It = info.load_avg.begin(); It != info.load_avg.end();) {
-      Out << StrFormat("%.2f", *It++);
-      if (It != info.load_avg.end()) Out << ", ";
-    }
-    Out << "\n";
-  }
-
-  std::map *global_context =
-      internal::GetGlobalContext();
-
-  if (global_context != nullptr) {
-    for (const auto &kv : *global_context) {
-      Out << kv.first << ": " << kv.second << "\n";
-    }
-  }
-
-  if (CPUInfo::Scaling::ENABLED == info.scaling) {
-    Out << "***WARNING*** CPU scaling is enabled, the benchmark "
-           "real time measurements may be noisy and will incur extra "
-           "overhead.\n";
-  }
-
-#ifndef NDEBUG
-  Out << "***WARNING*** Library was built as DEBUG. Timings may be "
-         "affected.\n";
-#endif
-}
-
-// No initializer because it's already initialized to NULL.
-const char *BenchmarkReporter::Context::executable_name;
-
-BenchmarkReporter::Context::Context()
-    : cpu_info(CPUInfo::Get()), sys_info(SystemInfo::Get()) {}
-
-std::string BenchmarkReporter::Run::benchmark_name() const {
-  std::string name = run_name.str();
-  if (run_type == RT_Aggregate) {
-    name += "_" + aggregate_name;
-  }
-  return name;
-}
-
-double BenchmarkReporter::Run::GetAdjustedRealTime() const {
-  double new_time = real_accumulated_time * GetTimeUnitMultiplier(time_unit);
-  if (iterations != 0) new_time /= static_cast(iterations);
-  return new_time;
-}
-
-double BenchmarkReporter::Run::GetAdjustedCPUTime() const {
-  double new_time = cpu_accumulated_time * GetTimeUnitMultiplier(time_unit);
-  if (iterations != 0) new_time /= static_cast(iterations);
-  return new_time;
-}
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/statistics.cc b/vendor/core/vendor/googlebenchmark/src/statistics.cc
deleted file mode 100644
index 16b60261f..000000000
--- a/vendor/core/vendor/googlebenchmark/src/statistics.cc
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright 2016 Ismael Jimenez Martinez. All rights reserved.
-// Copyright 2017 Roman Lebedev. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "statistics.h"
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-#include "check.h"
-
-namespace benchmark {
-
-auto StatisticsSum = [](const std::vector& v) {
-  return std::accumulate(v.begin(), v.end(), 0.0);
-};
-
-double StatisticsMean(const std::vector& v) {
-  if (v.empty()) return 0.0;
-  return StatisticsSum(v) * (1.0 / static_cast(v.size()));
-}
-
-double StatisticsMedian(const std::vector& v) {
-  if (v.size() < 3) return StatisticsMean(v);
-  std::vector copy(v);
-
-  auto center = copy.begin() + v.size() / 2;
-  std::nth_element(copy.begin(), center, copy.end());
-
-  // Did we have an odd number of samples?  If yes, then center is the median.
-  // If not, then we are looking for the average between center and the value
-  // before.  Instead of resorting, we just look for the max value before it,
-  // which is not necessarily the element immediately preceding `center` Since
-  // `copy` is only partially sorted by `nth_element`.
-  if (v.size() % 2 == 1) return *center;
-  auto center2 = std::max_element(copy.begin(), center);
-  return (*center + *center2) / 2.0;
-}
-
-// Return the sum of the squares of this sample set
-auto SumSquares = [](const std::vector& v) {
-  return std::inner_product(v.begin(), v.end(), v.begin(), 0.0);
-};
-
-auto Sqr = [](const double dat) { return dat * dat; };
-auto Sqrt = [](const double dat) {
-  // Avoid NaN due to imprecision in the calculations
-  if (dat < 0.0) return 0.0;
-  return std::sqrt(dat);
-};
-
-double StatisticsStdDev(const std::vector& v) {
-  const auto mean = StatisticsMean(v);
-  if (v.empty()) return mean;
-
-  // Sample standard deviation is undefined for n = 1
-  if (v.size() == 1) return 0.0;
-
-  const double avg_squares =
-      SumSquares(v) * (1.0 / static_cast(v.size()));
-  return Sqrt(static_cast(v.size()) /
-              (static_cast(v.size()) - 1.0) *
-              (avg_squares - Sqr(mean)));
-}
-
-double StatisticsCV(const std::vector& v) {
-  if (v.size() < 2) return 0.0;
-
-  const auto stddev = StatisticsStdDev(v);
-  const auto mean = StatisticsMean(v);
-
-  if (std::fpclassify(mean) == FP_ZERO) return 0.0;
-
-  return stddev / mean;
-}
-
-std::vector ComputeStats(
-    const std::vector& reports) {
-  typedef BenchmarkReporter::Run Run;
-  std::vector results;
-
-  auto error_count = std::count_if(reports.begin(), reports.end(),
-                                   [](Run const& run) { return run.skipped; });
-
-  if (reports.size() - static_cast(error_count) < 2) {
-    // We don't report aggregated data if there was a single run.
-    return results;
-  }
-
-  // Accumulators.
-  std::vector real_accumulated_time_stat;
-  std::vector cpu_accumulated_time_stat;
-
-  real_accumulated_time_stat.reserve(reports.size());
-  cpu_accumulated_time_stat.reserve(reports.size());
-
-  // All repetitions should be run with the same number of iterations so we
-  // can take this information from the first benchmark.
-  const IterationCount run_iterations = reports.front().iterations;
-  // create stats for user counters
-  struct CounterStat {
-    Counter c;
-    std::vector s;
-  };
-  std::map counter_stats;
-  for (Run const& r : reports) {
-    for (auto const& cnt : r.counters) {
-      auto it = counter_stats.find(cnt.first);
-      if (it == counter_stats.end()) {
-        it = counter_stats
-                 .emplace(cnt.first,
-                          CounterStat{cnt.second, std::vector{}})
-                 .first;
-        it->second.s.reserve(reports.size());
-      } else {
-        BM_CHECK_EQ(it->second.c.flags, cnt.second.flags);
-      }
-    }
-  }
-
-  // Populate the accumulators.
-  for (Run const& run : reports) {
-    BM_CHECK_EQ(reports[0].benchmark_name(), run.benchmark_name());
-    BM_CHECK_EQ(run_iterations, run.iterations);
-    if (run.skipped) continue;
-    real_accumulated_time_stat.emplace_back(run.real_accumulated_time);
-    cpu_accumulated_time_stat.emplace_back(run.cpu_accumulated_time);
-    // user counters
-    for (auto const& cnt : run.counters) {
-      auto it = counter_stats.find(cnt.first);
-      BM_CHECK_NE(it, counter_stats.end());
-      it->second.s.emplace_back(cnt.second);
-    }
-  }
-
-  // Only add label if it is same for all runs
-  std::string report_label = reports[0].report_label;
-  for (std::size_t i = 1; i < reports.size(); i++) {
-    if (reports[i].report_label != report_label) {
-      report_label = "";
-      break;
-    }
-  }
-
-  const double iteration_rescale_factor =
-      double(reports.size()) / double(run_iterations);
-
-  for (const auto& Stat : *reports[0].statistics) {
-    // Get the data from the accumulator to BenchmarkReporter::Run's.
-    Run data;
-    data.run_name = reports[0].run_name;
-    data.family_index = reports[0].family_index;
-    data.per_family_instance_index = reports[0].per_family_instance_index;
-    data.run_type = BenchmarkReporter::Run::RT_Aggregate;
-    data.threads = reports[0].threads;
-    data.repetitions = reports[0].repetitions;
-    data.repetition_index = Run::no_repetition_index;
-    data.aggregate_name = Stat.name_;
-    data.aggregate_unit = Stat.unit_;
-    data.report_label = report_label;
-
-    // It is incorrect to say that an aggregate is computed over
-    // run's iterations, because those iterations already got averaged.
-    // Similarly, if there are N repetitions with 1 iterations each,
-    // an aggregate will be computed over N measurements, not 1.
-    // Thus it is best to simply use the count of separate reports.
-    data.iterations = static_cast(reports.size());
-
-    data.real_accumulated_time = Stat.compute_(real_accumulated_time_stat);
-    data.cpu_accumulated_time = Stat.compute_(cpu_accumulated_time_stat);
-
-    if (data.aggregate_unit == StatisticUnit::kTime) {
-      // We will divide these times by data.iterations when reporting, but the
-      // data.iterations is not necessarily the scale of these measurements,
-      // because in each repetition, these timers are sum over all the iters.
-      // And if we want to say that the stats are over N repetitions and not
-      // M iterations, we need to multiply these by (N/M).
-      data.real_accumulated_time *= iteration_rescale_factor;
-      data.cpu_accumulated_time *= iteration_rescale_factor;
-    }
-
-    data.time_unit = reports[0].time_unit;
-
-    // user counters
-    for (auto const& kv : counter_stats) {
-      // Do *NOT* rescale the custom counters. They are already properly scaled.
-      const auto uc_stat = Stat.compute_(kv.second.s);
-      auto c = Counter(uc_stat, counter_stats[kv.first].c.flags,
-                       counter_stats[kv.first].c.oneK);
-      data.counters[kv.first] = c;
-    }
-
-    results.push_back(data);
-  }
-
-  return results;
-}
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/statistics.h b/vendor/core/vendor/googlebenchmark/src/statistics.h
deleted file mode 100644
index 6e5560e8f..000000000
--- a/vendor/core/vendor/googlebenchmark/src/statistics.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2016 Ismael Jimenez Martinez. All rights reserved.
-// Copyright 2017 Roman Lebedev. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef STATISTICS_H_
-#define STATISTICS_H_
-
-#include 
-
-#include "benchmark/benchmark.h"
-
-namespace benchmark {
-
-// Return a vector containing the mean, median and standard deviation
-// information (and any user-specified info) for the specified list of reports.
-// If 'reports' contains less than two non-errored runs an empty vector is
-// returned
-BENCHMARK_EXPORT
-std::vector ComputeStats(
-    const std::vector& reports);
-
-BENCHMARK_EXPORT
-double StatisticsMean(const std::vector& v);
-BENCHMARK_EXPORT
-double StatisticsMedian(const std::vector& v);
-BENCHMARK_EXPORT
-double StatisticsStdDev(const std::vector& v);
-BENCHMARK_EXPORT
-double StatisticsCV(const std::vector& v);
-
-}  // end namespace benchmark
-
-#endif  // STATISTICS_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/string_util.cc b/vendor/core/vendor/googlebenchmark/src/string_util.cc
deleted file mode 100644
index 9ba63a700..000000000
--- a/vendor/core/vendor/googlebenchmark/src/string_util.cc
+++ /dev/null
@@ -1,254 +0,0 @@
-#include "string_util.h"
-
-#include 
-#ifdef BENCHMARK_STL_ANDROID_GNUSTL
-#include 
-#endif
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "arraysize.h"
-#include "benchmark/benchmark.h"
-
-namespace benchmark {
-namespace {
-// kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta.
-const char* const kBigSIUnits[] = {"k", "M", "G", "T", "P", "E", "Z", "Y"};
-// Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi.
-const char* const kBigIECUnits[] = {"Ki", "Mi", "Gi", "Ti",
-                                    "Pi", "Ei", "Zi", "Yi"};
-// milli, micro, nano, pico, femto, atto, zepto, yocto.
-const char* const kSmallSIUnits[] = {"m", "u", "n", "p", "f", "a", "z", "y"};
-
-// We require that all three arrays have the same size.
-static_assert(arraysize(kBigSIUnits) == arraysize(kBigIECUnits),
-              "SI and IEC unit arrays must be the same size");
-static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits),
-              "Small SI and Big SI unit arrays must be the same size");
-
-static const int64_t kUnitsSize = arraysize(kBigSIUnits);
-
-void ToExponentAndMantissa(double val, int precision, double one_k,
-                           std::string* mantissa, int64_t* exponent) {
-  std::stringstream mantissa_stream;
-
-  if (val < 0) {
-    mantissa_stream << "-";
-    val = -val;
-  }
-
-  // Adjust threshold so that it never excludes things which can't be rendered
-  // in 'precision' digits.
-  const double adjusted_threshold =
-      std::max(1.0, 1.0 / std::pow(10.0, precision));
-  const double big_threshold = (adjusted_threshold * one_k) - 1;
-  const double small_threshold = adjusted_threshold;
-  // Values in ]simple_threshold,small_threshold[ will be printed as-is
-  const double simple_threshold = 0.01;
-
-  if (val > big_threshold) {
-    // Positive powers
-    double scaled = val;
-    for (size_t i = 0; i < arraysize(kBigSIUnits); ++i) {
-      scaled /= one_k;
-      if (scaled <= big_threshold) {
-        mantissa_stream << scaled;
-        *exponent = static_cast(i + 1);
-        *mantissa = mantissa_stream.str();
-        return;
-      }
-    }
-    mantissa_stream << val;
-    *exponent = 0;
-  } else if (val < small_threshold) {
-    // Negative powers
-    if (val < simple_threshold) {
-      double scaled = val;
-      for (size_t i = 0; i < arraysize(kSmallSIUnits); ++i) {
-        scaled *= one_k;
-        if (scaled >= small_threshold) {
-          mantissa_stream << scaled;
-          *exponent = -static_cast(i + 1);
-          *mantissa = mantissa_stream.str();
-          return;
-        }
-      }
-    }
-    mantissa_stream << val;
-    *exponent = 0;
-  } else {
-    mantissa_stream << val;
-    *exponent = 0;
-  }
-  *mantissa = mantissa_stream.str();
-}
-
-std::string ExponentToPrefix(int64_t exponent, bool iec) {
-  if (exponent == 0) return "";
-
-  const int64_t index = (exponent > 0 ? exponent - 1 : -exponent - 1);
-  if (index >= kUnitsSize) return "";
-
-  const char* const* array =
-      (exponent > 0 ? (iec ? kBigIECUnits : kBigSIUnits) : kSmallSIUnits);
-
-  return std::string(array[index]);
-}
-
-std::string ToBinaryStringFullySpecified(double value, int precision,
-                                         Counter::OneK one_k) {
-  std::string mantissa;
-  int64_t exponent;
-  ToExponentAndMantissa(value, precision,
-                        one_k == Counter::kIs1024 ? 1024.0 : 1000.0, &mantissa,
-                        &exponent);
-  return mantissa + ExponentToPrefix(exponent, one_k == Counter::kIs1024);
-}
-
-std::string StrFormatImp(const char* msg, va_list args) {
-  // we might need a second shot at this, so pre-emptivly make a copy
-  va_list args_cp;
-  va_copy(args_cp, args);
-
-  // TODO(ericwf): use std::array for first attempt to avoid one memory
-  // allocation guess what the size might be
-  std::array local_buff;
-
-  // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation
-  // in the android-ndk
-  auto ret = vsnprintf(local_buff.data(), local_buff.size(), msg, args_cp);
-
-  va_end(args_cp);
-
-  // handle empty expansion
-  if (ret == 0) return std::string{};
-  if (static_cast(ret) < local_buff.size())
-    return std::string(local_buff.data());
-
-  // we did not provide a long enough buffer on our first attempt.
-  // add 1 to size to account for null-byte in size cast to prevent overflow
-  std::size_t size = static_cast(ret) + 1;
-  auto buff_ptr = std::unique_ptr(new char[size]);
-  // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation
-  // in the android-ndk
-  vsnprintf(buff_ptr.get(), size, msg, args);
-  return std::string(buff_ptr.get());
-}
-
-}  // end namespace
-
-std::string HumanReadableNumber(double n, Counter::OneK one_k) {
-  return ToBinaryStringFullySpecified(n, 1, one_k);
-}
-
-std::string StrFormat(const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  std::string tmp = StrFormatImp(format, args);
-  va_end(args);
-  return tmp;
-}
-
-std::vector StrSplit(const std::string& str, char delim) {
-  if (str.empty()) return {};
-  std::vector ret;
-  size_t first = 0;
-  size_t next = str.find(delim);
-  for (; next != std::string::npos;
-       first = next + 1, next = str.find(delim, first)) {
-    ret.push_back(str.substr(first, next - first));
-  }
-  ret.push_back(str.substr(first));
-  return ret;
-}
-
-#ifdef BENCHMARK_STL_ANDROID_GNUSTL
-/*
- * GNU STL in Android NDK lacks support for some C++11 functions, including
- * stoul, stoi, stod. We reimplement them here using C functions strtoul,
- * strtol, strtod. Note that reimplemented functions are in benchmark::
- * namespace, not std:: namespace.
- */
-unsigned long stoul(const std::string& str, size_t* pos, int base) {
-  /* Record previous errno */
-  const int oldErrno = errno;
-  errno = 0;
-
-  const char* strStart = str.c_str();
-  char* strEnd = const_cast(strStart);
-  const unsigned long result = strtoul(strStart, &strEnd, base);
-
-  const int strtoulErrno = errno;
-  /* Restore previous errno */
-  errno = oldErrno;
-
-  /* Check for errors and return */
-  if (strtoulErrno == ERANGE) {
-    throw std::out_of_range("stoul failed: " + str +
-                            " is outside of range of unsigned long");
-  } else if (strEnd == strStart || strtoulErrno != 0) {
-    throw std::invalid_argument("stoul failed: " + str + " is not an integer");
-  }
-  if (pos != nullptr) {
-    *pos = static_cast(strEnd - strStart);
-  }
-  return result;
-}
-
-int stoi(const std::string& str, size_t* pos, int base) {
-  /* Record previous errno */
-  const int oldErrno = errno;
-  errno = 0;
-
-  const char* strStart = str.c_str();
-  char* strEnd = const_cast(strStart);
-  const long result = strtol(strStart, &strEnd, base);
-
-  const int strtolErrno = errno;
-  /* Restore previous errno */
-  errno = oldErrno;
-
-  /* Check for errors and return */
-  if (strtolErrno == ERANGE || long(int(result)) != result) {
-    throw std::out_of_range("stoul failed: " + str +
-                            " is outside of range of int");
-  } else if (strEnd == strStart || strtolErrno != 0) {
-    throw std::invalid_argument("stoul failed: " + str + " is not an integer");
-  }
-  if (pos != nullptr) {
-    *pos = static_cast(strEnd - strStart);
-  }
-  return int(result);
-}
-
-double stod(const std::string& str, size_t* pos) {
-  /* Record previous errno */
-  const int oldErrno = errno;
-  errno = 0;
-
-  const char* strStart = str.c_str();
-  char* strEnd = const_cast(strStart);
-  const double result = strtod(strStart, &strEnd);
-
-  /* Restore previous errno */
-  const int strtodErrno = errno;
-  errno = oldErrno;
-
-  /* Check for errors and return */
-  if (strtodErrno == ERANGE) {
-    throw std::out_of_range("stoul failed: " + str +
-                            " is outside of range of int");
-  } else if (strEnd == strStart || strtodErrno != 0) {
-    throw std::invalid_argument("stoul failed: " + str + " is not an integer");
-  }
-  if (pos != nullptr) {
-    *pos = static_cast(strEnd - strStart);
-  }
-  return result;
-}
-#endif
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/string_util.h b/vendor/core/vendor/googlebenchmark/src/string_util.h
deleted file mode 100644
index 731aa2c04..000000000
--- a/vendor/core/vendor/googlebenchmark/src/string_util.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef BENCHMARK_STRING_UTIL_H_
-#define BENCHMARK_STRING_UTIL_H_
-
-#include 
-#include 
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-#include "benchmark/export.h"
-#include "check.h"
-#include "internal_macros.h"
-
-namespace benchmark {
-
-BENCHMARK_EXPORT
-std::string HumanReadableNumber(double n, Counter::OneK one_k);
-
-BENCHMARK_EXPORT
-#if defined(__MINGW32__)
-__attribute__((format(__MINGW_PRINTF_FORMAT, 1, 2)))
-#elif defined(__GNUC__)
-__attribute__((format(printf, 1, 2)))
-#endif
-std::string
-StrFormat(const char* format, ...);
-
-inline std::ostream& StrCatImp(std::ostream& out) BENCHMARK_NOEXCEPT {
-  return out;
-}
-
-template 
-inline std::ostream& StrCatImp(std::ostream& out, First&& f, Rest&&... rest) {
-  out << std::forward(f);
-  return StrCatImp(out, std::forward(rest)...);
-}
-
-template 
-inline std::string StrCat(Args&&... args) {
-  std::ostringstream ss;
-  StrCatImp(ss, std::forward(args)...);
-  return ss.str();
-}
-
-BENCHMARK_EXPORT
-std::vector StrSplit(const std::string& str, char delim);
-
-// Disable lint checking for this block since it re-implements C functions.
-// NOLINTBEGIN
-#ifdef BENCHMARK_STL_ANDROID_GNUSTL
-/*
- * GNU STL in Android NDK lacks support for some C++11 functions, including
- * stoul, stoi, stod. We reimplement them here using C functions strtoul,
- * strtol, strtod. Note that reimplemented functions are in benchmark::
- * namespace, not std:: namespace.
- */
-unsigned long stoul(const std::string& str, size_t* pos = nullptr,
-                    int base = 10);
-int stoi(const std::string& str, size_t* pos = nullptr, int base = 10);
-double stod(const std::string& str, size_t* pos = nullptr);
-#else
-using std::stod;   // NOLINT(misc-unused-using-decls)
-using std::stoi;   // NOLINT(misc-unused-using-decls)
-using std::stoul;  // NOLINT(misc-unused-using-decls)
-#endif
-// NOLINTEND
-
-}  // end namespace benchmark
-
-#endif  // BENCHMARK_STRING_UTIL_H_
diff --git a/vendor/core/vendor/googlebenchmark/src/sysinfo.cc b/vendor/core/vendor/googlebenchmark/src/sysinfo.cc
deleted file mode 100644
index a153b20cf..000000000
--- a/vendor/core/vendor/googlebenchmark/src/sysinfo.cc
+++ /dev/null
@@ -1,871 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "internal_macros.h"
-
-#ifdef BENCHMARK_OS_WINDOWS
-#if !defined(WINVER) || WINVER < 0x0600
-#undef WINVER
-#define WINVER 0x0600
-#endif  // WINVER handling
-#include 
-#undef StrCat  // Don't let StrCat in string_util.h be renamed to lstrcatA
-#include 
-#include 
-
-#include 
-#else
-#include 
-#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
-#include 
-#endif
-#include 
-#include   // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
-#include 
-#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX || \
-    defined BENCHMARK_OS_NETBSD || defined BENCHMARK_OS_OPENBSD || \
-    defined BENCHMARK_OS_DRAGONFLY
-#define BENCHMARK_HAS_SYSCTL
-#include 
-#endif
-#endif
-#if defined(BENCHMARK_OS_SOLARIS)
-#include 
-#include 
-#endif
-#if defined(BENCHMARK_OS_QNX)
-#include 
-#endif
-#if defined(BENCHMARK_OS_QURT)
-#include 
-#endif
-#if defined(BENCHMARK_HAS_PTHREAD_AFFINITY)
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "benchmark/benchmark.h"
-#include "check.h"
-#include "cycleclock.h"
-#include "internal_macros.h"
-#include "log.h"
-#include "string_util.h"
-#include "timers.h"
-
-namespace benchmark {
-namespace {
-
-void PrintImp(std::ostream& out) { out << std::endl; }
-
-template 
-void PrintImp(std::ostream& out, First&& f, Rest&&... rest) {
-  out << std::forward(f);
-  PrintImp(out, std::forward(rest)...);
-}
-
-template 
-BENCHMARK_NORETURN void PrintErrorAndDie(Args&&... args) {
-  PrintImp(std::cerr, std::forward(args)...);
-  std::exit(EXIT_FAILURE);
-}
-
-#ifdef BENCHMARK_HAS_SYSCTL
-
-/// ValueUnion - A type used to correctly alias the byte-for-byte output of
-/// `sysctl` with the result type it's to be interpreted as.
-struct ValueUnion {
-  union DataT {
-    int32_t int32_value;
-    int64_t int64_value;
-    // For correct aliasing of union members from bytes.
-    char bytes[8];
-  };
-  using DataPtr = std::unique_ptr;
-
-  // The size of the data union member + its trailing array size.
-  std::size_t size;
-  DataPtr buff;
-
- public:
-  ValueUnion() : size(0), buff(nullptr, &std::free) {}
-
-  explicit ValueUnion(std::size_t buff_size)
-      : size(sizeof(DataT) + buff_size),
-        buff(::new (std::malloc(size)) DataT(), &std::free) {}
-
-  ValueUnion(ValueUnion&& other) = default;
-
-  explicit operator bool() const { return bool(buff); }
-
-  char* data() const { return buff->bytes; }
-
-  std::string GetAsString() const { return std::string(data()); }
-
-  int64_t GetAsInteger() const {
-    if (size == sizeof(buff->int32_value))
-      return buff->int32_value;
-    else if (size == sizeof(buff->int64_value))
-      return buff->int64_value;
-    BENCHMARK_UNREACHABLE();
-  }
-
-  template 
-  std::array GetAsArray() {
-    const int arr_size = sizeof(T) * N;
-    BM_CHECK_LE(arr_size, size);
-    std::array arr;
-    std::memcpy(arr.data(), data(), arr_size);
-    return arr;
-  }
-};
-
-ValueUnion GetSysctlImp(std::string const& name) {
-#if defined BENCHMARK_OS_OPENBSD
-  int mib[2];
-
-  mib[0] = CTL_HW;
-  if ((name == "hw.ncpu") || (name == "hw.cpuspeed")) {
-    ValueUnion buff(sizeof(int));
-
-    if (name == "hw.ncpu") {
-      mib[1] = HW_NCPU;
-    } else {
-      mib[1] = HW_CPUSPEED;
-    }
-
-    if (sysctl(mib, 2, buff.data(), &buff.size, nullptr, 0) == -1) {
-      return ValueUnion();
-    }
-    return buff;
-  }
-  return ValueUnion();
-#else
-  std::size_t cur_buff_size = 0;
-  if (sysctlbyname(name.c_str(), nullptr, &cur_buff_size, nullptr, 0) == -1)
-    return ValueUnion();
-
-  ValueUnion buff(cur_buff_size);
-  if (sysctlbyname(name.c_str(), buff.data(), &buff.size, nullptr, 0) == 0)
-    return buff;
-  return ValueUnion();
-#endif
-}
-
-BENCHMARK_MAYBE_UNUSED
-bool GetSysctl(std::string const& name, std::string* out) {
-  out->clear();
-  auto buff = GetSysctlImp(name);
-  if (!buff) return false;
-  out->assign(buff.data());
-  return true;
-}
-
-template ::value>::type>
-bool GetSysctl(std::string const& name, Tp* out) {
-  *out = 0;
-  auto buff = GetSysctlImp(name);
-  if (!buff) return false;
-  *out = static_cast(buff.GetAsInteger());
-  return true;
-}
-
-template 
-bool GetSysctl(std::string const& name, std::array* out) {
-  auto buff = GetSysctlImp(name);
-  if (!buff) return false;
-  *out = buff.GetAsArray();
-  return true;
-}
-#endif
-
-template 
-bool ReadFromFile(std::string const& fname, ArgT* arg) {
-  *arg = ArgT();
-  std::ifstream f(fname.c_str());
-  if (!f.is_open()) return false;
-  f >> *arg;
-  return f.good();
-}
-
-CPUInfo::Scaling CpuScaling(int num_cpus) {
-  // We don't have a valid CPU count, so don't even bother.
-  if (num_cpus <= 0) return CPUInfo::Scaling::UNKNOWN;
-#if defined(BENCHMARK_OS_QNX)
-  return CPUInfo::Scaling::UNKNOWN;
-#elif !defined(BENCHMARK_OS_WINDOWS)
-  // On Linux, the CPUfreq subsystem exposes CPU information as files on the
-  // local file system. If reading the exported files fails, then we may not be
-  // running on Linux, so we silently ignore all the read errors.
-  std::string res;
-  for (int cpu = 0; cpu < num_cpus; ++cpu) {
-    std::string governor_file =
-        StrCat("/sys/devices/system/cpu/cpu", cpu, "/cpufreq/scaling_governor");
-    if (ReadFromFile(governor_file, &res) && res != "performance")
-      return CPUInfo::Scaling::ENABLED;
-  }
-  return CPUInfo::Scaling::DISABLED;
-#else
-  return CPUInfo::Scaling::UNKNOWN;
-#endif
-}
-
-int CountSetBitsInCPUMap(std::string val) {
-  auto CountBits = [](std::string part) {
-    using CPUMask = std::bitset;
-    part = "0x" + part;
-    CPUMask mask(benchmark::stoul(part, nullptr, 16));
-    return static_cast(mask.count());
-  };
-  std::size_t pos;
-  int total = 0;
-  while ((pos = val.find(',')) != std::string::npos) {
-    total += CountBits(val.substr(0, pos));
-    val = val.substr(pos + 1);
-  }
-  if (!val.empty()) {
-    total += CountBits(val);
-  }
-  return total;
-}
-
-BENCHMARK_MAYBE_UNUSED
-std::vector GetCacheSizesFromKVFS() {
-  std::vector res;
-  std::string dir = "/sys/devices/system/cpu/cpu0/cache/";
-  int idx = 0;
-  while (true) {
-    CPUInfo::CacheInfo info;
-    std::string fpath = StrCat(dir, "index", idx++, "/");
-    std::ifstream f(StrCat(fpath, "size").c_str());
-    if (!f.is_open()) break;
-    std::string suffix;
-    f >> info.size;
-    if (f.fail())
-      PrintErrorAndDie("Failed while reading file '", fpath, "size'");
-    if (f.good()) {
-      f >> suffix;
-      if (f.bad())
-        PrintErrorAndDie(
-            "Invalid cache size format: failed to read size suffix");
-      else if (f && suffix != "K")
-        PrintErrorAndDie("Invalid cache size format: Expected bytes ", suffix);
-      else if (suffix == "K")
-        info.size *= 1024;
-    }
-    if (!ReadFromFile(StrCat(fpath, "type"), &info.type))
-      PrintErrorAndDie("Failed to read from file ", fpath, "type");
-    if (!ReadFromFile(StrCat(fpath, "level"), &info.level))
-      PrintErrorAndDie("Failed to read from file ", fpath, "level");
-    std::string map_str;
-    if (!ReadFromFile(StrCat(fpath, "shared_cpu_map"), &map_str))
-      PrintErrorAndDie("Failed to read from file ", fpath, "shared_cpu_map");
-    info.num_sharing = CountSetBitsInCPUMap(map_str);
-    res.push_back(info);
-  }
-
-  return res;
-}
-
-#ifdef BENCHMARK_OS_MACOSX
-std::vector GetCacheSizesMacOSX() {
-  std::vector res;
-  std::array cache_counts{{0, 0, 0, 0}};
-  GetSysctl("hw.cacheconfig", &cache_counts);
-
-  struct {
-    std::string name;
-    std::string type;
-    int level;
-    int num_sharing;
-  } cases[] = {{"hw.l1dcachesize", "Data", 1, cache_counts[1]},
-               {"hw.l1icachesize", "Instruction", 1, cache_counts[1]},
-               {"hw.l2cachesize", "Unified", 2, cache_counts[2]},
-               {"hw.l3cachesize", "Unified", 3, cache_counts[3]}};
-  for (auto& c : cases) {
-    int val;
-    if (!GetSysctl(c.name, &val)) continue;
-    CPUInfo::CacheInfo info;
-    info.type = c.type;
-    info.level = c.level;
-    info.size = val;
-    info.num_sharing = c.num_sharing;
-    res.push_back(std::move(info));
-  }
-  return res;
-}
-#elif defined(BENCHMARK_OS_WINDOWS)
-std::vector GetCacheSizesWindows() {
-  std::vector res;
-  DWORD buffer_size = 0;
-  using PInfo = SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
-  using CInfo = CACHE_DESCRIPTOR;
-
-  using UPtr = std::unique_ptr;
-  GetLogicalProcessorInformation(nullptr, &buffer_size);
-  UPtr buff(static_cast(std::malloc(buffer_size)), &std::free);
-  if (!GetLogicalProcessorInformation(buff.get(), &buffer_size))
-    PrintErrorAndDie("Failed during call to GetLogicalProcessorInformation: ",
-                     GetLastError());
-
-  PInfo* it = buff.get();
-  PInfo* end = buff.get() + (buffer_size / sizeof(PInfo));
-
-  for (; it != end; ++it) {
-    if (it->Relationship != RelationCache) continue;
-    using BitSet = std::bitset;
-    BitSet b(it->ProcessorMask);
-    // To prevent duplicates, only consider caches where CPU 0 is specified
-    if (!b.test(0)) continue;
-    const CInfo& cache = it->Cache;
-    CPUInfo::CacheInfo C;
-    C.num_sharing = static_cast(b.count());
-    C.level = cache.Level;
-    C.size = static_cast(cache.Size);
-    C.type = "Unknown";
-    switch (cache.Type) {
-      case CacheUnified:
-        C.type = "Unified";
-        break;
-      case CacheInstruction:
-        C.type = "Instruction";
-        break;
-      case CacheData:
-        C.type = "Data";
-        break;
-      case CacheTrace:
-        C.type = "Trace";
-        break;
-    }
-    res.push_back(C);
-  }
-  return res;
-}
-#elif BENCHMARK_OS_QNX
-std::vector GetCacheSizesQNX() {
-  std::vector res;
-  struct cacheattr_entry* cache = SYSPAGE_ENTRY(cacheattr);
-  uint32_t const elsize = SYSPAGE_ELEMENT_SIZE(cacheattr);
-  int num = SYSPAGE_ENTRY_SIZE(cacheattr) / elsize;
-  for (int i = 0; i < num; ++i) {
-    CPUInfo::CacheInfo info;
-    switch (cache->flags) {
-      case CACHE_FLAG_INSTR:
-        info.type = "Instruction";
-        info.level = 1;
-        break;
-      case CACHE_FLAG_DATA:
-        info.type = "Data";
-        info.level = 1;
-        break;
-      case CACHE_FLAG_UNIFIED:
-        info.type = "Unified";
-        info.level = 2;
-        break;
-      case CACHE_FLAG_SHARED:
-        info.type = "Shared";
-        info.level = 3;
-        break;
-      default:
-        continue;
-        break;
-    }
-    info.size = cache->line_size * cache->num_lines;
-    info.num_sharing = 0;
-    res.push_back(std::move(info));
-    cache = SYSPAGE_ARRAY_ADJ_OFFSET(cacheattr, cache, elsize);
-  }
-  return res;
-}
-#endif
-
-std::vector GetCacheSizes() {
-#ifdef BENCHMARK_OS_MACOSX
-  return GetCacheSizesMacOSX();
-#elif defined(BENCHMARK_OS_WINDOWS)
-  return GetCacheSizesWindows();
-#elif defined(BENCHMARK_OS_QNX)
-  return GetCacheSizesQNX();
-#elif defined(BENCHMARK_OS_QURT)
-  return std::vector();
-#else
-  return GetCacheSizesFromKVFS();
-#endif
-}
-
-std::string GetSystemName() {
-#if defined(BENCHMARK_OS_WINDOWS)
-  std::string str;
-  static constexpr int COUNT = MAX_COMPUTERNAME_LENGTH + 1;
-  TCHAR hostname[COUNT] = {'\0'};
-  DWORD DWCOUNT = COUNT;
-  if (!GetComputerName(hostname, &DWCOUNT)) return std::string("");
-#ifndef UNICODE
-  str = std::string(hostname, DWCOUNT);
-#else
-  // `WideCharToMultiByte` returns `0` when conversion fails.
-  int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, hostname,
-                                DWCOUNT, NULL, 0, NULL, NULL);
-  str.resize(len);
-  WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, hostname, DWCOUNT, &str[0],
-                      str.size(), NULL, NULL);
-#endif
-  return str;
-#elif defined(BENCHMARK_OS_QURT)
-  std::string str = "Hexagon DSP";
-  qurt_arch_version_t arch_version_struct;
-  if (qurt_sysenv_get_arch_version(&arch_version_struct) == QURT_EOK) {
-    str += " v";
-    str += std::to_string(arch_version_struct.arch_version);
-  }
-  return str;
-#else
-#ifndef HOST_NAME_MAX
-#ifdef BENCHMARK_HAS_SYSCTL  // BSD/Mac doesn't have HOST_NAME_MAX defined
-#define HOST_NAME_MAX 64
-#elif defined(BENCHMARK_OS_NACL)
-#define HOST_NAME_MAX 64
-#elif defined(BENCHMARK_OS_QNX)
-#define HOST_NAME_MAX 154
-#elif defined(BENCHMARK_OS_RTEMS)
-#define HOST_NAME_MAX 256
-#elif defined(BENCHMARK_OS_SOLARIS)
-#define HOST_NAME_MAX MAXHOSTNAMELEN
-#elif defined(BENCHMARK_OS_ZOS)
-#define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
-#else
-#pragma message("HOST_NAME_MAX not defined. using 64")
-#define HOST_NAME_MAX 64
-#endif
-#endif  // def HOST_NAME_MAX
-  char hostname[HOST_NAME_MAX];
-  int retVal = gethostname(hostname, HOST_NAME_MAX);
-  if (retVal != 0) return std::string("");
-  return std::string(hostname);
-#endif  // Catch-all POSIX block.
-}
-
-int GetNumCPUsImpl() {
-#ifdef BENCHMARK_HAS_SYSCTL
-  int num_cpu = -1;
-  if (GetSysctl("hw.ncpu", &num_cpu)) return num_cpu;
-  PrintErrorAndDie("Err: ", strerror(errno));
-#elif defined(BENCHMARK_OS_WINDOWS)
-  SYSTEM_INFO sysinfo;
-  // Use memset as opposed to = {} to avoid GCC missing initializer false
-  // positives.
-  std::memset(&sysinfo, 0, sizeof(SYSTEM_INFO));
-  GetSystemInfo(&sysinfo);
-  // number of logical processors in the current group
-  return static_cast(sysinfo.dwNumberOfProcessors);
-#elif defined(BENCHMARK_OS_SOLARIS)
-  // Returns -1 in case of a failure.
-  long num_cpu = sysconf(_SC_NPROCESSORS_ONLN);
-  if (num_cpu < 0) {
-    PrintErrorAndDie("sysconf(_SC_NPROCESSORS_ONLN) failed with error: ",
-                     strerror(errno));
-  }
-  return (int)num_cpu;
-#elif defined(BENCHMARK_OS_QNX)
-  return static_cast(_syspage_ptr->num_cpu);
-#elif defined(BENCHMARK_OS_QURT)
-  qurt_sysenv_max_hthreads_t hardware_threads;
-  if (qurt_sysenv_get_max_hw_threads(&hardware_threads) != QURT_EOK) {
-    hardware_threads.max_hthreads = 1;
-  }
-  return hardware_threads.max_hthreads;
-#else
-  int num_cpus = 0;
-  int max_id = -1;
-  std::ifstream f("/proc/cpuinfo");
-  if (!f.is_open()) {
-    std::cerr << "Failed to open /proc/cpuinfo\n";
-    return -1;
-  }
-#if defined(__alpha__)
-  const std::string Key = "cpus detected";
-#else
-  const std::string Key = "processor";
-#endif
-  std::string ln;
-  while (std::getline(f, ln)) {
-    if (ln.empty()) continue;
-    std::size_t split_idx = ln.find(':');
-    std::string value;
-#if defined(__s390__)
-    // s390 has another format in /proc/cpuinfo
-    // it needs to be parsed differently
-    if (split_idx != std::string::npos)
-      value = ln.substr(Key.size() + 1, split_idx - Key.size() - 1);
-#else
-    if (split_idx != std::string::npos) value = ln.substr(split_idx + 1);
-#endif
-    if (ln.size() >= Key.size() && ln.compare(0, Key.size(), Key) == 0) {
-      num_cpus++;
-      if (!value.empty()) {
-        const int cur_id = benchmark::stoi(value);
-        max_id = std::max(cur_id, max_id);
-      }
-    }
-  }
-  if (f.bad()) {
-    PrintErrorAndDie("Failure reading /proc/cpuinfo");
-  }
-  if (!f.eof()) {
-    PrintErrorAndDie("Failed to read to end of /proc/cpuinfo");
-  }
-  f.close();
-
-  if ((max_id + 1) != num_cpus) {
-    fprintf(stderr,
-            "CPU ID assignments in /proc/cpuinfo seem messed up."
-            " This is usually caused by a bad BIOS.\n");
-  }
-  return num_cpus;
-#endif
-  BENCHMARK_UNREACHABLE();
-}
-
-int GetNumCPUs() {
-  const int num_cpus = GetNumCPUsImpl();
-  if (num_cpus < 1) {
-    std::cerr << "Unable to extract number of CPUs.  If your platform uses "
-                 "/proc/cpuinfo, custom support may need to be added.\n";
-  }
-  return num_cpus;
-}
-
-class ThreadAffinityGuard final {
- public:
-  ThreadAffinityGuard() : reset_affinity(SetAffinity()) {
-    if (!reset_affinity)
-      std::cerr << "***WARNING*** Failed to set thread affinity. Estimated CPU "
-                   "frequency may be incorrect."
-                << std::endl;
-  }
-
-  ~ThreadAffinityGuard() {
-    if (!reset_affinity) return;
-
-#if defined(BENCHMARK_HAS_PTHREAD_AFFINITY)
-    int ret = pthread_setaffinity_np(self, sizeof(previous_affinity),
-                                     &previous_affinity);
-    if (ret == 0) return;
-#elif defined(BENCHMARK_OS_WINDOWS_WIN32)
-    DWORD_PTR ret = SetThreadAffinityMask(self, previous_affinity);
-    if (ret != 0) return;
-#endif  // def BENCHMARK_HAS_PTHREAD_AFFINITY
-    PrintErrorAndDie("Failed to reset thread affinity");
-  }
-
-  ThreadAffinityGuard(ThreadAffinityGuard&&) = delete;
-  ThreadAffinityGuard(const ThreadAffinityGuard&) = delete;
-  ThreadAffinityGuard& operator=(ThreadAffinityGuard&&) = delete;
-  ThreadAffinityGuard& operator=(const ThreadAffinityGuard&) = delete;
-
- private:
-  bool SetAffinity() {
-#if defined(BENCHMARK_HAS_PTHREAD_AFFINITY)
-    int ret;
-    self = pthread_self();
-    ret = pthread_getaffinity_np(self, sizeof(previous_affinity),
-                                 &previous_affinity);
-    if (ret != 0) return false;
-
-    cpu_set_t affinity;
-    memcpy(&affinity, &previous_affinity, sizeof(affinity));
-
-    bool is_first_cpu = true;
-
-    for (int i = 0; i < CPU_SETSIZE; ++i)
-      if (CPU_ISSET(i, &affinity)) {
-        if (is_first_cpu)
-          is_first_cpu = false;
-        else
-          CPU_CLR(i, &affinity);
-      }
-
-    if (is_first_cpu) return false;
-
-    ret = pthread_setaffinity_np(self, sizeof(affinity), &affinity);
-    return ret == 0;
-#elif defined(BENCHMARK_OS_WINDOWS_WIN32)
-    self = GetCurrentThread();
-    DWORD_PTR mask = static_cast(1) << GetCurrentProcessorNumber();
-    previous_affinity = SetThreadAffinityMask(self, mask);
-    return previous_affinity != 0;
-#else
-    return false;
-#endif  // def BENCHMARK_HAS_PTHREAD_AFFINITY
-  }
-
-#if defined(BENCHMARK_HAS_PTHREAD_AFFINITY)
-  pthread_t self;
-  cpu_set_t previous_affinity;
-#elif defined(BENCHMARK_OS_WINDOWS_WIN32)
-  HANDLE self;
-  DWORD_PTR previous_affinity;
-#endif  // def BENCHMARK_HAS_PTHREAD_AFFINITY
-  bool reset_affinity;
-};
-
-double GetCPUCyclesPerSecond(CPUInfo::Scaling scaling) {
-  // Currently, scaling is only used on linux path here,
-  // suppress diagnostics about it being unused on other paths.
-  (void)scaling;
-
-#if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN
-  long freq;
-
-  // If the kernel is exporting the tsc frequency use that. There are issues
-  // where cpuinfo_max_freq cannot be relied on because the BIOS may be
-  // exporintg an invalid p-state (on x86) or p-states may be used to put the
-  // processor in a new mode (turbo mode). Essentially, those frequencies
-  // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as
-  // well.
-  if (ReadFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)
-      // If CPU scaling is disabled, use the *current* frequency.
-      // Note that we specifically don't want to read cpuinfo_cur_freq,
-      // because it is only readable by root.
-      || (scaling == CPUInfo::Scaling::DISABLED &&
-          ReadFromFile("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq",
-                       &freq))
-      // Otherwise, if CPU scaling may be in effect, we want to use
-      // the *maximum* frequency, not whatever CPU speed some random processor
-      // happens to be using now.
-      || ReadFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
-                      &freq)) {
-    // The value is in kHz (as the file name suggests).  For example, on a
-    // 2GHz warpstation, the file contains the value "2000000".
-    return static_cast(freq) * 1000.0;
-  }
-
-  const double error_value = -1;
-  double bogo_clock = error_value;
-
-  std::ifstream f("/proc/cpuinfo");
-  if (!f.is_open()) {
-    std::cerr << "failed to open /proc/cpuinfo\n";
-    return error_value;
-  }
-
-  auto StartsWithKey = [](std::string const& Value, std::string const& Key) {
-    if (Key.size() > Value.size()) return false;
-    auto Cmp = [&](char X, char Y) {
-      return std::tolower(X) == std::tolower(Y);
-    };
-    return std::equal(Key.begin(), Key.end(), Value.begin(), Cmp);
-  };
-
-  std::string ln;
-  while (std::getline(f, ln)) {
-    if (ln.empty()) continue;
-    std::size_t split_idx = ln.find(':');
-    std::string value;
-    if (split_idx != std::string::npos) value = ln.substr(split_idx + 1);
-    // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only
-    // accept positive values. Some environments (virtual machines) report zero,
-    // which would cause infinite looping in WallTime_Init.
-    if (StartsWithKey(ln, "cpu MHz")) {
-      if (!value.empty()) {
-        double cycles_per_second = benchmark::stod(value) * 1000000.0;
-        if (cycles_per_second > 0) return cycles_per_second;
-      }
-    } else if (StartsWithKey(ln, "bogomips")) {
-      if (!value.empty()) {
-        bogo_clock = benchmark::stod(value) * 1000000.0;
-        if (bogo_clock < 0.0) bogo_clock = error_value;
-      }
-    }
-  }
-  if (f.bad()) {
-    std::cerr << "Failure reading /proc/cpuinfo\n";
-    return error_value;
-  }
-  if (!f.eof()) {
-    std::cerr << "Failed to read to end of /proc/cpuinfo\n";
-    return error_value;
-  }
-  f.close();
-  // If we found the bogomips clock, but nothing better, we'll use it (but
-  // we're not happy about it); otherwise, fallback to the rough estimation
-  // below.
-  if (bogo_clock >= 0.0) return bogo_clock;
-
-#elif defined BENCHMARK_HAS_SYSCTL
-  constexpr auto* freqStr =
-#if defined(BENCHMARK_OS_FREEBSD) || defined(BENCHMARK_OS_NETBSD)
-      "machdep.tsc_freq";
-#elif defined BENCHMARK_OS_OPENBSD
-      "hw.cpuspeed";
-#elif defined BENCHMARK_OS_DRAGONFLY
-      "hw.tsc_frequency";
-#else
-      "hw.cpufrequency";
-#endif
-  unsigned long long hz = 0;
-#if defined BENCHMARK_OS_OPENBSD
-  if (GetSysctl(freqStr, &hz)) return static_cast(hz * 1000000);
-#else
-  if (GetSysctl(freqStr, &hz)) return static_cast(hz);
-#endif
-  fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n",
-          freqStr, strerror(errno));
-  fprintf(stderr,
-          "This does not affect benchmark measurements, only the "
-          "metadata output.\n");
-
-#elif defined BENCHMARK_OS_WINDOWS_WIN32
-  // In NT, read MHz from the registry. If we fail to do so or we're in win9x
-  // then make a crude estimate.
-  DWORD data, data_size = sizeof(data);
-  if (IsWindowsXPOrGreater() &&
-      SUCCEEDED(
-          SHGetValueA(HKEY_LOCAL_MACHINE,
-                      "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
-                      "~MHz", nullptr, &data, &data_size)))
-    return static_cast(static_cast(data) *
-                               static_cast(1000 * 1000));  // was mhz
-#elif defined(BENCHMARK_OS_SOLARIS)
-  kstat_ctl_t* kc = kstat_open();
-  if (!kc) {
-    std::cerr << "failed to open /dev/kstat\n";
-    return -1;
-  }
-  kstat_t* ksp = kstat_lookup(kc, const_cast("cpu_info"), -1,
-                              const_cast("cpu_info0"));
-  if (!ksp) {
-    std::cerr << "failed to lookup in /dev/kstat\n";
-    return -1;
-  }
-  if (kstat_read(kc, ksp, NULL) < 0) {
-    std::cerr << "failed to read from /dev/kstat\n";
-    return -1;
-  }
-  kstat_named_t* knp = (kstat_named_t*)kstat_data_lookup(
-      ksp, const_cast("current_clock_Hz"));
-  if (!knp) {
-    std::cerr << "failed to lookup data in /dev/kstat\n";
-    return -1;
-  }
-  if (knp->data_type != KSTAT_DATA_UINT64) {
-    std::cerr << "current_clock_Hz is of unexpected data type: "
-              << knp->data_type << "\n";
-    return -1;
-  }
-  double clock_hz = knp->value.ui64;
-  kstat_close(kc);
-  return clock_hz;
-#elif defined(BENCHMARK_OS_QNX)
-  return static_cast(
-      static_cast(SYSPAGE_ENTRY(cpuinfo)->speed) *
-      static_cast(1000 * 1000));
-#elif defined(BENCHMARK_OS_QURT)
-  // QuRT doesn't provide any API to query Hexagon frequency.
-  return 1000000000;
-#endif
-  // If we've fallen through, attempt to roughly estimate the CPU clock rate.
-
-  // Make sure to use the same cycle counter when starting and stopping the
-  // cycle timer. We just pin the current thread to a cpu in the previous
-  // affinity set.
-  ThreadAffinityGuard affinity_guard;
-
-  static constexpr double estimate_time_s = 1.0;
-  const double start_time = ChronoClockNow();
-  const auto start_ticks = cycleclock::Now();
-
-  // Impose load instead of calling sleep() to make sure the cycle counter
-  // works.
-  using PRNG = std::minstd_rand;
-  using Result = PRNG::result_type;
-  PRNG rng(static_cast(start_ticks));
-
-  Result state = 0;
-
-  do {
-    static constexpr size_t batch_size = 10000;
-    rng.discard(batch_size);
-    state += rng();
-
-  } while (ChronoClockNow() - start_time < estimate_time_s);
-
-  DoNotOptimize(state);
-
-  const auto end_ticks = cycleclock::Now();
-  const double end_time = ChronoClockNow();
-
-  return static_cast(end_ticks - start_ticks) / (end_time - start_time);
-  // Reset the affinity of current thread when the lifetime of affinity_guard
-  // ends.
-}
-
-std::vector GetLoadAvg() {
-#if (defined BENCHMARK_OS_FREEBSD || defined(BENCHMARK_OS_LINUX) ||     \
-     defined BENCHMARK_OS_MACOSX || defined BENCHMARK_OS_NETBSD ||      \
-     defined BENCHMARK_OS_OPENBSD || defined BENCHMARK_OS_DRAGONFLY) && \
-    !(defined(__ANDROID__) && __ANDROID_API__ < 29)
-  static constexpr int kMaxSamples = 3;
-  std::vector res(kMaxSamples, 0.0);
-  const size_t nelem = static_cast(getloadavg(res.data(), kMaxSamples));
-  if (nelem < 1) {
-    res.clear();
-  } else {
-    res.resize(nelem);
-  }
-  return res;
-#else
-  return {};
-#endif
-}
-
-}  // end namespace
-
-const CPUInfo& CPUInfo::Get() {
-  static const CPUInfo* info = new CPUInfo();
-  return *info;
-}
-
-CPUInfo::CPUInfo()
-    : num_cpus(GetNumCPUs()),
-      scaling(CpuScaling(num_cpus)),
-      cycles_per_second(GetCPUCyclesPerSecond(scaling)),
-      caches(GetCacheSizes()),
-      load_avg(GetLoadAvg()) {}
-
-const SystemInfo& SystemInfo::Get() {
-  static const SystemInfo* info = new SystemInfo();
-  return *info;
-}
-
-SystemInfo::SystemInfo() : name(GetSystemName()) {}
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/thread_manager.h b/vendor/core/vendor/googlebenchmark/src/thread_manager.h
deleted file mode 100644
index 819b3c44d..000000000
--- a/vendor/core/vendor/googlebenchmark/src/thread_manager.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef BENCHMARK_THREAD_MANAGER_H
-#define BENCHMARK_THREAD_MANAGER_H
-
-#include 
-
-#include "benchmark/benchmark.h"
-#include "mutex.h"
-
-namespace benchmark {
-namespace internal {
-
-class ThreadManager {
- public:
-  explicit ThreadManager(int num_threads)
-      : alive_threads_(num_threads), start_stop_barrier_(num_threads) {}
-
-  Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) {
-    return benchmark_mutex_;
-  }
-
-  bool StartStopBarrier() EXCLUDES(end_cond_mutex_) {
-    return start_stop_barrier_.wait();
-  }
-
-  void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) {
-    start_stop_barrier_.removeThread();
-    if (--alive_threads_ == 0) {
-      MutexLock lock(end_cond_mutex_);
-      end_condition_.notify_all();
-    }
-  }
-
-  void WaitForAllThreads() EXCLUDES(end_cond_mutex_) {
-    MutexLock lock(end_cond_mutex_);
-    end_condition_.wait(lock.native_handle(),
-                        [this]() { return alive_threads_ == 0; });
-  }
-
-  struct Result {
-    IterationCount iterations = 0;
-    double real_time_used = 0;
-    double cpu_time_used = 0;
-    double manual_time_used = 0;
-    int64_t complexity_n = 0;
-    std::string report_label_;
-    std::string skip_message_;
-    internal::Skipped skipped_ = internal::NotSkipped;
-    UserCounters counters;
-  };
-  GUARDED_BY(GetBenchmarkMutex()) Result results;
-
- private:
-  mutable Mutex benchmark_mutex_;
-  std::atomic alive_threads_;
-  Barrier start_stop_barrier_;
-  Mutex end_cond_mutex_;
-  Condition end_condition_;
-};
-
-}  // namespace internal
-}  // namespace benchmark
-
-#endif  // BENCHMARK_THREAD_MANAGER_H
diff --git a/vendor/core/vendor/googlebenchmark/src/thread_timer.h b/vendor/core/vendor/googlebenchmark/src/thread_timer.h
deleted file mode 100644
index eb23f5956..000000000
--- a/vendor/core/vendor/googlebenchmark/src/thread_timer.h
+++ /dev/null
@@ -1,86 +0,0 @@
-#ifndef BENCHMARK_THREAD_TIMER_H
-#define BENCHMARK_THREAD_TIMER_H
-
-#include "check.h"
-#include "timers.h"
-
-namespace benchmark {
-namespace internal {
-
-class ThreadTimer {
-  explicit ThreadTimer(bool measure_process_cpu_time_)
-      : measure_process_cpu_time(measure_process_cpu_time_) {}
-
- public:
-  static ThreadTimer Create() {
-    return ThreadTimer(/*measure_process_cpu_time_=*/false);
-  }
-  static ThreadTimer CreateProcessCpuTime() {
-    return ThreadTimer(/*measure_process_cpu_time_=*/true);
-  }
-
-  // Called by each thread
-  void StartTimer() {
-    running_ = true;
-    start_real_time_ = ChronoClockNow();
-    start_cpu_time_ = ReadCpuTimerOfChoice();
-  }
-
-  // Called by each thread
-  void StopTimer() {
-    BM_CHECK(running_);
-    running_ = false;
-    real_time_used_ += ChronoClockNow() - start_real_time_;
-    // Floating point error can result in the subtraction producing a negative
-    // time. Guard against that.
-    cpu_time_used_ +=
-        std::max(ReadCpuTimerOfChoice() - start_cpu_time_, 0);
-  }
-
-  // Called by each thread
-  void SetIterationTime(double seconds) { manual_time_used_ += seconds; }
-
-  bool running() const { return running_; }
-
-  // REQUIRES: timer is not running
-  double real_time_used() const {
-    BM_CHECK(!running_);
-    return real_time_used_;
-  }
-
-  // REQUIRES: timer is not running
-  double cpu_time_used() const {
-    BM_CHECK(!running_);
-    return cpu_time_used_;
-  }
-
-  // REQUIRES: timer is not running
-  double manual_time_used() const {
-    BM_CHECK(!running_);
-    return manual_time_used_;
-  }
-
- private:
-  double ReadCpuTimerOfChoice() const {
-    if (measure_process_cpu_time) return ProcessCPUUsage();
-    return ThreadCPUUsage();
-  }
-
-  // should the thread, or the process, time be measured?
-  const bool measure_process_cpu_time;
-
-  bool running_ = false;        // Is the timer running
-  double start_real_time_ = 0;  // If running_
-  double start_cpu_time_ = 0;   // If running_
-
-  // Accumulated time so far (does not contain current slice if running_)
-  double real_time_used_ = 0;
-  double cpu_time_used_ = 0;
-  // Manually set iteration time. User sets this with SetIterationTime(seconds).
-  double manual_time_used_ = 0;
-};
-
-}  // namespace internal
-}  // namespace benchmark
-
-#endif  // BENCHMARK_THREAD_TIMER_H
diff --git a/vendor/core/vendor/googlebenchmark/src/timers.cc b/vendor/core/vendor/googlebenchmark/src/timers.cc
deleted file mode 100644
index 7ba540b88..000000000
--- a/vendor/core/vendor/googlebenchmark/src/timers.cc
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "timers.h"
-
-#include "internal_macros.h"
-
-#ifdef BENCHMARK_OS_WINDOWS
-#include 
-#undef StrCat  // Don't let StrCat in string_util.h be renamed to lstrcatA
-#include 
-#include 
-#else
-#include 
-#if !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
-#include 
-#endif
-#include 
-#include   // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
-#include 
-#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_DRAGONFLY || \
-    defined BENCHMARK_OS_MACOSX
-#include 
-#endif
-#if defined(BENCHMARK_OS_MACOSX)
-#include 
-#include 
-#include 
-#endif
-#if defined(BENCHMARK_OS_QURT)
-#include 
-#endif
-#endif
-
-#ifdef BENCHMARK_OS_EMSCRIPTEN
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "check.h"
-#include "log.h"
-#include "string_util.h"
-
-namespace benchmark {
-
-// Suppress unused warnings on helper functions.
-#if defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-#if defined(__NVCOMPILER)
-#pragma diag_suppress declared_but_not_referenced
-#endif
-
-namespace {
-#if defined(BENCHMARK_OS_WINDOWS)
-double MakeTime(FILETIME const& kernel_time, FILETIME const& user_time) {
-  ULARGE_INTEGER kernel;
-  ULARGE_INTEGER user;
-  kernel.HighPart = kernel_time.dwHighDateTime;
-  kernel.LowPart = kernel_time.dwLowDateTime;
-  user.HighPart = user_time.dwHighDateTime;
-  user.LowPart = user_time.dwLowDateTime;
-  return (static_cast(kernel.QuadPart) +
-          static_cast(user.QuadPart)) *
-         1e-7;
-}
-#elif !defined(BENCHMARK_OS_FUCHSIA) && !defined(BENCHMARK_OS_QURT)
-double MakeTime(struct rusage const& ru) {
-  return (static_cast(ru.ru_utime.tv_sec) +
-          static_cast(ru.ru_utime.tv_usec) * 1e-6 +
-          static_cast(ru.ru_stime.tv_sec) +
-          static_cast(ru.ru_stime.tv_usec) * 1e-6);
-}
-#endif
-#if defined(BENCHMARK_OS_MACOSX)
-double MakeTime(thread_basic_info_data_t const& info) {
-  return (static_cast(info.user_time.seconds) +
-          static_cast(info.user_time.microseconds) * 1e-6 +
-          static_cast(info.system_time.seconds) +
-          static_cast(info.system_time.microseconds) * 1e-6);
-}
-#endif
-#if defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_THREAD_CPUTIME_ID)
-double MakeTime(struct timespec const& ts) {
-  return static_cast(ts.tv_sec) +
-         (static_cast(ts.tv_nsec) * 1e-9);
-}
-#endif
-
-BENCHMARK_NORETURN static void DiagnoseAndExit(const char* msg) {
-  std::cerr << "ERROR: " << msg << std::endl;
-  std::exit(EXIT_FAILURE);
-}
-
-}  // end namespace
-
-double ProcessCPUUsage() {
-#if defined(BENCHMARK_OS_WINDOWS)
-  HANDLE proc = GetCurrentProcess();
-  FILETIME creation_time;
-  FILETIME exit_time;
-  FILETIME kernel_time;
-  FILETIME user_time;
-  if (GetProcessTimes(proc, &creation_time, &exit_time, &kernel_time,
-                      &user_time))
-    return MakeTime(kernel_time, user_time);
-  DiagnoseAndExit("GetProccessTimes() failed");
-#elif defined(BENCHMARK_OS_QURT)
-  // Note that qurt_timer_get_ticks() is no longer documented as of SDK 5.3.0,
-  // and doesn't appear to work on at least some devices (eg Samsung S22),
-  // so let's use the actually-documented and apparently-equivalent
-  // qurt_sysclock_get_hw_ticks() call instead.
-  return static_cast(
-             qurt_timer_timetick_to_us(qurt_sysclock_get_hw_ticks())) *
-         1.0e-6;
-#elif defined(BENCHMARK_OS_EMSCRIPTEN)
-  // clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) returns 0 on Emscripten.
-  // Use Emscripten-specific API. Reported CPU time would be exactly the
-  // same as total time, but this is ok because there aren't long-latency
-  // synchronous system calls in Emscripten.
-  return emscripten_get_now() * 1e-3;
-#elif defined(CLOCK_PROCESS_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
-  // FIXME We want to use clock_gettime, but its not available in MacOS 10.11.
-  // See https://github.com/google/benchmark/pull/292
-  struct timespec spec;
-  if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &spec) == 0)
-    return MakeTime(spec);
-  DiagnoseAndExit("clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) failed");
-#else
-  struct rusage ru;
-  if (getrusage(RUSAGE_SELF, &ru) == 0) return MakeTime(ru);
-  DiagnoseAndExit("getrusage(RUSAGE_SELF, ...) failed");
-#endif
-}
-
-double ThreadCPUUsage() {
-#if defined(BENCHMARK_OS_WINDOWS)
-  HANDLE this_thread = GetCurrentThread();
-  FILETIME creation_time;
-  FILETIME exit_time;
-  FILETIME kernel_time;
-  FILETIME user_time;
-  GetThreadTimes(this_thread, &creation_time, &exit_time, &kernel_time,
-                 &user_time);
-  return MakeTime(kernel_time, user_time);
-#elif defined(BENCHMARK_OS_QURT)
-  // Note that qurt_timer_get_ticks() is no longer documented as of SDK 5.3.0,
-  // and doesn't appear to work on at least some devices (eg Samsung S22),
-  // so let's use the actually-documented and apparently-equivalent
-  // qurt_sysclock_get_hw_ticks() call instead.
-  return static_cast(
-             qurt_timer_timetick_to_us(qurt_sysclock_get_hw_ticks())) *
-         1.0e-6;
-#elif defined(BENCHMARK_OS_MACOSX)
-  // FIXME We want to use clock_gettime, but its not available in MacOS 10.11.
-  // See https://github.com/google/benchmark/pull/292
-  mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
-  thread_basic_info_data_t info;
-  mach_port_t thread = pthread_mach_thread_np(pthread_self());
-  if (thread_info(thread, THREAD_BASIC_INFO,
-                  reinterpret_cast(&info),
-                  &count) == KERN_SUCCESS) {
-    return MakeTime(info);
-  }
-  DiagnoseAndExit("ThreadCPUUsage() failed when evaluating thread_info");
-#elif defined(BENCHMARK_OS_EMSCRIPTEN)
-  // Emscripten doesn't support traditional threads
-  return ProcessCPUUsage();
-#elif defined(BENCHMARK_OS_RTEMS)
-  // RTEMS doesn't support CLOCK_THREAD_CPUTIME_ID. See
-  // https://github.com/RTEMS/rtems/blob/master/cpukit/posix/src/clockgettime.c
-  return ProcessCPUUsage();
-#elif defined(BENCHMARK_OS_ZOS)
-  // z/OS doesn't support CLOCK_THREAD_CPUTIME_ID.
-  return ProcessCPUUsage();
-#elif defined(BENCHMARK_OS_SOLARIS)
-  struct rusage ru;
-  if (getrusage(RUSAGE_LWP, &ru) == 0) return MakeTime(ru);
-  DiagnoseAndExit("getrusage(RUSAGE_LWP, ...) failed");
-#elif defined(CLOCK_THREAD_CPUTIME_ID)
-  struct timespec ts;
-  if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0) return MakeTime(ts);
-  DiagnoseAndExit("clock_gettime(CLOCK_THREAD_CPUTIME_ID, ...) failed");
-#else
-#error Per-thread timing is not available on your system.
-#endif
-}
-
-std::string LocalDateTimeString() {
-  // Write the local time in RFC3339 format yyyy-mm-ddTHH:MM:SS+/-HH:MM.
-  typedef std::chrono::system_clock Clock;
-  std::time_t now = Clock::to_time_t(Clock::now());
-  const std::size_t kTzOffsetLen = 6;
-  const std::size_t kTimestampLen = 19;
-
-  std::size_t tz_len;
-  std::size_t timestamp_len;
-  long int offset_minutes;
-  char tz_offset_sign = '+';
-  // tz_offset is set in one of three ways:
-  // * strftime with %z - This either returns empty or the ISO 8601 time.  The
-  // maximum length an
-  //   ISO 8601 string can be is 7 (e.g. -03:30, plus trailing zero).
-  // * snprintf with %c%02li:%02li - The maximum length is 41 (one for %c, up to
-  // 19 for %02li,
-  //   one for :, up to 19 %02li, plus trailing zero).
-  // * A fixed string of "-00:00".  The maximum length is 7 (-00:00, plus
-  // trailing zero).
-  //
-  // Thus, the maximum size this needs to be is 41.
-  char tz_offset[41];
-  // Long enough buffer to avoid format-overflow warnings
-  char storage[128];
-
-#if defined(BENCHMARK_OS_WINDOWS)
-  std::tm* timeinfo_p = ::localtime(&now);
-#else
-  std::tm timeinfo;
-  std::tm* timeinfo_p = &timeinfo;
-  ::localtime_r(&now, &timeinfo);
-#endif
-
-  tz_len = std::strftime(tz_offset, sizeof(tz_offset), "%z", timeinfo_p);
-
-  if (tz_len < kTzOffsetLen && tz_len > 1) {
-    // Timezone offset was written. strftime writes offset as +HHMM or -HHMM,
-    // RFC3339 specifies an offset as +HH:MM or -HH:MM. To convert, we parse
-    // the offset as an integer, then reprint it to a string.
-
-    offset_minutes = ::strtol(tz_offset, NULL, 10);
-    if (offset_minutes < 0) {
-      offset_minutes *= -1;
-      tz_offset_sign = '-';
-    }
-
-    tz_len = static_cast(
-        ::snprintf(tz_offset, sizeof(tz_offset), "%c%02li:%02li",
-                   tz_offset_sign, offset_minutes / 100, offset_minutes % 100));
-    BM_CHECK(tz_len == kTzOffsetLen);
-    ((void)tz_len);  // Prevent unused variable warning in optimized build.
-  } else {
-    // Unknown offset. RFC3339 specifies that unknown local offsets should be
-    // written as UTC time with -00:00 timezone.
-#if defined(BENCHMARK_OS_WINDOWS)
-    // Potential race condition if another thread calls localtime or gmtime.
-    timeinfo_p = ::gmtime(&now);
-#else
-    ::gmtime_r(&now, &timeinfo);
-#endif
-
-    strncpy(tz_offset, "-00:00", kTzOffsetLen + 1);
-  }
-
-  timestamp_len =
-      std::strftime(storage, sizeof(storage), "%Y-%m-%dT%H:%M:%S", timeinfo_p);
-  BM_CHECK(timestamp_len == kTimestampLen);
-  // Prevent unused variable warning in optimized build.
-  ((void)kTimestampLen);
-
-  std::strncat(storage, tz_offset, sizeof(storage) - timestamp_len - 1);
-  return std::string(storage);
-}
-
-}  // end namespace benchmark
diff --git a/vendor/core/vendor/googlebenchmark/src/timers.h b/vendor/core/vendor/googlebenchmark/src/timers.h
deleted file mode 100644
index 690086b36..000000000
--- a/vendor/core/vendor/googlebenchmark/src/timers.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef BENCHMARK_TIMERS_H
-#define BENCHMARK_TIMERS_H
-
-#include 
-#include 
-
-namespace benchmark {
-
-// Return the CPU usage of the current process
-double ProcessCPUUsage();
-
-// Return the CPU usage of the children of the current process
-double ChildrenCPUUsage();
-
-// Return the CPU usage of the current thread
-double ThreadCPUUsage();
-
-#if defined(BENCHMARK_OS_QURT)
-
-// std::chrono::now() can return 0 on some Hexagon devices;
-// this reads the value of a 56-bit, 19.2MHz hardware counter
-// and converts it to seconds. Unlike std::chrono, this doesn't
-// return an absolute time, but since ChronoClockNow() is only used
-// to compute elapsed time, this shouldn't matter.
-struct QuRTClock {
-  typedef uint64_t rep;
-  typedef std::ratio<1, 19200000> period;
-  typedef std::chrono::duration duration;
-  typedef std::chrono::time_point time_point;
-  static const bool is_steady = false;
-
-  static time_point now() {
-    unsigned long long count;
-    asm volatile(" %0 = c31:30 " : "=r"(count));
-    return time_point(static_cast(count));
-  }
-};
-
-#else
-
-#if defined(HAVE_STEADY_CLOCK)
-template 
-struct ChooseSteadyClock {
-  typedef std::chrono::high_resolution_clock type;
-};
-
-template <>
-struct ChooseSteadyClock {
-  typedef std::chrono::steady_clock type;
-};
-#endif  // HAVE_STEADY_CLOCK
-
-#endif
-
-struct ChooseClockType {
-#if defined(BENCHMARK_OS_QURT)
-  typedef QuRTClock type;
-#elif defined(HAVE_STEADY_CLOCK)
-  typedef ChooseSteadyClock<>::type type;
-#else
-  typedef std::chrono::high_resolution_clock type;
-#endif
-};
-
-inline double ChronoClockNow() {
-  typedef ChooseClockType::type ClockType;
-  using FpSeconds = std::chrono::duration;
-  return FpSeconds(ClockType::now().time_since_epoch()).count();
-}
-
-std::string LocalDateTimeString();
-
-}  // end namespace benchmark
-
-#endif  // BENCHMARK_TIMERS_H

From c3e641b2806f972a21441b25d09ecc7e62aafc28 Mon Sep 17 00:00:00 2001
From: Juan Cruz Viotti 
Date: Mon, 21 Sep 2026 10:26:49 -0300
Subject: [PATCH 2/2] More

Signed-off-by: Juan Cruz Viotti 
---
 DEPENDENCIES                                  |   2 +-
 test/e2e/CMakeLists.txt                       |   2 +-
 test/e2e/runner.cc                            |   9 +-
 vendor/blaze/CMakeLists.txt                   |   9 -
 vendor/blaze/DEPENDENCIES                     |   2 +-
 vendor/blaze/config.cmake.in                  |   3 -
 vendor/blaze/src/format/CMakeLists.txt        |  14 --
 vendor/blaze/src/format/format.cc             | 166 ------------------
 .../format/include/sourcemeta/blaze/format.h  |  60 -------
 9 files changed, 8 insertions(+), 259 deletions(-)
 delete mode 100644 vendor/blaze/src/format/CMakeLists.txt
 delete mode 100644 vendor/blaze/src/format/format.cc
 delete mode 100644 vendor/blaze/src/format/include/sourcemeta/blaze/format.h

diff --git a/DEPENDENCIES b/DEPENDENCIES
index 107c82cc5..783278f6e 100644
--- a/DEPENDENCIES
+++ b/DEPENDENCIES
@@ -1,4 +1,4 @@
 vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02
 core https://github.com/sourcemeta/core 9c3323a59a4f8113e269cfb713c85ba34cf06d96
-blaze https://github.com/sourcemeta/blaze e91f46a5a91fd5a315ab01bac4ed6c3827ac3d95
+blaze https://github.com/sourcemeta/blaze d8d3b28a989b49672fa141b5d37792551999d532
 bootstrap https://github.com/twbs/bootstrap 1a6fdfae6be09b09eaced8f0e442ca6f7680a61e
diff --git a/test/e2e/CMakeLists.txt b/test/e2e/CMakeLists.txt
index f1eec4d63..5fc3bd091 100644
--- a/test/e2e/CMakeLists.txt
+++ b/test/e2e/CMakeLists.txt
@@ -3,7 +3,7 @@ sourcemeta_add_default_options(PRIVATE jsonbinpack_e2e_test_runner)
 target_link_libraries(jsonbinpack_e2e_test_runner PRIVATE sourcemeta::core::json)
 target_link_libraries(jsonbinpack_e2e_test_runner PRIVATE sourcemeta::jsonbinpack::compiler)
 target_link_libraries(jsonbinpack_e2e_test_runner PRIVATE sourcemeta::jsonbinpack::runtime)
-target_link_libraries(jsonbinpack_e2e_test_runner PRIVATE sourcemeta::blaze::format)
+target_link_libraries(jsonbinpack_e2e_test_runner PRIVATE sourcemeta::core::jsonschema)
 set_target_properties(jsonbinpack_e2e_test_runner
   PROPERTIES FOLDER "JSON BinPack/E2E")
 
diff --git a/test/e2e/runner.cc b/test/e2e/runner.cc
index 866700e59..3bb45cfc7 100644
--- a/test/e2e/runner.cc
+++ b/test/e2e/runner.cc
@@ -1,7 +1,6 @@
 #include 
 #include 
 
-#include 
 #include 
 #include 
 
@@ -43,9 +42,11 @@ auto main(int argc, char *argv[]) -> int {
                                         std::ios::binary);
   canonical_output_stream.exceptions(std::ios_base::badbit);
 
-  sourcemeta::blaze::format(schema, sourcemeta::core::schema_walker,
-                            sourcemeta::core::schema_resolver,
-                            "https://json-schema.org/draft/2020-12/schema");
+  const sourcemeta::core::SchemaFrame frame{
+      sourcemeta::core::SchemaFrame::Mode::Locations, schema,
+      sourcemeta::core::schema_walker, sourcemeta::core::schema_resolver,
+      DEFAULT_METASCHEMA};
+  sourcemeta::core::schema_format(schema, frame);
   sourcemeta::core::prettify(schema, canonical_output_stream);
   canonical_output_stream << "\n";
   canonical_output_stream.flush();
diff --git a/vendor/blaze/CMakeLists.txt b/vendor/blaze/CMakeLists.txt
index d0e6be383..b4fc417b3 100644
--- a/vendor/blaze/CMakeLists.txt
+++ b/vendor/blaze/CMakeLists.txt
@@ -16,7 +16,6 @@ option(BLAZE_CANONICALIZER "Build the Blaze canonicalizer library" ON)
 option(BLAZE_CONVERT "Build the Blaze convert library" ON)
 option(BLAZE_EDITOR "Build the Blaze editor schema compatibility library" ON)
 option(BLAZE_BUNDLE "Build the Blaze bundle library" ON)
-option(BLAZE_FORMAT "Build the Blaze format library" ON)
 option(BLAZE_TESTS "Build the Blaze tests" OFF)
 option(BLAZE_BENCHMARK "Build the Blaze benchmarks" OFF)
 option(BLAZE_CONTRIB "Build the Blaze contrib programs" OFF)
@@ -60,10 +59,6 @@ if(BLAZE_BUNDLE)
   add_subdirectory(src/bundle)
 endif()
 
-if(BLAZE_FORMAT)
-  add_subdirectory(src/format)
-endif()
-
 if(BLAZE_COMPILER)
   add_subdirectory(src/compiler)
 endif()
@@ -154,10 +149,6 @@ if(BLAZE_TESTS)
     add_subdirectory(test/bundle)
   endif()
 
-  if(BLAZE_FORMAT)
-    add_subdirectory(test/format)
-  endif()
-
   if(BLAZE_COMPILER)
     add_subdirectory(test/compiler)
   endif()
diff --git a/vendor/blaze/DEPENDENCIES b/vendor/blaze/DEPENDENCIES
index 4111b1d40..a78168aaf 100644
--- a/vendor/blaze/DEPENDENCIES
+++ b/vendor/blaze/DEPENDENCIES
@@ -1,3 +1,3 @@
 vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02
-core https://github.com/sourcemeta/core f3c2038b4c74a558f82b880d1a69e77dd8c8dce6
+core https://github.com/sourcemeta/core 9c3323a59a4f8113e269cfb713c85ba34cf06d96
 jsonschema-test-suite https://github.com/json-schema-org/JSON-Schema-Test-Suite 6648e8194c69697b2e1a15fe76a06a480b183a51
diff --git a/vendor/blaze/config.cmake.in b/vendor/blaze/config.cmake.in
index 85211835a..c21ab40ca 100644
--- a/vendor/blaze/config.cmake.in
+++ b/vendor/blaze/config.cmake.in
@@ -15,7 +15,6 @@ if(NOT BLAZE_COMPONENTS)
   list(APPEND BLAZE_COMPONENTS convert)
   list(APPEND BLAZE_COMPONENTS editor)
   list(APPEND BLAZE_COMPONENTS bundle)
-  list(APPEND BLAZE_COMPONENTS format)
 endif()
 
 include(CMakeFindDependencyMacro)
@@ -79,8 +78,6 @@ foreach(component ${BLAZE_COMPONENTS})
     include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_blaze_editor.cmake")
   elseif(component STREQUAL "bundle")
     include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_blaze_bundle.cmake")
-  elseif(component STREQUAL "format")
-    include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_blaze_format.cmake")
   else()
     message(FATAL_ERROR "Unknown Blaze component: ${component}")
   endif()
diff --git a/vendor/blaze/src/format/CMakeLists.txt b/vendor/blaze/src/format/CMakeLists.txt
deleted file mode 100644
index 1653df996..000000000
--- a/vendor/blaze/src/format/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-sourcemeta_library(NAMESPACE sourcemeta PROJECT blaze NAME format
-  FOLDER "Blaze/Format"
-  SOURCES format.cc)
-
-if(BLAZE_INSTALL)
-  sourcemeta_library_install(NAMESPACE sourcemeta PROJECT blaze NAME format)
-endif()
-
-target_link_libraries(sourcemeta_blaze_format PUBLIC
-  sourcemeta::core::json)
-target_link_libraries(sourcemeta_blaze_format PUBLIC
-  sourcemeta::core::jsonpointer)
-target_link_libraries(sourcemeta_blaze_format PUBLIC
-  sourcemeta::core::jsonschema)
diff --git a/vendor/blaze/src/format/format.cc b/vendor/blaze/src/format/format.cc
deleted file mode 100644
index 53cf2311c..000000000
--- a/vendor/blaze/src/format/format.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-#include 
-
-#include 
-
-#include        // std::uint64_t
-#include         // std::numeric_limits
-#include    // std::string_view
-#include  // std::unordered_map
-#include         // std::vector
-
-namespace {
-
-auto keyword_rank(const sourcemeta::core::JSON::String &keyword,
-                  const std::uint64_t otherwise) -> std::uint64_t {
-  using Rank =
-      std::unordered_map;
-  static Rank rank{// Most core keywords tend to come first
-                   {"$schema", 0},
-                   {"$id", 1},
-                   {"id", 2},
-                   {"$vocabulary", 3},
-                   {"$anchor", 4},
-                   {"$dynamicAnchor", 5},
-                   {"$recursiveAnchor", 6},
-
-                   // Then important metadata about the schema
-                   {"title", 7},
-                   {"description", 8},
-                   {"$comment", 10},
-                   {"examples", 11},
-                   {"deprecated", 12},
-                   {"readOnly", 13},
-                   {"writeOnly", 14},
-                   {"default", 15},
-
-                   // This is a placeholder for "x-"-prefixed unknown keywords,
-                   // as they are almost always metadata
-                   {"x-", 16},
-
-                   // Then references
-                   {"$ref", 17},
-                   {"$dynamicRef", 18},
-                   {"$recursiveRef", 19},
-
-                   // Then keywords that apply to any type
-                   {"type", 20},
-                   {"disallow", 21},
-                   {"extends", 22},
-                   {"const", 23},
-                   {"enum", 24},
-                   {"optional", 25},
-                   {"requires", 26},
-                   {"allOf", 27},
-                   {"anyOf", 28},
-                   {"oneOf", 29},
-                   {"not", 30},
-                   {"if", 31},
-                   {"then", 32},
-                   {"else", 33},
-
-                   // Then keywords about numbers
-                   {"exclusiveMaximum", 34},
-                   {"maximum", 35},
-                   {"maximumCanEqual", 36},
-                   {"exclusiveMinimum", 37},
-                   {"minimum", 38},
-                   {"minimumCanEqual", 39},
-                   {"multipleOf", 40},
-                   {"divisibleBy", 41},
-                   {"maxDecimal", 42},
-
-                   // Then keywords about strings
-                   {"pattern", 43},
-                   {"format", 44},
-                   {"maxLength", 45},
-                   {"minLength", 46},
-                   {"contentEncoding", 47},
-                   {"contentMediaType", 48},
-                   {"contentSchema", 49},
-
-                   // Then keywords about arrays
-                   {"maxItems", 50},
-                   {"minItems", 51},
-                   {"uniqueItems", 52},
-                   {"maxContains", 53},
-                   {"minContains", 54},
-                   {"contains", 55},
-                   {"prefixItems", 56},
-                   {"items", 57},
-                   {"additionalItems", 58},
-                   {"unevaluatedItems", 59},
-
-                   // Object
-                   {"required", 60},
-                   {"maxProperties", 61},
-                   {"minProperties", 62},
-                   {"propertyNames", 63},
-                   {"properties", 64},
-                   {"patternProperties", 65},
-                   {"additionalProperties", 66},
-                   {"unevaluatedProperties", 67},
-                   {"dependentRequired", 68},
-                   {"dependencies", 69},
-                   {"dependentSchemas", 70},
-
-                   // Reusable utilities go last
-                   {"$defs", 71},
-                   {"definitions", 72}};
-
-  // Handle `x-` prefixed unknown keywords
-  if (keyword.starts_with("x-")) {
-    const auto match{rank.find("x-")};
-    assert(match != rank.cend());
-    return match->second;
-  }
-
-  const auto match{rank.find(keyword)};
-  if (match != rank.cend()) {
-    return match->second;
-  }
-  return otherwise;
-}
-
-auto keyword_compare(const sourcemeta::core::JSON::String &left,
-                     const sourcemeta::core::JSON::String &right) -> bool {
-  constexpr auto DEFAULT{std::numeric_limits::max()};
-  const auto left_rank{keyword_rank(left, DEFAULT)};
-  const auto right_rank{keyword_rank(right, DEFAULT)};
-  if (left_rank == right_rank) {
-    return left < right;
-  }
-  return left_rank < right_rank;
-}
-
-} // namespace
-
-namespace sourcemeta::blaze {
-
-auto format(sourcemeta::core::JSON &schema,
-            const sourcemeta::core::SchemaWalker &walker,
-            const sourcemeta::core::SchemaResolver &resolver,
-            std::string_view default_dialect) -> void {
-  assert((schema.is_object() || schema.is_boolean()));
-  std::vector subschemas;
-
-  {
-    sourcemeta::core::SchemaFrame frame{
-        sourcemeta::core::SchemaFrame::Mode::Locations, schema, walker,
-        resolver, default_dialect};
-
-    frame.for_each_subschema(
-        [&subschemas](
-            const sourcemeta::core::SchemaFrame::Location &location) -> void {
-          subschemas.push_back(sourcemeta::core::to_pointer(location.pointer));
-        });
-  }
-
-  for (const auto &pointer : subschemas) {
-    auto &subschema{sourcemeta::core::get(schema, pointer)};
-    if (subschema.is_object()) {
-      subschema.reorder(keyword_compare);
-    }
-  }
-}
-
-} // namespace sourcemeta::blaze
diff --git a/vendor/blaze/src/format/include/sourcemeta/blaze/format.h b/vendor/blaze/src/format/include/sourcemeta/blaze/format.h
deleted file mode 100644
index e7e757b37..000000000
--- a/vendor/blaze/src/format/include/sourcemeta/blaze/format.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef SOURCEMETA_BLAZE_FORMAT_H_
-#define SOURCEMETA_BLAZE_FORMAT_H_
-
-/// @defgroup format Format
-/// @brief Format JSON Schemas by reordering keywords into a canonical order.
-///
-/// This functionality is included as follows:
-///
-/// ```cpp
-/// #include 
-/// ```
-
-#ifndef SOURCEMETA_BLAZE_FORMAT_EXPORT
-#include 
-#endif
-
-#include 
-
-#include 
-
-#include  // std::string_view
-
-namespace sourcemeta::blaze {
-
-/// @ingroup format
-///
-/// Format a JSON Schema document by reordering all object properties throughout
-/// the entire document according to an opinionated JSON Schema aware ordering.
-/// This function modifies the schema in-place. For example:
-///
-/// ```cpp
-/// #include 
-/// #include 
-///
-/// #include 
-///
-/// #include 
-/// #include 
-///
-/// sourcemeta::core::JSON schema =
-///   sourcemeta::core::parse_json(R"JSON({
-///     "type": "string",
-///     "minLength": 3,
-///     "$schema": "https://json-schema.org/draft/2020-12/schema"
-///   })JSON");
-/// sourcemeta::blaze::format(schema, sourcemeta::core::schema_walker,
-///                           sourcemeta::core::schema_resolver);
-/// std::ostringstream stream;
-/// sourcemeta::core::prettify(schema, stream);
-/// std::cout << stream.str() << std::endl;
-/// ```
-SOURCEMETA_BLAZE_FORMAT_EXPORT
-auto format(sourcemeta::core::JSON &schema,
-            const sourcemeta::core::SchemaWalker &walker,
-            const sourcemeta::core::SchemaResolver &resolver,
-            std::string_view default_dialect = "") -> void;
-
-} // namespace sourcemeta::blaze
-
-#endif