更新第三方库
This commit is contained in:
parent
b77ab4bb3d
commit
1113c5332a
1
3rdparty/MicroTeX
vendored
Submodule
1
3rdparty/MicroTeX
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 086f4eb740270b28bd0c61a0a359aea9300d61ae
|
||||
18
3rdparty/cmark-gfm/.editorconfig
vendored
Normal file
18
3rdparty/cmark-gfm/.editorconfig
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{c,h}]
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
83
3rdparty/cmark-gfm/.github/workflows/ci.yml
vendored
Normal file
83
3rdparty/cmark-gfm/.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
name: CI tests
|
||||
|
||||
on: [push, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
cmake_opts:
|
||||
- '-DCMARK_SHARED=ON'
|
||||
- ''
|
||||
compiler:
|
||||
- c: 'clang'
|
||||
cpp: 'clang++'
|
||||
- c: 'gcc'
|
||||
cpp: 'g++'
|
||||
env:
|
||||
CMAKE_OPTIONS: ${{ matrix.cmake_opts }}
|
||||
CC: ${{ matrix.compiler.c }}
|
||||
CXX: ${{ matrix.compiler.cpp }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Install valgrind
|
||||
run: |
|
||||
sudo apt install -y valgrind
|
||||
- name: Build and test
|
||||
run: |
|
||||
make
|
||||
make test
|
||||
make leakcheck
|
||||
|
||||
macos:
|
||||
|
||||
runs-on: macOS-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
cmake_opts:
|
||||
- '-DCMARK_SHARED=ON'
|
||||
- ''
|
||||
compiler:
|
||||
- c: 'clang'
|
||||
cpp: 'clang++'
|
||||
- c: 'gcc'
|
||||
cpp: 'g++'
|
||||
env:
|
||||
CMAKE_OPTIONS: ${{ matrix.cmake_opts }}
|
||||
CC: ${{ matrix.compiler.c }}
|
||||
CXX: ${{ matrix.compiler.cpp }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Build and test
|
||||
env:
|
||||
CMAKE_OPTIONS: -DCMARK_SHARED=OFF
|
||||
run: |
|
||||
make
|
||||
make test
|
||||
|
||||
windows:
|
||||
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
cmake_opts:
|
||||
- '-DCMARK_SHARED=ON'
|
||||
- ''
|
||||
env:
|
||||
CMAKE_OPTIONS: ${{ matrix.cmake_opts }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Build and test
|
||||
run: |
|
||||
chcp 65001
|
||||
nmake.exe /nologo /f Makefile.nmake test
|
||||
shell: cmd
|
||||
77
3rdparty/cmark-gfm/.github/workflows/codeql.yml
vendored
Normal file
77
3rdparty/cmark-gfm/.github/workflows/codeql.yml
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: '45 14 * * 3'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'cpp', 'javascript', 'python', 'ruby' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
|
||||
# Use only 'java' to analyze code written in Java, Kotlin or both
|
||||
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
42
3rdparty/cmark-gfm/.gitignore
vendored
Normal file
42
3rdparty/cmark-gfm/.gitignore
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
*.pyc
|
||||
|
||||
*~
|
||||
*.bak
|
||||
*.diff
|
||||
*#
|
||||
*.zip
|
||||
bstrlib.txt
|
||||
build
|
||||
cmark.dSYM/*
|
||||
cmark
|
||||
.vscode
|
||||
.DS_Store
|
||||
|
||||
# Testing and benchmark
|
||||
alltests.md
|
||||
progit/
|
||||
bench/benchinput.md
|
||||
test/afl_results/
|
||||
40
3rdparty/cmark-gfm/.travis.yml
vendored
Normal file
40
3rdparty/cmark-gfm/.travis.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
# Ensures that sudo is disabled, so that containerized builds are allowed
|
||||
sudo: false
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
language: c
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: CMAKE_OPTIONS="-DCMARK_SHARED=OFF"
|
||||
addons:
|
||||
apt:
|
||||
# we need a more recent cmake than travis/linux provides (at least 2.8.9):
|
||||
sources:
|
||||
- kubuntu-backports
|
||||
- kalakris-cmake
|
||||
packages:
|
||||
- cmake
|
||||
- python3
|
||||
- valgrind
|
||||
before_install:
|
||||
- |
|
||||
if [ ${TRAVIS_OS_NAME:-'linux'} = 'osx' ]
|
||||
then
|
||||
echo "Building without python3, to make sure that works."
|
||||
fi
|
||||
|
||||
script:
|
||||
- (mkdir -p build && cd build && cmake $CMAKE_OPTIONS ..)
|
||||
- make test
|
||||
- |
|
||||
if [ ${TRAVIS_OS_NAME:-'linux'} = 'linux' ]
|
||||
then
|
||||
make leakcheck
|
||||
fi
|
||||
48
3rdparty/cmark-gfm/CMakeLists.txt
vendored
Normal file
48
3rdparty/cmark-gfm/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(cmark-gfm)
|
||||
|
||||
set(PROJECT_VERSION_MAJOR 0)
|
||||
set(PROJECT_VERSION_MINOR 29)
|
||||
set(PROJECT_VERSION_PATCH 0)
|
||||
set(PROJECT_VERSION_GFM 13)
|
||||
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.gfm.${PROJECT_VERSION_GFM})
|
||||
|
||||
include("FindAsan.cmake")
|
||||
include("CheckFileOffsetBits.cmake")
|
||||
|
||||
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
|
||||
message(FATAL_ERROR "Do not build in-source.\nPlease remove CMakeCache.txt and the CMakeFiles/ directory.\nThen: mkdir build ; cd build ; cmake .. ; make")
|
||||
endif()
|
||||
|
||||
option(CMARK_TESTS "Build cmark-gfm tests and enable testing" OFF)
|
||||
option(CMARK_STATIC "Build static libcmark-gfm library" ON)
|
||||
option(CMARK_SHARED "Build shared libcmark-gfm library" OFF)
|
||||
option(CMARK_LIB_FUZZER "Build libFuzzer fuzzing harness" OFF)
|
||||
option(CMARK_FUZZ_QUADRATIC "Build quadratic fuzzing harness" OFF)
|
||||
|
||||
if(CMARK_FUZZ_QUADRATIC)
|
||||
set(FUZZER_FLAGS "-fsanitize=fuzzer-no-link,address -g")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FUZZER_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FUZZER_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FUZZER_FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FUZZER_FLAGS}")
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(extensions)
|
||||
if(CMARK_TESTS AND (CMARK_SHARED OR CMARK_STATIC))
|
||||
add_subdirectory(api_test)
|
||||
endif()
|
||||
add_subdirectory(man)
|
||||
if(CMARK_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(test testdir)
|
||||
endif()
|
||||
if(CMARK_FUZZ_QUADRATIC)
|
||||
add_subdirectory(fuzz)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
|
||||
"Choose the type of build, options are: Debug Profile Release Asan Ubsan." FORCE)
|
||||
endif(NOT CMAKE_BUILD_TYPE)
|
||||
170
3rdparty/cmark-gfm/COPYING
vendored
Normal file
170
3rdparty/cmark-gfm/COPYING
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
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
|
||||
(<http://www.public-software-group.org/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:
|
||||
<http://creativecommons.org/licenses/by-sa/4.0/>.
|
||||
|
||||
-----
|
||||
|
||||
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.
|
||||
14
3rdparty/cmark-gfm/CheckFileOffsetBits.c
vendored
Normal file
14
3rdparty/cmark-gfm/CheckFileOffsetBits.c
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#define KB ((off_t)1024)
|
||||
#define MB ((off_t)1024 * KB)
|
||||
#define GB ((off_t)1024 * MB)
|
||||
#define TB ((off_t)1024 * GB)
|
||||
int t2[(((64 * GB -1) % 671088649) == 268434537)
|
||||
&& (((TB - (64 * GB -1) + 255) % 1792151290) == 305159546)? 1: -1];
|
||||
|
||||
int main()
|
||||
{
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
43
3rdparty/cmark-gfm/CheckFileOffsetBits.cmake
vendored
Normal file
43
3rdparty/cmark-gfm/CheckFileOffsetBits.cmake
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
# - Check if _FILE_OFFSET_BITS macro needed for large files
|
||||
# CHECK_FILE_OFFSET_BITS ()
|
||||
#
|
||||
# The following variables may be set before calling this macro to
|
||||
# modify the way the check is run:
|
||||
#
|
||||
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
|
||||
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
|
||||
# CMAKE_REQUIRED_INCLUDES = list of include directories
|
||||
# Copyright (c) 2009, Michihiro NAKAJIMA
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
#INCLUDE(CheckCSourceCompiles)
|
||||
|
||||
GET_FILENAME_COMPONENT(_selfdir_CheckFileOffsetBits
|
||||
"${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
|
||||
MACRO (CHECK_FILE_OFFSET_BITS)
|
||||
IF(NOT DEFINED _FILE_OFFSET_BITS)
|
||||
MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files")
|
||||
TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${_selfdir_CheckFileOffsetBits}/CheckFileOffsetBits.c
|
||||
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
|
||||
IF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
|
||||
TRY_COMPILE(__WITH_FILE_OFFSET_BITS_64
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${_selfdir_CheckFileOffsetBits}/CheckFileOffsetBits.c
|
||||
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=64)
|
||||
ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
|
||||
|
||||
IF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
|
||||
SET(_FILE_OFFSET_BITS 64 CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
|
||||
MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - needed")
|
||||
ELSE(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
|
||||
SET(_FILE_OFFSET_BITS "" CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
|
||||
MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - not needed")
|
||||
ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
|
||||
ENDIF(NOT DEFINED _FILE_OFFSET_BITS)
|
||||
|
||||
ENDMACRO (CHECK_FILE_OFFSET_BITS)
|
||||
74
3rdparty/cmark-gfm/FindAsan.cmake
vendored
Normal file
74
3rdparty/cmark-gfm/FindAsan.cmake
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
#
|
||||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2013 Matthew Arsenault
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# This module tests if address sanitizer is supported by the compiler,
|
||||
# and creates a ASan build type (i.e. set CMAKE_BUILD_TYPE=ASan to use
|
||||
# it). This sets the following variables:
|
||||
#
|
||||
# CMAKE_C_FLAGS_ASAN - Flags to use for C with asan
|
||||
# CMAKE_CXX_FLAGS_ASAN - Flags to use for C++ with asan
|
||||
# HAVE_ADDRESS_SANITIZER - True or false if the ASan build type is available
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
|
||||
# Set -Werror to catch "argument unused during compilation" warnings
|
||||
set(CMAKE_REQUIRED_FLAGS "-Werror -faddress-sanitizer") # Also needs to be a link flag for test to pass
|
||||
check_c_compiler_flag("-faddress-sanitizer" HAVE_FLAG_ADDRESS_SANITIZER)
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS "-Werror -fsanitize=address") # Also needs to be a link flag for test to pass
|
||||
check_c_compiler_flag("-fsanitize=address" HAVE_FLAG_SANITIZE_ADDRESS)
|
||||
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
if(HAVE_FLAG_SANITIZE_ADDRESS)
|
||||
# Clang 3.2+ use this version
|
||||
set(ADDRESS_SANITIZER_FLAG "-fsanitize=address")
|
||||
elseif(HAVE_FLAG_ADDRESS_SANITIZER)
|
||||
# Older deprecated flag for ASan
|
||||
set(ADDRESS_SANITIZER_FLAG "-faddress-sanitizer")
|
||||
endif()
|
||||
|
||||
if(NOT ADDRESS_SANITIZER_FLAG)
|
||||
return()
|
||||
else(NOT ADDRESS_SANITIZER_FLAG)
|
||||
set(HAVE_ADDRESS_SANITIZER FALSE)
|
||||
endif()
|
||||
|
||||
set(HAVE_ADDRESS_SANITIZER TRUE)
|
||||
|
||||
set(CMAKE_C_FLAGS_ASAN "-O1 -g ${ADDRESS_SANITIZER_FLAG} -fno-omit-frame-pointer -fno-optimize-sibling-calls"
|
||||
CACHE STRING "Flags used by the C compiler during ASan builds."
|
||||
FORCE)
|
||||
set(CMAKE_CXX_FLAGS_ASAN "-O1 -g ${ADDRESS_SANITIZER_FLAG} -fno-omit-frame-pointer -fno-optimize-sibling-calls"
|
||||
CACHE STRING "Flags used by the C++ compiler during ASan builds."
|
||||
FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_ASAN "${ADDRESS_SANITIZER_FLAG}"
|
||||
CACHE STRING "Flags used for linking binaries during ASan builds."
|
||||
FORCE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_ASAN "${ADDRESS_SANITIZER_FLAG}"
|
||||
CACHE STRING "Flags used by the shared libraries linker during ASan builds."
|
||||
FORCE)
|
||||
mark_as_advanced(CMAKE_C_FLAGS_ASAN
|
||||
CMAKE_CXX_FLAGS_ASAN
|
||||
CMAKE_EXE_LINKER_FLAGS_ASAN
|
||||
CMAKE_SHARED_LINKER_FLAGS_ASAN)
|
||||
226
3rdparty/cmark-gfm/Makefile
vendored
Normal file
226
3rdparty/cmark-gfm/Makefile
vendored
Normal file
@ -0,0 +1,226 @@
|
||||
SRCDIR=src
|
||||
EXTDIR=extensions
|
||||
DATADIR=data
|
||||
BUILDDIR?=build
|
||||
GENERATOR?=Unix Makefiles
|
||||
MINGW_BUILDDIR?=build-mingw
|
||||
MINGW_INSTALLDIR?=windows
|
||||
SPEC=test/spec.txt
|
||||
EXTENSIONS_SPEC=test/extensions.txt
|
||||
SITE=_site
|
||||
SPECVERSION=$(shell perl -ne 'print $$1 if /^version: *([0-9.]+)/' $(SPEC))
|
||||
FUZZCHARS?=2000000 # for fuzztest
|
||||
BENCHDIR=bench
|
||||
BENCHSAMPLES=$(wildcard $(BENCHDIR)/samples/*.md)
|
||||
BENCHFILE=$(BENCHDIR)/benchinput.md
|
||||
ALLTESTS=alltests.md
|
||||
NUMRUNS?=20
|
||||
CMARK=$(BUILDDIR)/src/cmark-gfm
|
||||
CMARK_FUZZ=$(BUILDDIR)/src/cmark-fuzz
|
||||
PROG?=$(CMARK)
|
||||
VERSION?=$(SPECVERSION)
|
||||
RELEASE?=CommonMark-$(VERSION)
|
||||
INSTALL_PREFIX?=/usr/local
|
||||
CLANG_CHECK?=clang-check
|
||||
CLANG_FORMAT=clang-format -style llvm -sort-includes=0 -i
|
||||
AFL_PATH?=/usr/local/bin
|
||||
|
||||
.PHONY: all cmake_build leakcheck clean fuzztest test debug ubsan asan mingw archive newbench bench format update-spec afl clang-check docker libFuzzer
|
||||
|
||||
all: cmake_build man/man3/cmark-gfm.3
|
||||
|
||||
$(CMARK): cmake_build
|
||||
|
||||
cmake_build: $(BUILDDIR)
|
||||
@$(MAKE) -j2 -C $(BUILDDIR)
|
||||
@echo "Binaries can be found in $(BUILDDIR)/src"
|
||||
|
||||
$(BUILDDIR):
|
||||
@cmake --version > /dev/null || (echo "You need cmake to build this program: http://www.cmake.org/download/" && exit 1)
|
||||
mkdir -p $(BUILDDIR); \
|
||||
cd $(BUILDDIR); \
|
||||
cmake .. \
|
||||
-G "$(GENERATOR)" \
|
||||
-DCMAKE_BUILD_TYPE=$(BUILD_TYPE) \
|
||||
-DCMAKE_INSTALL_PREFIX=$(INSTALL_PREFIX) \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
|
||||
install: $(BUILDDIR)
|
||||
$(MAKE) -C $(BUILDDIR) install
|
||||
|
||||
debug:
|
||||
mkdir -p $(BUILDDIR); \
|
||||
cd $(BUILDDIR); \
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug; \
|
||||
$(MAKE)
|
||||
|
||||
ubsan:
|
||||
mkdir -p $(BUILDDIR); \
|
||||
cd $(BUILDDIR); \
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Ubsan; \
|
||||
$(MAKE)
|
||||
|
||||
asan:
|
||||
mkdir -p $(BUILDDIR); \
|
||||
cd $(BUILDDIR); \
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Asan; \
|
||||
$(MAKE)
|
||||
|
||||
prof:
|
||||
mkdir -p $(BUILDDIR); \
|
||||
cd $(BUILDDIR); \
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Profile; \
|
||||
$(MAKE)
|
||||
|
||||
afl:
|
||||
@[ -n "$(AFL_PATH)" ] || { echo '$$AFL_PATH not set'; false; }
|
||||
mkdir -p $(BUILDDIR)
|
||||
cd $(BUILDDIR) && cmake .. -DCMARK_TESTS=0 -DCMAKE_C_COMPILER=$(AFL_PATH)/afl-clang
|
||||
$(MAKE)
|
||||
$(AFL_PATH)/afl-fuzz \
|
||||
-i test/afl_test_cases \
|
||||
-o test/afl_results \
|
||||
-x test/fuzzing_dictionary \
|
||||
$(AFL_OPTIONS) \
|
||||
-t 100 \
|
||||
$(CMARK) -e table -e strikethrough -e autolink -e tagfilter $(CMARK_OPTS)
|
||||
|
||||
libFuzzer:
|
||||
@[ -n "$(LIB_FUZZER_PATH)" ] || { echo '$$LIB_FUZZER_PATH not set'; false; }
|
||||
mkdir -p $(BUILDDIR)
|
||||
cd $(BUILDDIR) && cmake -DCMAKE_BUILD_TYPE=Asan -DCMARK_LIB_FUZZER=ON -DCMAKE_LIB_FUZZER_PATH=$(LIB_FUZZER_PATH) ..
|
||||
$(MAKE) -j2 -C $(BUILDDIR) cmark-fuzz
|
||||
test/run-cmark-fuzz $(CMARK_FUZZ)
|
||||
|
||||
clang-check: all
|
||||
${CLANG_CHECK} -p build -analyze src/*.c
|
||||
|
||||
mingw:
|
||||
mkdir -p $(MINGW_BUILDDIR); \
|
||||
cd $(MINGW_BUILDDIR); \
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=../toolchain-mingw32.cmake -DCMAKE_INSTALL_PREFIX=$(MINGW_INSTALLDIR) ;\
|
||||
$(MAKE) && $(MAKE) install
|
||||
|
||||
man/man3/cmark-gfm.3: src/cmark-gfm.h | $(CMARK)
|
||||
python man/make_man_page.py $< > $@ \
|
||||
|
||||
archive:
|
||||
git archive --prefix=$(RELEASE)/ -o $(RELEASE).tar.gz HEAD
|
||||
git archive --prefix=$(RELEASE)/ -o $(RELEASE).zip HEAD
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR) $(MINGW_BUILDDIR) $(MINGW_INSTALLDIR)
|
||||
|
||||
# We include case_fold_switch.inc in the repository, so this shouldn't
|
||||
# normally need to be generated.
|
||||
$(SRCDIR)/case_fold_switch.inc: $(DATADIR)/CaseFolding.txt
|
||||
perl tools/mkcasefold.pl < $< > $@
|
||||
|
||||
# We include scanners.c in the repository, so this shouldn't
|
||||
# normally need to be generated.
|
||||
$(SRCDIR)/scanners.c: $(SRCDIR)/scanners.re
|
||||
@case "$$(re2c -v)" in \
|
||||
*\ 0.13.*|*\ 0.14|*\ 0.14.1) \
|
||||
echo "re2c >= 0.14.2 is required"; \
|
||||
false; \
|
||||
;; \
|
||||
esac
|
||||
re2c -W -Werror --case-insensitive -b -i --no-generation-date -8 \
|
||||
--encoding-policy substitute -o $@ $<
|
||||
$(CLANG_FORMAT) $@
|
||||
|
||||
# We include scanners.c in the repository, so this shouldn't
|
||||
# normally need to be generated.
|
||||
$(EXTDIR)/ext_scanners.c: $(EXTDIR)/ext_scanners.re
|
||||
@case "$$(re2c -v)" in \
|
||||
*\ 0.13.*|*\ 0.14|*\ 0.14.1) \
|
||||
echo "re2c >= 0.14.2 is required"; \
|
||||
false; \
|
||||
;; \
|
||||
esac
|
||||
re2c --case-insensitive -b -i --no-generation-date -8 \
|
||||
--encoding-policy substitute -o $@ $<
|
||||
clang-format -style llvm -i $@
|
||||
|
||||
# We include entities.inc in the repository, so normally this
|
||||
# doesn't need to be regenerated:
|
||||
$(SRCDIR)/entities.inc: tools/make_entities_inc.py
|
||||
python3 $< > $@
|
||||
|
||||
update-spec:
|
||||
curl 'https://raw.githubusercontent.com/jgm/CommonMark/master/spec.txt'\
|
||||
> $(SPEC)
|
||||
|
||||
test: $(SPEC) cmake_build
|
||||
$(MAKE) -C $(BUILDDIR) test || (cat $(BUILDDIR)/Testing/Temporary/LastTest.log && exit 1)
|
||||
|
||||
$(ALLTESTS): $(SPEC) $(EXTENSIONS_SPEC)
|
||||
( \
|
||||
python3 test/spec_tests.py --spec $(SPEC) --dump-tests | \
|
||||
python3 -c 'import json; import sys; tests = json.loads(sys.stdin.read()); u8s = open(1, "w", encoding="utf-8", closefd=False); print("\n".join([test["markdown"] for test in tests]), file=u8s)'; \
|
||||
python3 test/spec_tests.py --spec $(EXTENSIONS_SPEC) --dump-tests | \
|
||||
python3 -c 'import json; import sys; tests = json.loads(sys.stdin.read()); u8s = open(1, "w", encoding="utf-8", closefd=False); print("\n".join([test["markdown"] for test in tests]), file=u8s)'; \
|
||||
) > $@
|
||||
|
||||
leakcheck: $(ALLTESTS)
|
||||
for format in html man xml latex commonmark; do \
|
||||
for opts in "" "--smart"; do \
|
||||
echo "cmark-gfm -t $$format -e table -e strikethrough -e autolink -e tagfilter $$opts" ; \
|
||||
valgrind -q --leak-check=full --dsymutil=yes --suppressions=suppressions --error-exitcode=1 $(PROG) -t $$format -e table -e strikethrough -e autolink -e tagfilter $$opts $(ALLTESTS) >/dev/null || exit 1;\
|
||||
done; \
|
||||
done;
|
||||
|
||||
fuzztest:
|
||||
{ for i in `seq 1 10`; do \
|
||||
cat /dev/urandom | head -c $(FUZZCHARS) | iconv -f latin1 -t utf-8 | tee fuzz-$$i.txt | \
|
||||
/usr/bin/env time -p $(PROG) >/dev/null && rm fuzz-$$i.txt ; \
|
||||
done } 2>&1 | grep 'user\|abnormally'
|
||||
|
||||
progit:
|
||||
git clone https://github.com/progit/progit.git
|
||||
|
||||
$(BENCHFILE): progit
|
||||
echo "" > $@
|
||||
for lang in ar az be ca cs de en eo es es-ni fa fi fr hi hu id it ja ko mk nl no-nb pl pt-br ro ru sr th tr uk vi zh zh-tw; do \
|
||||
for i in `seq 1 10`; do \
|
||||
cat progit/$$lang/*/*.markdown >> $@; \
|
||||
done; \
|
||||
done
|
||||
|
||||
# for more accurate results, run with
|
||||
# sudo renice -10 $$; make bench
|
||||
bench: $(BENCHFILE)
|
||||
{ for x in `seq 1 $(NUMRUNS)` ; do \
|
||||
/usr/bin/env time -p $(PROG) </dev/null >/dev/null ; \
|
||||
/usr/bin/env time -p $(PROG) $< >/dev/null ; \
|
||||
done \
|
||||
} 2>&1 | grep 'real' | awk '{print $$2}' | python3 'bench/stats.py'
|
||||
|
||||
newbench:
|
||||
for f in $(BENCHSAMPLES) ; do \
|
||||
printf "%26s " `basename $$f` ; \
|
||||
{ for x in `seq 1 $(NUMRUNS)` ; do \
|
||||
/usr/bin/env time -p $(PROG) </dev/null >/dev/null ; \
|
||||
for x in `seq 1 200` ; do cat $$f ; done | \
|
||||
/usr/bin/env time -p $(PROG) > /dev/null; \
|
||||
done \
|
||||
} 2>&1 | grep 'real' | awk '{print $$2}' | \
|
||||
python3 'bench/stats.py'; done
|
||||
|
||||
format:
|
||||
$(CLANG_FORMAT) src/*.c src/*.h api_test/*.c api_test/*.h
|
||||
|
||||
format-extensions:
|
||||
clang-format -style llvm -i extensions/*.c extensions/*.h
|
||||
|
||||
operf: $(CMARK)
|
||||
operf $< < $(BENCHFILE) > /dev/null
|
||||
|
||||
distclean: clean
|
||||
-rm -rf *.dSYM
|
||||
-rm -f README.html
|
||||
-rm -rf $(BENCHFILE) $(ALLTESTS) progit
|
||||
|
||||
docker:
|
||||
docker build -t cmark-gfm $(CURDIR)/tools
|
||||
docker run --privileged -t -i -v $(CURDIR):/src/cmark-gfm -w /src/cmark-gfm cmark-gfm /bin/bash
|
||||
38
3rdparty/cmark-gfm/Makefile.nmake
vendored
Normal file
38
3rdparty/cmark-gfm/Makefile.nmake
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
SRCDIR=src
|
||||
DATADIR=data
|
||||
BUILDDIR=build
|
||||
INSTALLDIR=windows
|
||||
SPEC=test/spec.txt
|
||||
PROG=$(BUILDDIR)\src\cmark-gfm.exe
|
||||
GENERATOR=NMake Makefiles
|
||||
|
||||
all: $(BUILDDIR)/CMakeFiles
|
||||
@cd $(BUILDDIR) && $(MAKE) /nologo && cd ..
|
||||
|
||||
$(BUILDDIR)/CMakeFiles:
|
||||
@-mkdir $(BUILDDIR) 2> nul
|
||||
cd $(BUILDDIR) && \
|
||||
cmake \
|
||||
-G "$(GENERATOR)" \
|
||||
-D CMAKE_BUILD_TYPE=$(BUILD_TYPE) \
|
||||
-D CMAKE_INSTALL_PREFIX=$(INSTALLDIR) \
|
||||
-D CMARK_STATIC=ON \
|
||||
-D CMARK_SHARED=OFF \
|
||||
.. && \
|
||||
cd ..
|
||||
|
||||
install: all
|
||||
@cd $(BUILDDIR) && $(MAKE) /nologo install && cd ..
|
||||
|
||||
clean:
|
||||
-rmdir /s /q $(BUILDDIR) $(MINGW_INSTALLDIR) 2> nul
|
||||
|
||||
$(SRCDIR)\case_fold_switch.inc: $(DATADIR)\CaseFolding-3.2.0.txt
|
||||
perl mkcasefold.pl < $? > $@
|
||||
|
||||
test: $(SPEC) all
|
||||
@cd $(BUILDDIR) && $(MAKE) /nologo test ARGS="-V" && cd ..
|
||||
|
||||
distclean: clean
|
||||
del /q src\scanners.c 2> nul
|
||||
del /q spec.md spec.html 2> nul
|
||||
206
3rdparty/cmark-gfm/README.md
vendored
Normal file
206
3rdparty/cmark-gfm/README.md
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
cmark-gfm
|
||||
=========
|
||||
|
||||

|
||||
|
||||
`cmark-gfm` is an extended version of the C reference implementation of
|
||||
[CommonMark], a rationalized version of Markdown syntax with a spec. This
|
||||
repository adds GitHub Flavored Markdown extensions to
|
||||
[the upstream implementation], as defined in [the spec].
|
||||
|
||||
The rest of the README is preserved as-is from the upstream source. Note that
|
||||
the library and binaries produced by this fork are suffixed with `-gfm` in
|
||||
order to distinguish them from the upstream.
|
||||
|
||||
---
|
||||
|
||||
It provides a shared library (`libcmark`) with functions for parsing
|
||||
CommonMark documents to an abstract syntax tree (AST), manipulating
|
||||
the AST, and rendering the document to HTML, groff man, LaTeX,
|
||||
CommonMark, or an XML representation of the AST. It also provides a
|
||||
command-line program (`cmark`) for parsing and rendering CommonMark
|
||||
documents.
|
||||
|
||||
Advantages of this library:
|
||||
|
||||
- **Portable.** The library and program are written in standard
|
||||
C99 and have no external dependencies. They have been tested with
|
||||
MSVC, gcc, tcc, and clang.
|
||||
|
||||
- **Fast.** cmark can render a Markdown version of *War and Peace* in
|
||||
the blink of an eye (127 milliseconds on a ten year old laptop,
|
||||
vs. 100-400 milliseconds for an eye blink). In our [benchmarks],
|
||||
cmark is 10,000 times faster than the original `Markdown.pl`, and
|
||||
on par with the very fastest available Markdown processors.
|
||||
|
||||
- **Accurate.** The library passes all CommonMark conformance tests.
|
||||
|
||||
- **Standardized.** The library can be expected to parse CommonMark
|
||||
the same way as any other conforming parser. So, for example,
|
||||
you can use `commonmark.js` on the client to preview content that
|
||||
will be rendered on the server using `cmark`.
|
||||
|
||||
- **Robust.** The library has been extensively fuzz-tested using
|
||||
[american fuzzy lop]. The test suite includes pathological cases
|
||||
that bring many other Markdown parsers to a crawl (for example,
|
||||
thousands-deep nested bracketed text or block quotes).
|
||||
|
||||
- **Flexible.** CommonMark input is parsed to an AST which can be
|
||||
manipulated programmatically prior to rendering.
|
||||
|
||||
- **Multiple renderers.** Output in HTML, groff man, LaTeX, CommonMark,
|
||||
and a custom XML format is supported. And it is easy to write new
|
||||
renderers to support other formats.
|
||||
|
||||
- **Free.** BSD2-licensed.
|
||||
|
||||
It is easy to use `libcmark` in python, lua, ruby, and other dynamic
|
||||
languages: see the `wrappers/` subdirectory for some simple examples.
|
||||
|
||||
There are also libraries that wrap `libcmark` for
|
||||
[Go](https://github.com/rhinoman/go-commonmark),
|
||||
[Haskell](https://hackage.haskell.org/package/cmark),
|
||||
[Ruby](https://github.com/gjtorikian/commonmarker),
|
||||
[Lua](https://github.com/jgm/cmark-lua),
|
||||
[Perl](https://metacpan.org/release/CommonMark),
|
||||
[Python](https://pypi.python.org/pypi/paka.cmark),
|
||||
[R](https://cran.r-project.org/package=commonmark),
|
||||
[Tcl](https://github.com/apnadkarni/tcl-cmark),
|
||||
[Scala](https://github.com/sparsetech/cmark-scala) and
|
||||
[Node.js](https://github.com/killa123/node-cmark).
|
||||
|
||||
Installing
|
||||
----------
|
||||
|
||||
Building the C program (`cmark`) and shared library (`libcmark`)
|
||||
requires [cmake]. If you modify `scanners.re`, then you will also
|
||||
need [re2c] \(>= 0.14.2\), which is used to generate `scanners.c` from
|
||||
`scanners.re`. We have included a pre-generated `scanners.c` in
|
||||
the repository to reduce build dependencies.
|
||||
|
||||
If you have GNU make, you can simply `make`, `make test`, and `make
|
||||
install`. This calls [cmake] to create a `Makefile` in the `build`
|
||||
directory, then uses that `Makefile` to create the executable and
|
||||
library. The binaries can be found in `build/src`. The default
|
||||
installation prefix is `/usr/local`. To change the installation
|
||||
prefix, pass the `INSTALL_PREFIX` variable if you run `make` for the
|
||||
first time: `make INSTALL_PREFIX=path`.
|
||||
|
||||
For a more portable method, you can use [cmake] manually. [cmake] knows
|
||||
how to create build environments for many build systems. For example,
|
||||
on FreeBSD:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. # optionally: -DCMAKE_INSTALL_PREFIX=path
|
||||
make # executable will be created as build/src/cmark
|
||||
make test
|
||||
make install
|
||||
|
||||
Or, to create Xcode project files on OSX:
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Xcode ..
|
||||
open cmark.xcodeproj
|
||||
|
||||
The GNU Makefile also provides a few other targets for developers.
|
||||
To run a benchmark:
|
||||
|
||||
make bench
|
||||
|
||||
For more detailed benchmarks:
|
||||
|
||||
make newbench
|
||||
|
||||
To run a test for memory leaks using `valgrind`:
|
||||
|
||||
make leakcheck
|
||||
|
||||
To reformat source code using `clang-format`:
|
||||
|
||||
make format
|
||||
|
||||
To run a "fuzz test" against ten long randomly generated inputs:
|
||||
|
||||
make fuzztest
|
||||
|
||||
To do a more systematic fuzz test with [american fuzzy lop]:
|
||||
|
||||
AFL_PATH=/path/to/afl_directory make afl
|
||||
|
||||
Fuzzing with [libFuzzer] is also supported but, because libFuzzer is still
|
||||
under active development, may not work with your system-installed version of
|
||||
clang. Assuming LLVM has been built in `$HOME/src/llvm/build` the fuzzer can be
|
||||
run with:
|
||||
|
||||
CC="$HOME/src/llvm/build/bin/clang" LIB_FUZZER_PATH="$HOME/src/llvm/lib/Fuzzer/libFuzzer.a" make libFuzzer
|
||||
|
||||
To make a release tarball and zip archive:
|
||||
|
||||
make archive
|
||||
|
||||
Installing (Windows)
|
||||
--------------------
|
||||
|
||||
To compile with MSVC and NMAKE:
|
||||
|
||||
nmake
|
||||
|
||||
You can cross-compile a Windows binary and dll on linux if you have the
|
||||
`mingw32` compiler:
|
||||
|
||||
make mingw
|
||||
|
||||
The binaries will be in `build-mingw/windows/bin`.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Instructions for the use of the command line program and library can
|
||||
be found in the man pages in the `man` subdirectory.
|
||||
|
||||
Security
|
||||
--------
|
||||
|
||||
By default, the library will scrub raw HTML and potentially
|
||||
dangerous links (`javascript:`, `vbscript:`, `data:`, `file:`).
|
||||
|
||||
To allow these, use the option `CMARK_OPT_UNSAFE` (or
|
||||
`--unsafe`) with the command line program. If doing so, we
|
||||
recommend you use a HTML sanitizer specific to your needs to
|
||||
protect against [XSS
|
||||
attacks](http://en.wikipedia.org/wiki/Cross-site_scripting).
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
There is a [forum for discussing
|
||||
CommonMark](http://talk.commonmark.org); you should use it instead of
|
||||
github issues for questions and possibly open-ended discussions.
|
||||
Use the [github issue tracker](http://github.com/commonmark/CommonMark/issues)
|
||||
only for simple, clear, actionable issues.
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
John MacFarlane wrote the original library and program.
|
||||
The block parsing algorithm was worked out together with David
|
||||
Greenspan. Vicent Marti optimized the C implementation for
|
||||
performance, increasing its speed tenfold. Kārlis Gaņģis helped
|
||||
work out a better parsing algorithm for links and emphasis,
|
||||
eliminating several worst-case performance issues.
|
||||
Nick Wellnhofer contributed many improvements, including
|
||||
most of the C library's API and its test harness.
|
||||
|
||||
[benchmarks]: benchmarks.md
|
||||
[the spec]: https://github.github.com/gfm/
|
||||
[the upstream implementation]: https://github.com/jgm/cmark
|
||||
[CommonMark]: http://commonmark.org
|
||||
[cmake]: http://www.cmake.org/download/
|
||||
[re2c]: http://re2c.org
|
||||
[commonmark.js]: https://github.com/commonmark/commonmark.js
|
||||
[Build Status]: https://img.shields.io/travis/github/cmark-gfm/master.svg?style=flat
|
||||
[Windows Build Status]: https://ci.appveyor.com/api/projects/status/wv7ifhqhv5itm3d5?svg=true
|
||||
[american fuzzy lop]: http://lcamtuf.coredump.cx/afl/
|
||||
[libFuzzer]: http://llvm.org/docs/LibFuzzer.html
|
||||
30
3rdparty/cmark-gfm/api_test/CMakeLists.txt
vendored
Normal file
30
3rdparty/cmark-gfm/api_test/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
add_executable(api_test
|
||||
cplusplus.cpp
|
||||
harness.c
|
||||
harness.h
|
||||
main.c
|
||||
)
|
||||
include_directories(
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_BINARY_DIR}/src
|
||||
${PROJECT_BINARY_DIR}/extensions
|
||||
)
|
||||
if(CMARK_SHARED)
|
||||
target_link_libraries(api_test libcmark-gfm-extensions libcmark-gfm)
|
||||
else()
|
||||
target_link_libraries(api_test libcmark-gfm-extensions_static libcmark-gfm_static)
|
||||
endif()
|
||||
|
||||
# Compiler flags
|
||||
if(MSVC)
|
||||
# Force to always compile with W4
|
||||
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4706 /D_CRT_SECURE_NO_WARNINGS")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /TP")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -std=c99 -pedantic")
|
||||
endif()
|
||||
15
3rdparty/cmark-gfm/api_test/cplusplus.cpp
vendored
Normal file
15
3rdparty/cmark-gfm/api_test/cplusplus.cpp
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
#include <cstdlib>
|
||||
|
||||
#include "cmark-gfm.h"
|
||||
#include "cplusplus.h"
|
||||
#include "harness.h"
|
||||
|
||||
void
|
||||
test_cplusplus(test_batch_runner *runner)
|
||||
{
|
||||
static const char md[] = "paragraph\n";
|
||||
char *html = cmark_markdown_to_html(md, sizeof(md) - 1, CMARK_OPT_DEFAULT);
|
||||
STR_EQ(runner, html, "<p>paragraph</p>\n", "libcmark works with C++");
|
||||
free(html);
|
||||
}
|
||||
|
||||
16
3rdparty/cmark-gfm/api_test/cplusplus.h
vendored
Normal file
16
3rdparty/cmark-gfm/api_test/cplusplus.h
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef CMARK_API_TEST_CPLUSPLUS_H
|
||||
#define CMARK_API_TEST_CPLUSPLUS_H
|
||||
|
||||
#include "harness.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void test_cplusplus(test_batch_runner *runner);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
111
3rdparty/cmark-gfm/api_test/harness.c
vendored
Normal file
111
3rdparty/cmark-gfm/api_test/harness.c
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
#define _DEFAULT_SOURCE
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "harness.h"
|
||||
|
||||
test_batch_runner *test_batch_runner_new() {
|
||||
return (test_batch_runner *)calloc(1, sizeof(test_batch_runner));
|
||||
}
|
||||
|
||||
static void test_result(test_batch_runner *runner, int cond, const char *msg,
|
||||
va_list ap) {
|
||||
++runner->test_num;
|
||||
|
||||
if (cond) {
|
||||
++runner->num_passed;
|
||||
} else {
|
||||
fprintf(stderr, "FAILED test %d: ", runner->test_num);
|
||||
vfprintf(stderr, msg, ap);
|
||||
fprintf(stderr, "\n");
|
||||
++runner->num_failed;
|
||||
}
|
||||
}
|
||||
|
||||
void SKIP(test_batch_runner *runner, int num_tests) {
|
||||
runner->test_num += num_tests;
|
||||
runner->num_skipped += num_tests;
|
||||
}
|
||||
|
||||
void OK(test_batch_runner *runner, int cond, const char *msg, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
test_result(runner, cond, msg, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void INT_EQ(test_batch_runner *runner, int got, int expected, const char *msg,
|
||||
...) {
|
||||
int cond = got == expected;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
test_result(runner, cond, msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (!cond) {
|
||||
fprintf(stderr, " Got: %d\n", got);
|
||||
fprintf(stderr, " Expected: %d\n", expected);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
|
||||
static char *write_tmp(char const *header, char const *data) {
|
||||
char *name = strdup("/tmp/fileXXXXXX");
|
||||
int fd = mkstemp(name);
|
||||
FILE *f = fdopen(fd, "w+");
|
||||
fputs(header, f);
|
||||
fwrite(data, 1, strlen(data), f);
|
||||
fclose(f);
|
||||
return name;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void STR_EQ(test_batch_runner *runner, const char *got, const char *expected,
|
||||
const char *msg, ...) {
|
||||
int cond = strcmp(got, expected) == 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
test_result(runner, cond, msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (!cond) {
|
||||
#ifndef _WIN32
|
||||
char *got_fn = write_tmp("actual\n", got);
|
||||
char *expected_fn = write_tmp("expected\n", expected);
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "git diff --no-index %s %s", expected_fn, got_fn);
|
||||
system(buf);
|
||||
remove(got_fn);
|
||||
remove(expected_fn);
|
||||
free(got_fn);
|
||||
free(expected_fn);
|
||||
#else
|
||||
fprintf(stderr, " Got: \"%s\"\n", got);
|
||||
fprintf(stderr, " Expected: \"%s\"\n", expected);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int test_ok(test_batch_runner *runner) { return runner->num_failed == 0; }
|
||||
|
||||
void test_print_summary(test_batch_runner *runner) {
|
||||
int num_passed = runner->num_passed;
|
||||
int num_skipped = runner->num_skipped;
|
||||
int num_failed = runner->num_failed;
|
||||
|
||||
fprintf(stderr, "%d tests passed, %d failed, %d skipped\n", num_passed,
|
||||
num_failed, num_skipped);
|
||||
|
||||
if (test_ok(runner)) {
|
||||
fprintf(stderr, "PASS\n");
|
||||
} else {
|
||||
fprintf(stderr, "FAIL\n");
|
||||
}
|
||||
}
|
||||
35
3rdparty/cmark-gfm/api_test/harness.h
vendored
Normal file
35
3rdparty/cmark-gfm/api_test/harness.h
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef CMARK_API_TEST_HARNESS_H
|
||||
#define CMARK_API_TEST_HARNESS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int test_num;
|
||||
int num_passed;
|
||||
int num_failed;
|
||||
int num_skipped;
|
||||
} test_batch_runner;
|
||||
|
||||
test_batch_runner *test_batch_runner_new();
|
||||
|
||||
void SKIP(test_batch_runner *runner, int num_tests);
|
||||
|
||||
void OK(test_batch_runner *runner, int cond, const char *msg, ...);
|
||||
|
||||
void INT_EQ(test_batch_runner *runner, int got, int expected, const char *msg,
|
||||
...);
|
||||
|
||||
void STR_EQ(test_batch_runner *runner, const char *got, const char *expected,
|
||||
const char *msg, ...);
|
||||
|
||||
int test_ok(test_batch_runner *runner);
|
||||
|
||||
void test_print_summary(test_batch_runner *runner);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1169
3rdparty/cmark-gfm/api_test/main.c
vendored
Normal file
1169
3rdparty/cmark-gfm/api_test/main.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
21
3rdparty/cmark-gfm/appveyor.yml
vendored
Normal file
21
3rdparty/cmark-gfm/appveyor.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
environment:
|
||||
PYTHON: "C:\\Python34-x64"
|
||||
PYTHON_VERSION: "3.4.3"
|
||||
PYTHON_ARCH: "64"
|
||||
matrix:
|
||||
- MSVC_VERSION: 10
|
||||
- MSVC_VERSION: 12
|
||||
|
||||
# set up for nmake:
|
||||
install:
|
||||
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
|
||||
|
||||
build_script:
|
||||
- 'tools\appveyor-build.bat'
|
||||
|
||||
artifacts:
|
||||
- path: build/src/cmark-gfm.exe
|
||||
name: cmark-gfm.exe
|
||||
|
||||
test_script:
|
||||
- 'nmake test'
|
||||
16
3rdparty/cmark-gfm/bench/samples/block-bq-flat.md
vendored
Normal file
16
3rdparty/cmark-gfm/bench/samples/block-bq-flat.md
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
> the simple example of a blockquote
|
||||
> the simple example of a blockquote
|
||||
> the simple example of a blockquote
|
||||
> the simple example of a blockquote
|
||||
... continuation
|
||||
... continuation
|
||||
... continuation
|
||||
... continuation
|
||||
|
||||
empty blockquote:
|
||||
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
|
||||
13
3rdparty/cmark-gfm/bench/samples/block-bq-nested.md
vendored
Normal file
13
3rdparty/cmark-gfm/bench/samples/block-bq-nested.md
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
>>>>>> deeply nested blockquote
|
||||
>>>>> deeply nested blockquote
|
||||
>>>> deeply nested blockquote
|
||||
>>> deeply nested blockquote
|
||||
>> deeply nested blockquote
|
||||
> deeply nested blockquote
|
||||
|
||||
> deeply nested blockquote
|
||||
>> deeply nested blockquote
|
||||
>>> deeply nested blockquote
|
||||
>>>> deeply nested blockquote
|
||||
>>>>> deeply nested blockquote
|
||||
>>>>>> deeply nested blockquote
|
||||
11
3rdparty/cmark-gfm/bench/samples/block-code.md
vendored
Normal file
11
3rdparty/cmark-gfm/bench/samples/block-code.md
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
an
|
||||
example
|
||||
|
||||
of
|
||||
|
||||
|
||||
|
||||
a code
|
||||
block
|
||||
|
||||
14
3rdparty/cmark-gfm/bench/samples/block-fences.md
vendored
Normal file
14
3rdparty/cmark-gfm/bench/samples/block-fences.md
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
``````````text
|
||||
an
|
||||
example
|
||||
```
|
||||
of
|
||||
|
||||
|
||||
a fenced
|
||||
```
|
||||
code
|
||||
block
|
||||
``````````
|
||||
|
||||
9
3rdparty/cmark-gfm/bench/samples/block-heading.md
vendored
Normal file
9
3rdparty/cmark-gfm/bench/samples/block-heading.md
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# heading
|
||||
### heading
|
||||
##### heading
|
||||
|
||||
# heading #
|
||||
### heading ###
|
||||
##### heading \#\#\#\#\######
|
||||
|
||||
############ not a heading
|
||||
10
3rdparty/cmark-gfm/bench/samples/block-hr.md
vendored
Normal file
10
3rdparty/cmark-gfm/bench/samples/block-hr.md
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
* * * * *
|
||||
|
||||
- - - - -
|
||||
|
||||
________
|
||||
|
||||
|
||||
************************* text
|
||||
|
||||
32
3rdparty/cmark-gfm/bench/samples/block-html.md
vendored
Normal file
32
3rdparty/cmark-gfm/bench/samples/block-html.md
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<div class="this is an html block">
|
||||
|
||||
blah blah
|
||||
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
**test**
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
|
||||
<td>
|
||||
|
||||
test
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<![CDATA[
|
||||
[[[[[[[[[[[... *cdata section - this should not be parsed* ...]]]]]]]]]]]
|
||||
]]>
|
||||
|
||||
8
3rdparty/cmark-gfm/bench/samples/block-lheading.md
vendored
Normal file
8
3rdparty/cmark-gfm/bench/samples/block-lheading.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
heading
|
||||
---
|
||||
|
||||
heading
|
||||
===================================
|
||||
|
||||
not a heading
|
||||
----------------------------------- text
|
||||
67
3rdparty/cmark-gfm/bench/samples/block-list-flat.md
vendored
Normal file
67
3rdparty/cmark-gfm/bench/samples/block-list-flat.md
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
- tidy
|
||||
- bullet
|
||||
- list
|
||||
|
||||
|
||||
- loose
|
||||
|
||||
- bullet
|
||||
|
||||
- list
|
||||
|
||||
|
||||
0. ordered
|
||||
1. list
|
||||
2. example
|
||||
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
|
||||
- an example
|
||||
of a list item
|
||||
with a continuation
|
||||
|
||||
this part is inside the list
|
||||
|
||||
this part is just a paragraph
|
||||
|
||||
|
||||
1. test
|
||||
- test
|
||||
1. test
|
||||
- test
|
||||
|
||||
|
||||
111111111111111111111111111111111111111111. is this a valid bullet?
|
||||
|
||||
- _________________________
|
||||
|
||||
- this
|
||||
- is
|
||||
|
||||
a
|
||||
|
||||
long
|
||||
- loose
|
||||
- list
|
||||
|
||||
- with
|
||||
- some
|
||||
|
||||
tidy
|
||||
|
||||
- list
|
||||
- items
|
||||
- in
|
||||
|
||||
- between
|
||||
- _________________________
|
||||
36
3rdparty/cmark-gfm/bench/samples/block-list-nested.md
vendored
Normal file
36
3rdparty/cmark-gfm/bench/samples/block-list-nested.md
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
- this
|
||||
- is
|
||||
- a
|
||||
- deeply
|
||||
- nested
|
||||
- bullet
|
||||
- list
|
||||
|
||||
|
||||
1. this
|
||||
2. is
|
||||
3. a
|
||||
4. deeply
|
||||
5. nested
|
||||
6. unordered
|
||||
7. list
|
||||
|
||||
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
- 6
|
||||
- 7
|
||||
- 6
|
||||
- 5
|
||||
- 4
|
||||
- 3
|
||||
- 2
|
||||
- 1
|
||||
|
||||
|
||||
- - - - - - - - - deeply-nested one-element item
|
||||
|
||||
15
3rdparty/cmark-gfm/bench/samples/block-ref-flat.md
vendored
Normal file
15
3rdparty/cmark-gfm/bench/samples/block-ref-flat.md
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
[1] [2] [3] [1] [2] [3]
|
||||
|
||||
[looooooooooooooooooooooooooooooooooooooooooooooooooong label]
|
||||
|
||||
[1]: <http://something.example.com/foo/bar>
|
||||
[2]: http://something.example.com/foo/bar 'test'
|
||||
[3]:
|
||||
http://foo/bar
|
||||
[ looooooooooooooooooooooooooooooooooooooooooooooooooong label ]:
|
||||
111
|
||||
'test'
|
||||
[[[[[[[[[[[[[[[[[[[[ this should not slow down anything ]]]]]]]]]]]]]]]]]]]]: q
|
||||
(as long as it is not referenced anywhere)
|
||||
|
||||
[[[[[[[[[[[[[[[[[[[[]: this is not a valid reference
|
||||
17
3rdparty/cmark-gfm/bench/samples/block-ref-nested.md
vendored
Normal file
17
3rdparty/cmark-gfm/bench/samples/block-ref-nested.md
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
[[[[[[[foo]]]]]]]
|
||||
|
||||
[[[[[[[foo]]]]]]]: bar
|
||||
[[[[[[foo]]]]]]: bar
|
||||
[[[[[foo]]]]]: bar
|
||||
[[[[foo]]]]: bar
|
||||
[[[foo]]]: bar
|
||||
[[foo]]: bar
|
||||
[foo]: bar
|
||||
|
||||
[*[*[*[*[foo]*]*]*]*]
|
||||
|
||||
[*[*[*[*[foo]*]*]*]*]: bar
|
||||
[*[*[*[foo]*]*]*]: bar
|
||||
[*[*[foo]*]*]: bar
|
||||
[*[foo]*]: bar
|
||||
[foo]: bar
|
||||
14
3rdparty/cmark-gfm/bench/samples/inline-autolink.md
vendored
Normal file
14
3rdparty/cmark-gfm/bench/samples/inline-autolink.md
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
closed (valid) autolinks:
|
||||
|
||||
<ftp://1.2.3.4:21/path/foo>
|
||||
<http://foo.bar.baz?q=hello&id=22&boolean>
|
||||
<http://veeeeeeeeeeeeeeeeeeery.loooooooooooooooooooooooooooooooong.autolink/>
|
||||
<teeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeest@gmail.com>
|
||||
|
||||
these are not autolinks:
|
||||
|
||||
<ftp://1.2.3.4:21/path/foo
|
||||
<http://foo.bar.baz?q=hello&id=22&boolean
|
||||
<http://veeeeeeeeeeeeeeeeeeery.loooooooooooooooooooooooooooooooong.autolink
|
||||
<teeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeest@gmail.com
|
||||
< http://foo.bar.baz?q=hello&id=22&boolean >
|
||||
3
3rdparty/cmark-gfm/bench/samples/inline-backticks.md
vendored
Normal file
3
3rdparty/cmark-gfm/bench/samples/inline-backticks.md
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
`lots`of`backticks`
|
||||
|
||||
``i``wonder``how``this``will``be``parsed``
|
||||
5
3rdparty/cmark-gfm/bench/samples/inline-em-flat.md
vendored
Normal file
5
3rdparty/cmark-gfm/bench/samples/inline-em-flat.md
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
*this* *is* *your* *basic* *boring* *emphasis*
|
||||
|
||||
_this_ _is_ _your_ _basic_ _boring_ _emphasis_
|
||||
|
||||
**this** **is** **your** **basic** **boring** **emphasis**
|
||||
5
3rdparty/cmark-gfm/bench/samples/inline-em-nested.md
vendored
Normal file
5
3rdparty/cmark-gfm/bench/samples/inline-em-nested.md
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
*this *is *a *bunch* of* nested* emphases*
|
||||
|
||||
__this __is __a __bunch__ of__ nested__ emphases__
|
||||
|
||||
***this ***is ***a ***bunch*** of*** nested*** emphases***
|
||||
5
3rdparty/cmark-gfm/bench/samples/inline-em-worst.md
vendored
Normal file
5
3rdparty/cmark-gfm/bench/samples/inline-em-worst.md
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
*this *is *a *worst *case *for *em *backtracking
|
||||
|
||||
__this __is __a __worst __case __for __em __backtracking
|
||||
|
||||
***this ***is ***a ***worst ***case ***for ***em ***backtracking
|
||||
11
3rdparty/cmark-gfm/bench/samples/inline-entity.md
vendored
Normal file
11
3rdparty/cmark-gfm/bench/samples/inline-entity.md
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
entities:
|
||||
|
||||
& © Æ Ď ¾ ℋ ⅆ ∲
|
||||
|
||||
# Ӓ Ϡ �
|
||||
|
||||
non-entities:
|
||||
|
||||
&18900987654321234567890; &1234567890098765432123456789009876543212345678987654;
|
||||
|
||||
&qwertyuioppoiuytrewqwer; &oiuytrewqwertyuioiuytrewqwertyuioytrewqwertyuiiuytri;
|
||||
15
3rdparty/cmark-gfm/bench/samples/inline-escape.md
vendored
Normal file
15
3rdparty/cmark-gfm/bench/samples/inline-escape.md
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
\t\e\s\t\i\n\g \e\s\c\a\p\e \s\e\q\u\e\n\c\e\s
|
||||
|
||||
\!\\\"\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?
|
||||
|
||||
\@ \[ \] \^ \_ \` \{ \| \} \~ \- \'
|
||||
|
||||
\
|
||||
\\
|
||||
\\\
|
||||
\\\\
|
||||
\\\\\
|
||||
|
||||
\<this\> \<is\> \<not\> \<html\>
|
||||
|
||||
44
3rdparty/cmark-gfm/bench/samples/inline-html.md
vendored
Normal file
44
3rdparty/cmark-gfm/bench/samples/inline-html.md
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
Taking commonmark tests from the spec for benchmarking here:
|
||||
|
||||
<a><bab><c2c>
|
||||
|
||||
<a/><b2/>
|
||||
|
||||
<a /><b2
|
||||
data="foo" >
|
||||
|
||||
<a foo="bar" bam = 'baz <em>"</em>'
|
||||
_boolean zoop:33=zoop:33 />
|
||||
|
||||
<33> <__>
|
||||
|
||||
<a h*#ref="hi">
|
||||
|
||||
<a href="hi'> <a href=hi'>
|
||||
|
||||
< a><
|
||||
foo><bar/ >
|
||||
|
||||
<a href='bar'title=title>
|
||||
|
||||
</a>
|
||||
</foo >
|
||||
|
||||
</a href="foo">
|
||||
|
||||
foo <!-- this is a
|
||||
comment - with hyphen -->
|
||||
|
||||
foo <!-- not a comment -- two hyphens -->
|
||||
|
||||
foo <?php echo $a; ?>
|
||||
|
||||
foo <!ELEMENT br EMPTY>
|
||||
|
||||
foo <![CDATA[>&<]]>
|
||||
|
||||
<a href="ö">
|
||||
|
||||
<a href="\*">
|
||||
|
||||
<a href="\"">
|
||||
23
3rdparty/cmark-gfm/bench/samples/inline-links-flat.md
vendored
Normal file
23
3rdparty/cmark-gfm/bench/samples/inline-links-flat.md
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
Valid links:
|
||||
|
||||
[this is a link]()
|
||||
[this is a link](<http://something.example.com/foo/bar>)
|
||||
[this is a link](http://something.example.com/foo/bar 'test')
|
||||
![this is an image]()
|
||||

|
||||

|
||||
|
||||
[escape test](<\>\>\>\>\>\>\>\>\>\>\>\>\>\>> '\'\'\'\'\'\'\'\'\'\'\'\'\'\'')
|
||||
[escape test \]\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]](\)\)\)\)\)\)\)\)\)\)\)\)\)\))
|
||||
|
||||
Invalid links:
|
||||
|
||||
[this is not a link
|
||||
|
||||
[this is not a link](
|
||||
|
||||
[this is not a link](http://something.example.com/foo/bar 'test'
|
||||
|
||||
[this is not a link](((((((((((((((((((((((((((((((((((((((((((((((
|
||||
|
||||
[this is not a link]((((((((((()))))))))) (((((((((()))))))))))
|
||||
13
3rdparty/cmark-gfm/bench/samples/inline-links-nested.md
vendored
Normal file
13
3rdparty/cmark-gfm/bench/samples/inline-links-nested.md
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
Valid links:
|
||||
|
||||
[[[[[[[[](test)](test)](test)](test)](test)](test)](test)]
|
||||
|
||||
[ [[[[[[[[[[[[[[[[[[ [](test) ]]]]]]]]]]]]]]]]]] ](test)
|
||||
|
||||
Invalid links:
|
||||
|
||||
[[[[[[[[[
|
||||
|
||||
[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [
|
||||
|
||||
 lobortis, sapien arcu mattis erat, vel aliquet sem urna et risus. Ut feugiat sapien vitae mi elementum laoreet. Suspendisse potenti. Aliquam erat nisl, aliquam pretium libero aliquet, sagittis eleifend nunc. In hac habitasse platea dictumst. Integer turpis augue, tincidunt dignissim mauris id, rhoncus dapibus purus. Maecenas et enim odio. Nullam massa metus, varius quis vehicula sed, pharetra mollis erat. In quis viverra velit. Vivamus placerat, est nec hendrerit varius, enim dui hendrerit magna, ut pulvinar nibh lorem vel lacus. Mauris a orci iaculis, hendrerit eros sed, gravida leo. In dictum mauris vel augue varius, ac ullamcorper nisl ornare. In eu posuere velit, ac fermentum arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nullam sed malesuada leo, at interdum elit.
|
||||
|
||||
Nullam ut tincidunt nunc. [Pellentesque][1] metus lacus, commodo eget justo ut, rutrum varius nunc. Sed non rhoncus risus. Morbi sodales gravida pulvinar. Duis malesuada, odio volutpat elementum vulputate, massa magna scelerisque ante, et accumsan tellus nunc in sem. Donec mattis arcu et velit aliquet, non sagittis justo vestibulum. Suspendisse volutpat felis lectus, nec consequat ipsum mattis id. Donec dapibus vehicula facilisis. In tincidunt mi nisi, nec faucibus tortor euismod nec. Suspendisse ante ligula, aliquet vitae libero eu, vulputate dapibus libero. Sed bibendum, sapien at posuere interdum, libero est sollicitudin magna, ac gravida tellus purus eu ipsum. Proin ut quam arcu.
|
||||
|
||||
Suspendisse potenti. Donec ante velit, ornare at augue quis, tristique laoreet sem. Etiam in ipsum elit. Nullam cursus dolor sit amet nulla feugiat tristique. Phasellus ac tellus tincidunt, imperdiet purus eget, ullamcorper ipsum. Cras eu tincidunt sem. Nullam sed dapibus magna. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In id venenatis tortor. In consectetur sollicitudin pharetra. Etiam convallis nisi nunc, et aliquam turpis viverra sit amet. Maecenas faucibus sodales tortor. Suspendisse lobortis mi eu leo viverra volutpat. Pellentesque velit ante, vehicula sodales congue ut, elementum a urna. Cras tempor, ipsum eget luctus rhoncus, arcu ligula fermentum urna, vulputate pharetra enim enim non libero.
|
||||
|
||||
Proin diam quam, elementum in eleifend id, elementum et metus. Cras in justo consequat justo semper ultrices. Sed dignissim lectus a ante mollis, nec vulputate ante molestie. Proin in porta nunc. Etiam pulvinar turpis sed velit porttitor, vel adipiscing velit fringilla. Cras ac tellus vitae purus pharetra tincidunt. Sed cursus aliquet aliquet. Cras eleifend commodo malesuada. In turpis turpis, ullamcorper ut tincidunt a, ullamcorper a nunc. Etiam luctus tellus ac dapibus gravida. Ut nec lacus laoreet neque ullamcorper volutpat.
|
||||
|
||||
Nunc et leo erat. Aenean mattis ultrices lorem, eget adipiscing dolor ultricies eu. In hac habitasse platea dictumst. Vivamus cursus feugiat sapien quis aliquam. Mauris quam libero, porta vel volutpat ut, blandit a purus. Vivamus vestibulum dui vel tortor molestie, sit amet feugiat sem commodo. Nulla facilisi. Sed molestie arcu eget tellus vestibulum tristique.
|
||||
|
||||
[1]: https://github.com/markdown-it
|
||||
18
3rdparty/cmark-gfm/bench/samples/rawtabs.md
vendored
Normal file
18
3rdparty/cmark-gfm/bench/samples/rawtabs.md
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
this is a test for tab expansion, be careful not to replace them with spaces
|
||||
|
||||
1 4444
|
||||
22 333
|
||||
333 22
|
||||
4444 1
|
||||
|
||||
|
||||
tab-indented line
|
||||
space-indented line
|
||||
tab-indented line
|
||||
|
||||
|
||||
a lot of spaces in between here
|
||||
|
||||
a lot of tabs in between here
|
||||
|
||||
595
3rdparty/cmark-gfm/bench/statistics.py
vendored
Normal file
595
3rdparty/cmark-gfm/bench/statistics.py
vendored
Normal file
@ -0,0 +1,595 @@
|
||||
## Module statistics.py
|
||||
##
|
||||
## Copyright (c) 2013 Steven D'Aprano <steve+python@pearwood.info>.
|
||||
##
|
||||
## 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.
|
||||
|
||||
|
||||
"""
|
||||
Basic statistics module.
|
||||
|
||||
This module provides functions for calculating statistics of data, including
|
||||
averages, variance, and standard deviation.
|
||||
|
||||
Calculating averages
|
||||
--------------------
|
||||
|
||||
================== =============================================
|
||||
Function Description
|
||||
================== =============================================
|
||||
mean Arithmetic mean (average) of data.
|
||||
median Median (middle value) of data.
|
||||
median_low Low median of data.
|
||||
median_high High median of data.
|
||||
median_grouped Median, or 50th percentile, of grouped data.
|
||||
mode Mode (most common value) of data.
|
||||
================== =============================================
|
||||
|
||||
Calculate the arithmetic mean ("the average") of data:
|
||||
|
||||
>>> mean([-1.0, 2.5, 3.25, 5.75])
|
||||
2.625
|
||||
|
||||
|
||||
Calculate the standard median of discrete data:
|
||||
|
||||
>>> median([2, 3, 4, 5])
|
||||
3.5
|
||||
|
||||
|
||||
Calculate the median, or 50th percentile, of data grouped into class intervals
|
||||
centred on the data values provided. E.g. if your data points are rounded to
|
||||
the nearest whole number:
|
||||
|
||||
>>> median_grouped([2, 2, 3, 3, 3, 4]) #doctest: +ELLIPSIS
|
||||
2.8333333333...
|
||||
|
||||
This should be interpreted in this way: you have two data points in the class
|
||||
interval 1.5-2.5, three data points in the class interval 2.5-3.5, and one in
|
||||
the class interval 3.5-4.5. The median of these data points is 2.8333...
|
||||
|
||||
|
||||
Calculating variability or spread
|
||||
---------------------------------
|
||||
|
||||
================== =============================================
|
||||
Function Description
|
||||
================== =============================================
|
||||
pvariance Population variance of data.
|
||||
variance Sample variance of data.
|
||||
pstdev Population standard deviation of data.
|
||||
stdev Sample standard deviation of data.
|
||||
================== =============================================
|
||||
|
||||
Calculate the standard deviation of sample data:
|
||||
|
||||
>>> stdev([2.5, 3.25, 5.5, 11.25, 11.75]) #doctest: +ELLIPSIS
|
||||
4.38961843444...
|
||||
|
||||
If you have previously calculated the mean, you can pass it as the optional
|
||||
second argument to the four "spread" functions to avoid recalculating it:
|
||||
|
||||
>>> data = [1, 2, 2, 4, 4, 4, 5, 6]
|
||||
>>> mu = mean(data)
|
||||
>>> pvariance(data, mu)
|
||||
2.5
|
||||
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
A single exception is defined: StatisticsError is a subclass of ValueError.
|
||||
|
||||
"""
|
||||
|
||||
__all__ = [ 'StatisticsError',
|
||||
'pstdev', 'pvariance', 'stdev', 'variance',
|
||||
'median', 'median_low', 'median_high', 'median_grouped',
|
||||
'mean', 'mode',
|
||||
]
|
||||
|
||||
|
||||
import collections
|
||||
import math
|
||||
|
||||
from fractions import Fraction
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
# === Exceptions ===
|
||||
|
||||
class StatisticsError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
# === Private utilities ===
|
||||
|
||||
def _sum(data, start=0):
|
||||
"""_sum(data [, start]) -> value
|
||||
|
||||
Return a high-precision sum of the given numeric data. If optional
|
||||
argument ``start`` is given, it is added to the total. If ``data`` is
|
||||
empty, ``start`` (defaulting to 0) is returned.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
>>> _sum([3, 2.25, 4.5, -0.5, 1.0], 0.75)
|
||||
11.0
|
||||
|
||||
Some sources of round-off error will be avoided:
|
||||
|
||||
>>> _sum([1e50, 1, -1e50] * 1000) # Built-in sum returns zero.
|
||||
1000.0
|
||||
|
||||
Fractions and Decimals are also supported:
|
||||
|
||||
>>> from fractions import Fraction as F
|
||||
>>> _sum([F(2, 3), F(7, 5), F(1, 4), F(5, 6)])
|
||||
Fraction(63, 20)
|
||||
|
||||
>>> from decimal import Decimal as D
|
||||
>>> data = [D("0.1375"), D("0.2108"), D("0.3061"), D("0.0419")]
|
||||
>>> _sum(data)
|
||||
Decimal('0.6963')
|
||||
|
||||
Mixed types are currently treated as an error, except that int is
|
||||
allowed.
|
||||
"""
|
||||
# We fail as soon as we reach a value that is not an int or the type of
|
||||
# the first value which is not an int. E.g. _sum([int, int, float, int])
|
||||
# is okay, but sum([int, int, float, Fraction]) is not.
|
||||
allowed_types = set([int, type(start)])
|
||||
n, d = _exact_ratio(start)
|
||||
partials = {d: n} # map {denominator: sum of numerators}
|
||||
# Micro-optimizations.
|
||||
exact_ratio = _exact_ratio
|
||||
partials_get = partials.get
|
||||
# Add numerators for each denominator.
|
||||
for x in data:
|
||||
_check_type(type(x), allowed_types)
|
||||
n, d = exact_ratio(x)
|
||||
partials[d] = partials_get(d, 0) + n
|
||||
# Find the expected result type. If allowed_types has only one item, it
|
||||
# will be int; if it has two, use the one which isn't int.
|
||||
assert len(allowed_types) in (1, 2)
|
||||
if len(allowed_types) == 1:
|
||||
assert allowed_types.pop() is int
|
||||
T = int
|
||||
else:
|
||||
T = (allowed_types - set([int])).pop()
|
||||
if None in partials:
|
||||
assert issubclass(T, (float, Decimal))
|
||||
assert not math.isfinite(partials[None])
|
||||
return T(partials[None])
|
||||
total = Fraction()
|
||||
for d, n in sorted(partials.items()):
|
||||
total += Fraction(n, d)
|
||||
if issubclass(T, int):
|
||||
assert total.denominator == 1
|
||||
return T(total.numerator)
|
||||
if issubclass(T, Decimal):
|
||||
return T(total.numerator)/total.denominator
|
||||
return T(total)
|
||||
|
||||
|
||||
def _check_type(T, allowed):
|
||||
if T not in allowed:
|
||||
if len(allowed) == 1:
|
||||
allowed.add(T)
|
||||
else:
|
||||
types = ', '.join([t.__name__ for t in allowed] + [T.__name__])
|
||||
raise TypeError("unsupported mixed types: %s" % types)
|
||||
|
||||
|
||||
def _exact_ratio(x):
|
||||
"""Convert Real number x exactly to (numerator, denominator) pair.
|
||||
|
||||
>>> _exact_ratio(0.25)
|
||||
(1, 4)
|
||||
|
||||
x is expected to be an int, Fraction, Decimal or float.
|
||||
"""
|
||||
try:
|
||||
try:
|
||||
# int, Fraction
|
||||
return (x.numerator, x.denominator)
|
||||
except AttributeError:
|
||||
# float
|
||||
try:
|
||||
return x.as_integer_ratio()
|
||||
except AttributeError:
|
||||
# Decimal
|
||||
try:
|
||||
return _decimal_to_ratio(x)
|
||||
except AttributeError:
|
||||
msg = "can't convert type '{}' to numerator/denominator"
|
||||
raise TypeError(msg.format(type(x).__name__)) from None
|
||||
except (OverflowError, ValueError):
|
||||
# INF or NAN
|
||||
if __debug__:
|
||||
# Decimal signalling NANs cannot be converted to float :-(
|
||||
if isinstance(x, Decimal):
|
||||
assert not x.is_finite()
|
||||
else:
|
||||
assert not math.isfinite(x)
|
||||
return (x, None)
|
||||
|
||||
|
||||
# FIXME This is faster than Fraction.from_decimal, but still too slow.
|
||||
def _decimal_to_ratio(d):
|
||||
"""Convert Decimal d to exact integer ratio (numerator, denominator).
|
||||
|
||||
>>> from decimal import Decimal
|
||||
>>> _decimal_to_ratio(Decimal("2.6"))
|
||||
(26, 10)
|
||||
|
||||
"""
|
||||
sign, digits, exp = d.as_tuple()
|
||||
if exp in ('F', 'n', 'N'): # INF, NAN, sNAN
|
||||
assert not d.is_finite()
|
||||
raise ValueError
|
||||
num = 0
|
||||
for digit in digits:
|
||||
num = num*10 + digit
|
||||
if exp < 0:
|
||||
den = 10**-exp
|
||||
else:
|
||||
num *= 10**exp
|
||||
den = 1
|
||||
if sign:
|
||||
num = -num
|
||||
return (num, den)
|
||||
|
||||
|
||||
def _counts(data):
|
||||
# Generate a table of sorted (value, frequency) pairs.
|
||||
table = collections.Counter(iter(data)).most_common()
|
||||
if not table:
|
||||
return table
|
||||
# Extract the values with the highest frequency.
|
||||
maxfreq = table[0][1]
|
||||
for i in range(1, len(table)):
|
||||
if table[i][1] != maxfreq:
|
||||
table = table[:i]
|
||||
break
|
||||
return table
|
||||
|
||||
|
||||
# === Measures of central tendency (averages) ===
|
||||
|
||||
def mean(data):
|
||||
"""Return the sample arithmetic mean of data.
|
||||
|
||||
>>> mean([1, 2, 3, 4, 4])
|
||||
2.8
|
||||
|
||||
>>> from fractions import Fraction as F
|
||||
>>> mean([F(3, 7), F(1, 21), F(5, 3), F(1, 3)])
|
||||
Fraction(13, 21)
|
||||
|
||||
>>> from decimal import Decimal as D
|
||||
>>> mean([D("0.5"), D("0.75"), D("0.625"), D("0.375")])
|
||||
Decimal('0.5625')
|
||||
|
||||
If ``data`` is empty, StatisticsError will be raised.
|
||||
"""
|
||||
if iter(data) is data:
|
||||
data = list(data)
|
||||
n = len(data)
|
||||
if n < 1:
|
||||
raise StatisticsError('mean requires at least one data point')
|
||||
return _sum(data)/n
|
||||
|
||||
|
||||
# FIXME: investigate ways to calculate medians without sorting? Quickselect?
|
||||
def median(data):
|
||||
"""Return the median (middle value) of numeric data.
|
||||
|
||||
When the number of data points is odd, return the middle data point.
|
||||
When the number of data points is even, the median is interpolated by
|
||||
taking the average of the two middle values:
|
||||
|
||||
>>> median([1, 3, 5])
|
||||
3
|
||||
>>> median([1, 3, 5, 7])
|
||||
4.0
|
||||
|
||||
"""
|
||||
data = sorted(data)
|
||||
n = len(data)
|
||||
if n == 0:
|
||||
raise StatisticsError("no median for empty data")
|
||||
if n%2 == 1:
|
||||
return data[n//2]
|
||||
else:
|
||||
i = n//2
|
||||
return (data[i - 1] + data[i])/2
|
||||
|
||||
|
||||
def median_low(data):
|
||||
"""Return the low median of numeric data.
|
||||
|
||||
When the number of data points is odd, the middle value is returned.
|
||||
When it is even, the smaller of the two middle values is returned.
|
||||
|
||||
>>> median_low([1, 3, 5])
|
||||
3
|
||||
>>> median_low([1, 3, 5, 7])
|
||||
3
|
||||
|
||||
"""
|
||||
data = sorted(data)
|
||||
n = len(data)
|
||||
if n == 0:
|
||||
raise StatisticsError("no median for empty data")
|
||||
if n%2 == 1:
|
||||
return data[n//2]
|
||||
else:
|
||||
return data[n//2 - 1]
|
||||
|
||||
|
||||
def median_high(data):
|
||||
"""Return the high median of data.
|
||||
|
||||
When the number of data points is odd, the middle value is returned.
|
||||
When it is even, the larger of the two middle values is returned.
|
||||
|
||||
>>> median_high([1, 3, 5])
|
||||
3
|
||||
>>> median_high([1, 3, 5, 7])
|
||||
5
|
||||
|
||||
"""
|
||||
data = sorted(data)
|
||||
n = len(data)
|
||||
if n == 0:
|
||||
raise StatisticsError("no median for empty data")
|
||||
return data[n//2]
|
||||
|
||||
|
||||
def median_grouped(data, interval=1):
|
||||
""""Return the 50th percentile (median) of grouped continuous data.
|
||||
|
||||
>>> median_grouped([1, 2, 2, 3, 4, 4, 4, 4, 4, 5])
|
||||
3.7
|
||||
>>> median_grouped([52, 52, 53, 54])
|
||||
52.5
|
||||
|
||||
This calculates the median as the 50th percentile, and should be
|
||||
used when your data is continuous and grouped. In the above example,
|
||||
the values 1, 2, 3, etc. actually represent the midpoint of classes
|
||||
0.5-1.5, 1.5-2.5, 2.5-3.5, etc. The middle value falls somewhere in
|
||||
class 3.5-4.5, and interpolation is used to estimate it.
|
||||
|
||||
Optional argument ``interval`` represents the class interval, and
|
||||
defaults to 1. Changing the class interval naturally will change the
|
||||
interpolated 50th percentile value:
|
||||
|
||||
>>> median_grouped([1, 3, 3, 5, 7], interval=1)
|
||||
3.25
|
||||
>>> median_grouped([1, 3, 3, 5, 7], interval=2)
|
||||
3.5
|
||||
|
||||
This function does not check whether the data points are at least
|
||||
``interval`` apart.
|
||||
"""
|
||||
data = sorted(data)
|
||||
n = len(data)
|
||||
if n == 0:
|
||||
raise StatisticsError("no median for empty data")
|
||||
elif n == 1:
|
||||
return data[0]
|
||||
# Find the value at the midpoint. Remember this corresponds to the
|
||||
# centre of the class interval.
|
||||
x = data[n//2]
|
||||
for obj in (x, interval):
|
||||
if isinstance(obj, (str, bytes)):
|
||||
raise TypeError('expected number but got %r' % obj)
|
||||
try:
|
||||
L = x - interval/2 # The lower limit of the median interval.
|
||||
except TypeError:
|
||||
# Mixed type. For now we just coerce to float.
|
||||
L = float(x) - float(interval)/2
|
||||
cf = data.index(x) # Number of values below the median interval.
|
||||
# FIXME The following line could be more efficient for big lists.
|
||||
f = data.count(x) # Number of data points in the median interval.
|
||||
return L + interval*(n/2 - cf)/f
|
||||
|
||||
|
||||
def mode(data):
|
||||
"""Return the most common data point from discrete or nominal data.
|
||||
|
||||
``mode`` assumes discrete data, and returns a single value. This is the
|
||||
standard treatment of the mode as commonly taught in schools:
|
||||
|
||||
>>> mode([1, 1, 2, 3, 3, 3, 3, 4])
|
||||
3
|
||||
|
||||
This also works with nominal (non-numeric) data:
|
||||
|
||||
>>> mode(["red", "blue", "blue", "red", "green", "red", "red"])
|
||||
'red'
|
||||
|
||||
If there is not exactly one most common value, ``mode`` will raise
|
||||
StatisticsError.
|
||||
"""
|
||||
# Generate a table of sorted (value, frequency) pairs.
|
||||
table = _counts(data)
|
||||
if len(table) == 1:
|
||||
return table[0][0]
|
||||
elif table:
|
||||
raise StatisticsError(
|
||||
'no unique mode; found %d equally common values' % len(table)
|
||||
)
|
||||
else:
|
||||
raise StatisticsError('no mode for empty data')
|
||||
|
||||
|
||||
# === Measures of spread ===
|
||||
|
||||
# See http://mathworld.wolfram.com/Variance.html
|
||||
# http://mathworld.wolfram.com/SampleVariance.html
|
||||
# http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
|
||||
#
|
||||
# Under no circumstances use the so-called "computational formula for
|
||||
# variance", as that is only suitable for hand calculations with a small
|
||||
# amount of low-precision data. It has terrible numeric properties.
|
||||
#
|
||||
# See a comparison of three computational methods here:
|
||||
# http://www.johndcook.com/blog/2008/09/26/comparing-three-methods-of-computing-standard-deviation/
|
||||
|
||||
def _ss(data, c=None):
|
||||
"""Return sum of square deviations of sequence data.
|
||||
|
||||
If ``c`` is None, the mean is calculated in one pass, and the deviations
|
||||
from the mean are calculated in a second pass. Otherwise, deviations are
|
||||
calculated from ``c`` as given. Use the second case with care, as it can
|
||||
lead to garbage results.
|
||||
"""
|
||||
if c is None:
|
||||
c = mean(data)
|
||||
ss = _sum((x-c)**2 for x in data)
|
||||
# The following sum should mathematically equal zero, but due to rounding
|
||||
# error may not.
|
||||
ss -= _sum((x-c) for x in data)**2/len(data)
|
||||
assert not ss < 0, 'negative sum of square deviations: %f' % ss
|
||||
return ss
|
||||
|
||||
|
||||
def variance(data, xbar=None):
|
||||
"""Return the sample variance of data.
|
||||
|
||||
data should be an iterable of Real-valued numbers, with at least two
|
||||
values. The optional argument xbar, if given, should be the mean of
|
||||
the data. If it is missing or None, the mean is automatically calculated.
|
||||
|
||||
Use this function when your data is a sample from a population. To
|
||||
calculate the variance from the entire population, see ``pvariance``.
|
||||
|
||||
Examples:
|
||||
|
||||
>>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
|
||||
>>> variance(data)
|
||||
1.3720238095238095
|
||||
|
||||
If you have already calculated the mean of your data, you can pass it as
|
||||
the optional second argument ``xbar`` to avoid recalculating it:
|
||||
|
||||
>>> m = mean(data)
|
||||
>>> variance(data, m)
|
||||
1.3720238095238095
|
||||
|
||||
This function does not check that ``xbar`` is actually the mean of
|
||||
``data``. Giving arbitrary values for ``xbar`` may lead to invalid or
|
||||
impossible results.
|
||||
|
||||
Decimals and Fractions are supported:
|
||||
|
||||
>>> from decimal import Decimal as D
|
||||
>>> variance([D("27.5"), D("30.25"), D("30.25"), D("34.5"), D("41.75")])
|
||||
Decimal('31.01875')
|
||||
|
||||
>>> from fractions import Fraction as F
|
||||
>>> variance([F(1, 6), F(1, 2), F(5, 3)])
|
||||
Fraction(67, 108)
|
||||
|
||||
"""
|
||||
if iter(data) is data:
|
||||
data = list(data)
|
||||
n = len(data)
|
||||
if n < 2:
|
||||
raise StatisticsError('variance requires at least two data points')
|
||||
ss = _ss(data, xbar)
|
||||
return ss/(n-1)
|
||||
|
||||
|
||||
def pvariance(data, mu=None):
|
||||
"""Return the population variance of ``data``.
|
||||
|
||||
data should be an iterable of Real-valued numbers, with at least one
|
||||
value. The optional argument mu, if given, should be the mean of
|
||||
the data. If it is missing or None, the mean is automatically calculated.
|
||||
|
||||
Use this function to calculate the variance from the entire population.
|
||||
To estimate the variance from a sample, the ``variance`` function is
|
||||
usually a better choice.
|
||||
|
||||
Examples:
|
||||
|
||||
>>> data = [0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25]
|
||||
>>> pvariance(data)
|
||||
1.25
|
||||
|
||||
If you have already calculated the mean of the data, you can pass it as
|
||||
the optional second argument to avoid recalculating it:
|
||||
|
||||
>>> mu = mean(data)
|
||||
>>> pvariance(data, mu)
|
||||
1.25
|
||||
|
||||
This function does not check that ``mu`` is actually the mean of ``data``.
|
||||
Giving arbitrary values for ``mu`` may lead to invalid or impossible
|
||||
results.
|
||||
|
||||
Decimals and Fractions are supported:
|
||||
|
||||
>>> from decimal import Decimal as D
|
||||
>>> pvariance([D("27.5"), D("30.25"), D("30.25"), D("34.5"), D("41.75")])
|
||||
Decimal('24.815')
|
||||
|
||||
>>> from fractions import Fraction as F
|
||||
>>> pvariance([F(1, 4), F(5, 4), F(1, 2)])
|
||||
Fraction(13, 72)
|
||||
|
||||
"""
|
||||
if iter(data) is data:
|
||||
data = list(data)
|
||||
n = len(data)
|
||||
if n < 1:
|
||||
raise StatisticsError('pvariance requires at least one data point')
|
||||
ss = _ss(data, mu)
|
||||
return ss/n
|
||||
|
||||
|
||||
def stdev(data, xbar=None):
|
||||
"""Return the square root of the sample variance.
|
||||
|
||||
See ``variance`` for arguments and other details.
|
||||
|
||||
>>> stdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])
|
||||
1.0810874155219827
|
||||
|
||||
"""
|
||||
var = variance(data, xbar)
|
||||
try:
|
||||
return var.sqrt()
|
||||
except AttributeError:
|
||||
return math.sqrt(var)
|
||||
|
||||
|
||||
def pstdev(data, mu=None):
|
||||
"""Return the square root of the population variance.
|
||||
|
||||
See ``pvariance`` for arguments and other details.
|
||||
|
||||
>>> pstdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75])
|
||||
0.986893273527251
|
||||
|
||||
"""
|
||||
var = pvariance(data, mu)
|
||||
try:
|
||||
return var.sqrt()
|
||||
except AttributeError:
|
||||
return math.sqrt(var)
|
||||
19
3rdparty/cmark-gfm/bench/stats.py
vendored
Normal file
19
3rdparty/cmark-gfm/bench/stats.py
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import statistics
|
||||
|
||||
def pairs(l, n):
|
||||
return zip(*[l[i::n] for i in range(n)])
|
||||
|
||||
# data comes in pairs:
|
||||
# n - time for running the program with no input
|
||||
# m - time for running it with the benchmark input
|
||||
# we measure (m - n)
|
||||
|
||||
values = [ float(y) - float(x) for (x,y) in pairs(sys.stdin.readlines(),2)]
|
||||
|
||||
print("mean = %.4f, median = %.4f, stdev = %.4f" %
|
||||
(statistics.mean(values), statistics.median(values),
|
||||
statistics.stdev(values)))
|
||||
|
||||
33
3rdparty/cmark-gfm/benchmarks.md
vendored
Normal file
33
3rdparty/cmark-gfm/benchmarks.md
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
# Benchmarks
|
||||
|
||||
Here are some benchmarks, run on an ancient Thinkpad running Intel
|
||||
Core 2 Duo at 2GHz. The input text is a 11MB Markdown file built by
|
||||
concatenating the Markdown sources of all the localizations of the
|
||||
first edition of
|
||||
[*Pro Git*](https://github.com/progit/progit/tree/master/en) by Scott
|
||||
Chacon.
|
||||
|
||||
|Implementation | Time (sec)|
|
||||
|-------------------|-----------:|
|
||||
| Markdown.pl | 2921.24 |
|
||||
| Python markdown | 291.25 |
|
||||
| PHP markdown | 20.82 |
|
||||
| kramdown | 17.32 |
|
||||
| cheapskate | 8.24 |
|
||||
| peg-markdown | 5.45 |
|
||||
| parsedown | 5.06 |
|
||||
| **commonmark.js** | 2.09 |
|
||||
| marked | 1.99 |
|
||||
| discount | 1.85 |
|
||||
| **cmark** | 0.29 |
|
||||
| hoedown | 0.21 |
|
||||
|
||||
To run these benchmarks, use `make bench PROG=/path/to/program`.
|
||||
|
||||
`time` is used to measure execution speed. The reported
|
||||
time is the *difference* between the time to run the program
|
||||
with the benchmark input and the time to run it with no input.
|
||||
(This procedure ensures that implementations in dynamic languages are
|
||||
not penalized by startup time.) A median of ten runs is taken. The
|
||||
process is reniced to a high priority so that the system doesn't
|
||||
interrupt runs.
|
||||
BIN
3rdparty/cmark-gfm/bin/cmark-gfm.exe
vendored
BIN
3rdparty/cmark-gfm/bin/cmark-gfm.exe
vendored
Binary file not shown.
1245
3rdparty/cmark-gfm/changelog.txt
vendored
Normal file
1245
3rdparty/cmark-gfm/changelog.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1495
3rdparty/cmark-gfm/data/CaseFolding.txt
vendored
Normal file
1495
3rdparty/cmark-gfm/data/CaseFolding.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
125
3rdparty/cmark-gfm/extensions/CMakeLists.txt
vendored
Normal file
125
3rdparty/cmark-gfm/extensions/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
set(LIBRARY "libcmark-gfm-extensions")
|
||||
set(STATICLIBRARY "libcmark-gfm-extensions_static")
|
||||
|
||||
set(LIBRARY_SOURCES
|
||||
core-extensions.c
|
||||
table.c
|
||||
strikethrough.c
|
||||
autolink.c
|
||||
tagfilter.c
|
||||
ext_scanners.c
|
||||
ext_scanners.re
|
||||
ext_scanners.h
|
||||
tasklist.c
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_BINARY_DIR}/src
|
||||
)
|
||||
|
||||
include_directories(. ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE} -pg")
|
||||
set(CMAKE_LINKER_PROFILE "${CMAKE_LINKER_FLAGS_RELEASE} -pg")
|
||||
|
||||
if (CMARK_SHARED)
|
||||
add_library(${LIBRARY} SHARED ${LIBRARY_SOURCES})
|
||||
|
||||
set_target_properties(${LIBRARY} PROPERTIES
|
||||
OUTPUT_NAME "cmark-gfm-extensions"
|
||||
DEFINE_SYMBOL "cmark-gfm"
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.gfm.${PROJECT_VERSION_GFM}
|
||||
VERSION ${PROJECT_VERSION})
|
||||
|
||||
set_property(TARGET ${LIBRARY}
|
||||
APPEND PROPERTY MACOSX_RPATH true)
|
||||
|
||||
# Avoid name clash between PROGRAM and LIBRARY pdb files.
|
||||
set_target_properties(${LIBRARY} PROPERTIES PDB_NAME cmark-gfm-extensions_dll)
|
||||
|
||||
list(APPEND CMARK_INSTALL ${LIBRARY})
|
||||
target_link_libraries(${LIBRARY} libcmark-gfm)
|
||||
|
||||
endif()
|
||||
|
||||
if (CMARK_STATIC)
|
||||
add_library(${STATICLIBRARY} STATIC ${LIBRARY_SOURCES})
|
||||
|
||||
set_target_properties(${STATICLIBRARY} PROPERTIES
|
||||
AUTOMOC OFF
|
||||
AUTOUIC OFF
|
||||
AUTORCC OFF)
|
||||
|
||||
set_target_properties(${STATICLIBRARY} PROPERTIES
|
||||
COMPILE_FLAGS "-DCMARK_GFM_STATIC_DEFINE -DCMARK_GFM_EXTENSIONS_STATIC_DEFINE"
|
||||
DEFINE_SYMBOL "cmark-gfm"
|
||||
POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if (MSVC)
|
||||
set_target_properties(${STATICLIBRARY} PROPERTIES
|
||||
OUTPUT_NAME "cmark-gfm-extensions_static"
|
||||
VERSION ${PROJECT_VERSION})
|
||||
else()
|
||||
set_target_properties(${STATICLIBRARY} PROPERTIES
|
||||
OUTPUT_NAME "cmark-gfm-extensions"
|
||||
VERSION ${PROJECT_VERSION})
|
||||
endif(MSVC)
|
||||
|
||||
list(APPEND CMARK_INSTALL ${STATICLIBRARY})
|
||||
endif()
|
||||
|
||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON)
|
||||
|
||||
include (InstallRequiredSystemLibraries)
|
||||
install(TARGETS ${CMARK_INSTALL}
|
||||
EXPORT cmark-gfm-extensions
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib${LIB_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LIB_SUFFIX}
|
||||
)
|
||||
|
||||
if (CMARK_SHARED OR CMARK_STATIC)
|
||||
install(FILES
|
||||
cmark-gfm-core-extensions.h
|
||||
DESTINATION include
|
||||
)
|
||||
|
||||
install(EXPORT cmark-gfm-extensions DESTINATION lib${LIB_SUFFIX}/cmake-gfm-extensions)
|
||||
endif()
|
||||
|
||||
# Feature tests
|
||||
include(CheckIncludeFile)
|
||||
include(CheckCSourceCompiles)
|
||||
include(CheckCSourceRuns)
|
||||
include(CheckSymbolExists)
|
||||
CHECK_INCLUDE_FILE(stdbool.h HAVE_STDBOOL_H)
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"int main() { __builtin_expect(0,0); return 0; }"
|
||||
HAVE___BUILTIN_EXPECT)
|
||||
CHECK_C_SOURCE_COMPILES("
|
||||
int f(void) __attribute__ (());
|
||||
int main() { return 0; }
|
||||
" HAVE___ATTRIBUTE__)
|
||||
|
||||
# Always compile with warnings
|
||||
if(MSVC)
|
||||
# Force to always compile with W4
|
||||
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX /wd4706 /wd4204 /wd4221 /wd4100 /D_CRT_SECURE_NO_WARNINGS")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter -std=c99 -pedantic")
|
||||
endif()
|
||||
|
||||
# Compile as C++ under MSVC older than 12.0
|
||||
if(MSVC AND MSVC_VERSION LESS 1800)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /TP")
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Ubsan")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
|
||||
endif()
|
||||
508
3rdparty/cmark-gfm/extensions/autolink.c
vendored
Normal file
508
3rdparty/cmark-gfm/extensions/autolink.c
vendored
Normal file
@ -0,0 +1,508 @@
|
||||
#include "autolink.h"
|
||||
#include <parser.h>
|
||||
#include <string.h>
|
||||
#include <utf8.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define strncasecmp _strnicmp
|
||||
#else
|
||||
#include <strings.h>
|
||||
#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;
|
||||
}
|
||||
8
3rdparty/cmark-gfm/extensions/autolink.h
vendored
Normal file
8
3rdparty/cmark-gfm/extensions/autolink.h
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef CMARK_GFM_AUTOLINK_H
|
||||
#define CMARK_GFM_AUTOLINK_H
|
||||
|
||||
#include "cmark-gfm-core-extensions.h"
|
||||
|
||||
cmark_syntax_extension *create_autolink_extension(void);
|
||||
|
||||
#endif
|
||||
27
3rdparty/cmark-gfm/extensions/core-extensions.c
vendored
Normal file
27
3rdparty/cmark-gfm/extensions/core-extensions.c
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
879
3rdparty/cmark-gfm/extensions/ext_scanners.c
vendored
Normal file
879
3rdparty/cmark-gfm/extensions/ext_scanners.c
vendored
Normal file
@ -0,0 +1,879 @@
|
||||
/* Generated by re2c 1.3 */
|
||||
|
||||
#include "ext_scanners.h"
|
||||
#include <stdlib.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;
|
||||
}
|
||||
|
||||
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); }
|
||||
}
|
||||
}
|
||||
24
3rdparty/cmark-gfm/extensions/ext_scanners.h
vendored
Normal file
24
3rdparty/cmark-gfm/extensions/ext_scanners.h
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
#include "chunk.h"
|
||||
#include "cmark-gfm.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bufsize_t _ext_scan_at(bufsize_t (*scanner)(const unsigned char *),
|
||||
unsigned char *ptr, int len, bufsize_t offset);
|
||||
bufsize_t _scan_table_start(const unsigned char *p);
|
||||
bufsize_t _scan_table_cell(const unsigned char *p);
|
||||
bufsize_t _scan_table_cell_end(const unsigned char *p);
|
||||
bufsize_t _scan_table_row_end(const unsigned char *p);
|
||||
bufsize_t _scan_tasklist(const unsigned char *p);
|
||||
|
||||
#define scan_table_start(c, l, n) _ext_scan_at(&_scan_table_start, c, l, n)
|
||||
#define scan_table_cell(c, l, n) _ext_scan_at(&_scan_table_cell, c, l, n)
|
||||
#define scan_table_cell_end(c, l, n) _ext_scan_at(&_scan_table_cell_end, c, l, n)
|
||||
#define scan_table_row_end(c, l, n) _ext_scan_at(&_scan_table_row_end, c, l, n)
|
||||
#define scan_tasklist(c, l, n) _ext_scan_at(&_scan_tasklist, c, l, n)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
92
3rdparty/cmark-gfm/extensions/ext_scanners.re
vendored
Normal file
92
3rdparty/cmark-gfm/extensions/ext_scanners.re
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
/*!re2c re2c:flags:no-debug-info = 1; */
|
||||
/*!re2c re2c:indent:string = ' '; */
|
||||
|
||||
#include <stdlib.h>
|
||||
#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; }
|
||||
*/
|
||||
}
|
||||
167
3rdparty/cmark-gfm/extensions/strikethrough.c
vendored
Normal file
167
3rdparty/cmark-gfm/extensions/strikethrough.c
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
#include "strikethrough.h"
|
||||
#include <parser.h>
|
||||
#include <render.h>
|
||||
|
||||
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" : "<unknown>";
|
||||
}
|
||||
|
||||
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, "<del>");
|
||||
} else {
|
||||
cmark_strbuf_puts(renderer->html, "</del>");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
9
3rdparty/cmark-gfm/extensions/strikethrough.h
vendored
Normal file
9
3rdparty/cmark-gfm/extensions/strikethrough.h
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef CMARK_GFM_STRIKETHROUGH_H
|
||||
#define CMARK_GFM_STRIKETHROUGH_H
|
||||
|
||||
#include "cmark-gfm-core-extensions.h"
|
||||
|
||||
extern cmark_node_type CMARK_NODE_STRIKETHROUGH;
|
||||
cmark_syntax_extension *create_strikethrough_extension(void);
|
||||
|
||||
#endif
|
||||
917
3rdparty/cmark-gfm/extensions/table.c
vendored
Normal file
917
3rdparty/cmark-gfm/extensions/table.c
vendored
Normal file
@ -0,0 +1,917 @@
|
||||
#include <cmark-gfm-extension_api.h>
|
||||
#include <html.h>
|
||||
#include <inlines.h>
|
||||
#include <parser.h>
|
||||
#include <references.h>
|
||||
#include <string.h>
|
||||
#include <render.h>
|
||||
|
||||
#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 "<unknown>";
|
||||
}
|
||||
|
||||
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");
|
||||
cmark_html_render_sourcepos(node, html, options);
|
||||
cmark_strbuf_putc(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, "</tbody>");
|
||||
cmark_html_render_cr(html);
|
||||
}
|
||||
table_state->need_closing_table_body = false;
|
||||
cmark_html_render_cr(html);
|
||||
cmark_strbuf_puts(html, "</table>");
|
||||
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, "<thead>");
|
||||
cmark_html_render_cr(html);
|
||||
} else if (!table_state->need_closing_table_body) {
|
||||
cmark_strbuf_puts(html, "<tbody>");
|
||||
cmark_html_render_cr(html);
|
||||
table_state->need_closing_table_body = 1;
|
||||
}
|
||||
cmark_strbuf_puts(html, "<tr");
|
||||
cmark_html_render_sourcepos(node, html, options);
|
||||
cmark_strbuf_putc(html, '>');
|
||||
} else {
|
||||
cmark_html_render_cr(html);
|
||||
cmark_strbuf_puts(html, "</tr>");
|
||||
if (((node_table_row *)node->as.opaque)->is_header) {
|
||||
cmark_html_render_cr(html);
|
||||
cmark_strbuf_puts(html, "</thead>");
|
||||
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, "<th");
|
||||
} else {
|
||||
cmark_strbuf_puts(html, "<td");
|
||||
}
|
||||
|
||||
switch (get_cell_alignment(node)) {
|
||||
case 'l': html_table_add_align(html, "left", options); break;
|
||||
case 'c': html_table_add_align(html, "center", options); break;
|
||||
case 'r': html_table_add_align(html, "right", options); break;
|
||||
}
|
||||
|
||||
cmark_html_render_sourcepos(node, html, options);
|
||||
cmark_strbuf_putc(html, '>');
|
||||
} else {
|
||||
if (table_state->in_table_header) {
|
||||
cmark_strbuf_puts(html, "</th>");
|
||||
} else {
|
||||
cmark_strbuf_puts(html, "</td>");
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
12
3rdparty/cmark-gfm/extensions/table.h
vendored
Normal file
12
3rdparty/cmark-gfm/extensions/table.h
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef CMARK_GFM_TABLE_H
|
||||
#define CMARK_GFM_TABLE_H
|
||||
|
||||
#include "cmark-gfm-core-extensions.h"
|
||||
|
||||
|
||||
extern cmark_node_type CMARK_NODE_TABLE, CMARK_NODE_TABLE_ROW,
|
||||
CMARK_NODE_TABLE_CELL;
|
||||
|
||||
cmark_syntax_extension *create_table_extension(void);
|
||||
|
||||
#endif
|
||||
60
3rdparty/cmark-gfm/extensions/tagfilter.c
vendored
Normal file
60
3rdparty/cmark-gfm/extensions/tagfilter.c
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
#include "tagfilter.h"
|
||||
#include <parser.h>
|
||||
#include <ctype.h>
|
||||
|
||||
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;
|
||||
}
|
||||
8
3rdparty/cmark-gfm/extensions/tagfilter.h
vendored
Normal file
8
3rdparty/cmark-gfm/extensions/tagfilter.h
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef CMARK_GFM_TAGFILTER_H
|
||||
#define CMARK_GFM_TAGFILTER_H
|
||||
|
||||
#include "cmark-gfm-core-extensions.h"
|
||||
|
||||
cmark_syntax_extension *create_tagfilter_extension(void);
|
||||
|
||||
#endif
|
||||
156
3rdparty/cmark-gfm/extensions/tasklist.c
vendored
Normal file
156
3rdparty/cmark-gfm/extensions/tasklist.c
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
#include "tasklist.h"
|
||||
#include <parser.h>
|
||||
#include <render.h>
|
||||
#include <html.h>
|
||||
#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, "<li");
|
||||
cmark_html_render_sourcepos(node, renderer->html, options);
|
||||
cmark_strbuf_putc(renderer->html, '>');
|
||||
if (node->as.list.checked) {
|
||||
cmark_strbuf_puts(renderer->html, "<input type=\"checkbox\" checked=\"\" disabled=\"\" /> ");
|
||||
} else {
|
||||
cmark_strbuf_puts(renderer->html, "<input type=\"checkbox\" disabled=\"\" /> ");
|
||||
}
|
||||
} else {
|
||||
cmark_strbuf_puts(renderer->html, "</li>\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;
|
||||
}
|
||||
8
3rdparty/cmark-gfm/extensions/tasklist.h
vendored
Normal file
8
3rdparty/cmark-gfm/extensions/tasklist.h
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef TASKLIST_H
|
||||
#define TASKLIST_H
|
||||
|
||||
#include "cmark-gfm-core-extensions.h"
|
||||
|
||||
cmark_syntax_extension *create_tasklist_extension(void);
|
||||
|
||||
#endif
|
||||
22
3rdparty/cmark-gfm/fuzz/CMakeLists.txt
vendored
Normal file
22
3rdparty/cmark-gfm/fuzz/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
include_directories(
|
||||
${PROJECT_BINARY_DIR}/extensions
|
||||
${PROJECT_BINARY_DIR}/src
|
||||
../extensions
|
||||
../src
|
||||
)
|
||||
|
||||
macro(fuzzer name)
|
||||
add_executable(${name} ${name}.c)
|
||||
set_target_properties(${name}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "-fsanitize=fuzzer"
|
||||
LINK_FLAGS "-fsanitize=fuzzer")
|
||||
if(CMARK_SHARED)
|
||||
target_link_libraries(${name} libcmark-gfm-extensions libcmark-gfm)
|
||||
elseif(CMARK_STATIC)
|
||||
target_link_libraries(${name} libcmark-gfm-extensions_static libcmark-gfm_static)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
fuzzer(fuzz_quadratic)
|
||||
fuzzer(fuzz_quadratic_brackets)
|
||||
12
3rdparty/cmark-gfm/fuzz/README.md
vendored
Normal file
12
3rdparty/cmark-gfm/fuzz/README.md
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
The quadratic fuzzer generates long sequences of repeated characters, such as `<?x<?x<?x<?x...`,
|
||||
to detect quadratic complexity performance issues.
|
||||
|
||||
To build and run the quadratic fuzzer:
|
||||
|
||||
```bash
|
||||
mkdir build-fuzz
|
||||
cd build-fuzz
|
||||
cmake -DCMARK_FUZZ_QUADRATIC=ON -DCMAKE_C_COMPILER=$(which clang) -DCMAKE_CXX_COMPILER=$(which clang++) -DCMAKE_BUILD_TYPE=Release ..
|
||||
make
|
||||
../fuzz/fuzzloop.sh
|
||||
```
|
||||
91
3rdparty/cmark-gfm/fuzz/fuzz_quadratic.c
vendored
Normal file
91
3rdparty/cmark-gfm/fuzz/fuzz_quadratic.c
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cmark-gfm.h"
|
||||
#include "cmark-gfm-core-extensions.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char *extension_names[] = {
|
||||
"autolink",
|
||||
"strikethrough",
|
||||
"table",
|
||||
"tagfilter",
|
||||
NULL,
|
||||
};
|
||||
|
||||
int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
||||
cmark_gfm_core_extensions_ensure_registered();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
struct __attribute__((packed)) {
|
||||
int options;
|
||||
int width;
|
||||
uint8_t splitpoint;
|
||||
uint8_t repeatlen;
|
||||
} fuzz_config;
|
||||
|
||||
if (size >= sizeof(fuzz_config)) {
|
||||
/* The beginning of `data` is treated as fuzzer configuration */
|
||||
memcpy(&fuzz_config, data, sizeof(fuzz_config));
|
||||
|
||||
/* Test options that are used by GitHub. */
|
||||
fuzz_config.options = CMARK_OPT_UNSAFE | CMARK_OPT_FOOTNOTES | CMARK_OPT_GITHUB_PRE_LANG | CMARK_OPT_HARDBREAKS;
|
||||
|
||||
/* Remainder of input is the markdown */
|
||||
const char *markdown0 = (const char *)(data + sizeof(fuzz_config));
|
||||
const size_t markdown_size0 = size - sizeof(fuzz_config);
|
||||
char markdown[0x80000];
|
||||
if (markdown_size0 <= sizeof(markdown)) {
|
||||
size_t markdown_size = 0;
|
||||
if (fuzz_config.splitpoint <= markdown_size0 && 0 < fuzz_config.repeatlen &&
|
||||
fuzz_config.repeatlen <= markdown_size0 - fuzz_config.splitpoint) {
|
||||
const size_t size_after_splitpoint = markdown_size0 - fuzz_config.splitpoint - fuzz_config.repeatlen;
|
||||
memcpy(&markdown[markdown_size], &markdown0[0], fuzz_config.splitpoint);
|
||||
markdown_size += fuzz_config.splitpoint;
|
||||
|
||||
while (markdown_size + fuzz_config.repeatlen + size_after_splitpoint <= sizeof(markdown)) {
|
||||
memcpy(&markdown[markdown_size], &markdown0[fuzz_config.splitpoint],
|
||||
fuzz_config.repeatlen);
|
||||
markdown_size += fuzz_config.repeatlen;
|
||||
}
|
||||
memcpy(&markdown[markdown_size], &markdown0[fuzz_config.splitpoint + fuzz_config.repeatlen],
|
||||
size_after_splitpoint);
|
||||
markdown_size += size_after_splitpoint;
|
||||
} else {
|
||||
markdown_size = markdown_size0;
|
||||
memcpy(markdown, markdown0, markdown_size);
|
||||
}
|
||||
|
||||
cmark_parser *parser = cmark_parser_new(fuzz_config.options);
|
||||
|
||||
for (const char **it = extension_names; *it; ++it) {
|
||||
const char *extension_name = *it;
|
||||
cmark_syntax_extension *syntax_extension = cmark_find_syntax_extension(extension_name);
|
||||
if (!syntax_extension) {
|
||||
fprintf(stderr, "%s is not a valid syntax extension\n", extension_name);
|
||||
abort();
|
||||
}
|
||||
cmark_parser_attach_syntax_extension(parser, syntax_extension);
|
||||
}
|
||||
|
||||
cmark_parser_feed(parser, markdown, markdown_size);
|
||||
cmark_node *doc = cmark_parser_finish(parser);
|
||||
|
||||
free(cmark_render_html(doc, fuzz_config.options, NULL));
|
||||
free(cmark_render_xml(doc, fuzz_config.options));
|
||||
free(cmark_render_man(doc, fuzz_config.options, 80));
|
||||
free(cmark_render_commonmark(doc, fuzz_config.options, 80));
|
||||
free(cmark_render_plaintext(doc, fuzz_config.options, 80));
|
||||
free(cmark_render_latex(doc, fuzz_config.options, 80));
|
||||
|
||||
cmark_node_free(doc);
|
||||
cmark_parser_free(parser);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
110
3rdparty/cmark-gfm/fuzz/fuzz_quadratic_brackets.c
vendored
Normal file
110
3rdparty/cmark-gfm/fuzz/fuzz_quadratic_brackets.c
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cmark-gfm.h"
|
||||
#include "cmark-gfm-core-extensions.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const char *extension_names[] = {
|
||||
"autolink",
|
||||
"strikethrough",
|
||||
"table",
|
||||
"tagfilter",
|
||||
NULL,
|
||||
};
|
||||
|
||||
int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
||||
cmark_gfm_core_extensions_ensure_registered();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
struct __attribute__((packed)) {
|
||||
int options;
|
||||
int width;
|
||||
uint8_t startlen;
|
||||
uint8_t openlen;
|
||||
uint8_t middlelen;
|
||||
uint8_t closelen;
|
||||
} fuzz_config;
|
||||
|
||||
if (size >= sizeof(fuzz_config)) {
|
||||
/* The beginning of `data` is treated as fuzzer configuration */
|
||||
memcpy(&fuzz_config, data, sizeof(fuzz_config));
|
||||
|
||||
/* Test options that are used by GitHub. */
|
||||
fuzz_config.options = CMARK_OPT_UNSAFE | CMARK_OPT_FOOTNOTES | CMARK_OPT_GITHUB_PRE_LANG | CMARK_OPT_HARDBREAKS;
|
||||
fuzz_config.openlen = fuzz_config.openlen & 0x7;
|
||||
fuzz_config.middlelen = fuzz_config.middlelen & 0x7;
|
||||
fuzz_config.closelen = fuzz_config.closelen & 0x7;
|
||||
|
||||
/* Remainder of input is the markdown */
|
||||
const char *markdown0 = (const char *)(data + sizeof(fuzz_config));
|
||||
const size_t markdown_size0 = size - sizeof(fuzz_config);
|
||||
char markdown[0x80000];
|
||||
if (markdown_size0 <= sizeof(markdown)) {
|
||||
size_t markdown_size = 0;
|
||||
const size_t componentslen = fuzz_config.startlen + fuzz_config.openlen + fuzz_config.middlelen + fuzz_config.closelen;
|
||||
if (componentslen <= markdown_size0) {
|
||||
size_t offset = 0;
|
||||
const size_t endlen = markdown_size0 - componentslen;
|
||||
memcpy(&markdown[markdown_size], &markdown0[offset], fuzz_config.startlen);
|
||||
markdown_size += fuzz_config.startlen;
|
||||
offset += fuzz_config.startlen;
|
||||
|
||||
if (0 < fuzz_config.openlen) {
|
||||
while (markdown_size + fuzz_config.openlen <= sizeof(markdown)/2) {
|
||||
memcpy(&markdown[markdown_size], &markdown0[offset],
|
||||
fuzz_config.openlen);
|
||||
markdown_size += fuzz_config.openlen;
|
||||
}
|
||||
offset += fuzz_config.openlen;
|
||||
}
|
||||
memcpy(&markdown[markdown_size], &markdown0[offset],
|
||||
fuzz_config.middlelen);
|
||||
markdown_size += fuzz_config.middlelen;
|
||||
offset += fuzz_config.middlelen;
|
||||
if (0 < fuzz_config.closelen) {
|
||||
while (markdown_size + fuzz_config.closelen + endlen <= sizeof(markdown)) {
|
||||
memcpy(&markdown[markdown_size], &markdown0[offset],
|
||||
fuzz_config.closelen);
|
||||
markdown_size += fuzz_config.closelen;
|
||||
}
|
||||
offset += fuzz_config.closelen;
|
||||
}
|
||||
if (markdown_size + endlen <= sizeof(markdown)) {
|
||||
memcpy(&markdown[markdown_size], &markdown0[offset],
|
||||
endlen);
|
||||
markdown_size += endlen;
|
||||
}
|
||||
} else {
|
||||
markdown_size = markdown_size0;
|
||||
memcpy(markdown, markdown0, markdown_size);
|
||||
}
|
||||
|
||||
cmark_parser *parser = cmark_parser_new(fuzz_config.options);
|
||||
|
||||
for (const char **it = extension_names; *it; ++it) {
|
||||
const char *extension_name = *it;
|
||||
cmark_syntax_extension *syntax_extension = cmark_find_syntax_extension(extension_name);
|
||||
if (!syntax_extension) {
|
||||
fprintf(stderr, "%s is not a valid syntax extension\n", extension_name);
|
||||
abort();
|
||||
}
|
||||
cmark_parser_attach_syntax_extension(parser, syntax_extension);
|
||||
}
|
||||
|
||||
cmark_parser_feed(parser, markdown, markdown_size);
|
||||
cmark_node *doc = cmark_parser_finish(parser);
|
||||
|
||||
free(cmark_render_html(doc, fuzz_config.options, NULL));
|
||||
|
||||
cmark_node_free(doc);
|
||||
cmark_parser_free(parser);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
28
3rdparty/cmark-gfm/fuzz/fuzzloop.sh
vendored
Normal file
28
3rdparty/cmark-gfm/fuzz/fuzzloop.sh
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Stop when an error is found
|
||||
set -e
|
||||
|
||||
# Create a corpus sub-directory if it doesn't already exist.
|
||||
mkdir -p corpus
|
||||
|
||||
# The memory and disk usage grows over time, so this loop restarts the
|
||||
# fuzzer every 4 hours. The `-merge=1` option is used to minimize the
|
||||
# corpus on each iteration.
|
||||
while :
|
||||
do
|
||||
date
|
||||
echo restarting loop
|
||||
|
||||
# Minimize the corpus
|
||||
mv corpus/ corpus2
|
||||
mkdir corpus
|
||||
echo minimizing corpus
|
||||
./fuzz/fuzz_quadratic -merge=1 corpus ../bench corpus2/ -max_len=1024
|
||||
rm -r corpus2
|
||||
|
||||
# Run the fuzzer for 4 hours
|
||||
date
|
||||
echo start fuzzer
|
||||
./fuzz/fuzz_quadratic corpus -dict=../test/fuzzing_dictionary -jobs=$(nproc) -workers=$(nproc) -max_len=1024 -max_total_time=14400
|
||||
done
|
||||
@ -1,19 +0,0 @@
|
||||
#----------------------------------------------------------------
|
||||
# Generated CMake target import file for configuration "Release".
|
||||
#----------------------------------------------------------------
|
||||
|
||||
# Commands may need to know the format version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION 1)
|
||||
|
||||
# Import target "libcmark-gfm-extensions_static" for configuration "Release"
|
||||
set_property(TARGET libcmark-gfm-extensions_static APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_target_properties(libcmark-gfm-extensions_static PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
|
||||
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libcmark-gfm-extensions.a"
|
||||
)
|
||||
|
||||
list(APPEND _cmake_import_check_targets libcmark-gfm-extensions_static )
|
||||
list(APPEND _cmake_import_check_files_for_libcmark-gfm-extensions_static "${_IMPORT_PREFIX}/lib/libcmark-gfm-extensions.a" )
|
||||
|
||||
# Commands beyond this point should not need to know the version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION)
|
||||
@ -1,101 +0,0 @@
|
||||
# Generated by CMake
|
||||
|
||||
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8)
|
||||
message(FATAL_ERROR "CMake >= 2.8.0 required")
|
||||
endif()
|
||||
if(CMAKE_VERSION VERSION_LESS "2.8.3")
|
||||
message(FATAL_ERROR "CMake >= 2.8.3 required")
|
||||
endif()
|
||||
cmake_policy(PUSH)
|
||||
cmake_policy(VERSION 2.8.3...3.28)
|
||||
#----------------------------------------------------------------
|
||||
# Generated CMake target import file.
|
||||
#----------------------------------------------------------------
|
||||
|
||||
# Commands may need to know the format version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION 1)
|
||||
|
||||
# Protect against multiple inclusion, which would fail when already imported targets are added once more.
|
||||
set(_cmake_targets_defined "")
|
||||
set(_cmake_targets_not_defined "")
|
||||
set(_cmake_expected_targets "")
|
||||
foreach(_cmake_expected_target IN ITEMS libcmark-gfm-extensions_static)
|
||||
list(APPEND _cmake_expected_targets "${_cmake_expected_target}")
|
||||
if(TARGET "${_cmake_expected_target}")
|
||||
list(APPEND _cmake_targets_defined "${_cmake_expected_target}")
|
||||
else()
|
||||
list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}")
|
||||
endif()
|
||||
endforeach()
|
||||
unset(_cmake_expected_target)
|
||||
if(_cmake_targets_defined STREQUAL _cmake_expected_targets)
|
||||
unset(_cmake_targets_defined)
|
||||
unset(_cmake_targets_not_defined)
|
||||
unset(_cmake_expected_targets)
|
||||
unset(CMAKE_IMPORT_FILE_VERSION)
|
||||
cmake_policy(POP)
|
||||
return()
|
||||
endif()
|
||||
if(NOT _cmake_targets_defined STREQUAL "")
|
||||
string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}")
|
||||
string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}")
|
||||
message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n")
|
||||
endif()
|
||||
unset(_cmake_targets_defined)
|
||||
unset(_cmake_targets_not_defined)
|
||||
unset(_cmake_expected_targets)
|
||||
|
||||
|
||||
# Compute the installation prefix relative to this file.
|
||||
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
|
||||
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
|
||||
if(_IMPORT_PREFIX STREQUAL "/")
|
||||
set(_IMPORT_PREFIX "")
|
||||
endif()
|
||||
|
||||
# Create imported target libcmark-gfm-extensions_static
|
||||
add_library(libcmark-gfm-extensions_static STATIC IMPORTED)
|
||||
|
||||
# Load information for each installed configuration.
|
||||
file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/cmark-gfm-extensions-*.cmake")
|
||||
foreach(_cmake_config_file IN LISTS _cmake_config_files)
|
||||
include("${_cmake_config_file}")
|
||||
endforeach()
|
||||
unset(_cmake_config_file)
|
||||
unset(_cmake_config_files)
|
||||
|
||||
# Cleanup temporary variables.
|
||||
set(_IMPORT_PREFIX)
|
||||
|
||||
# Loop over all imported files and verify that they actually exist
|
||||
foreach(_cmake_target IN LISTS _cmake_import_check_targets)
|
||||
if(CMAKE_VERSION VERSION_LESS "3.28"
|
||||
OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target}
|
||||
OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}")
|
||||
foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}")
|
||||
if(NOT EXISTS "${_cmake_file}")
|
||||
message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file
|
||||
\"${_cmake_file}\"
|
||||
but this file does not exist. Possible reasons include:
|
||||
* The file was deleted, renamed, or moved to another location.
|
||||
* An install or uninstall procedure did not complete successfully.
|
||||
* The installation package was faulty and contained
|
||||
\"${CMAKE_CURRENT_LIST_FILE}\"
|
||||
but not all the files it references.
|
||||
")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
unset(_cmake_file)
|
||||
unset("_cmake_import_check_files_for_${_cmake_target}")
|
||||
endforeach()
|
||||
unset(_cmake_target)
|
||||
unset(_cmake_import_check_targets)
|
||||
|
||||
# This file does not depend on other imported targets which have
|
||||
# been exported from the same project but in a separate export set.
|
||||
|
||||
# Commands beyond this point should not need to know the version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION)
|
||||
cmake_policy(POP)
|
||||
@ -1,28 +0,0 @@
|
||||
#----------------------------------------------------------------
|
||||
# Generated CMake target import file for configuration "Release".
|
||||
#----------------------------------------------------------------
|
||||
|
||||
# Commands may need to know the format version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION 1)
|
||||
|
||||
# Import target "cmark-gfm" for configuration "Release"
|
||||
set_property(TARGET cmark-gfm APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_target_properties(cmark-gfm PROPERTIES
|
||||
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/cmark-gfm.exe"
|
||||
)
|
||||
|
||||
list(APPEND _cmake_import_check_targets cmark-gfm )
|
||||
list(APPEND _cmake_import_check_files_for_cmark-gfm "${_IMPORT_PREFIX}/bin/cmark-gfm.exe" )
|
||||
|
||||
# Import target "libcmark-gfm_static" for configuration "Release"
|
||||
set_property(TARGET libcmark-gfm_static APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_target_properties(libcmark-gfm_static PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
|
||||
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libcmark-gfm.a"
|
||||
)
|
||||
|
||||
list(APPEND _cmake_import_check_targets libcmark-gfm_static )
|
||||
list(APPEND _cmake_import_check_files_for_libcmark-gfm_static "${_IMPORT_PREFIX}/lib/libcmark-gfm.a" )
|
||||
|
||||
# Commands beyond this point should not need to know the version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION)
|
||||
104
3rdparty/cmark-gfm/lib/cmake/cmark-gfm.cmake
vendored
104
3rdparty/cmark-gfm/lib/cmake/cmark-gfm.cmake
vendored
@ -1,104 +0,0 @@
|
||||
# Generated by CMake
|
||||
|
||||
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8)
|
||||
message(FATAL_ERROR "CMake >= 2.8.0 required")
|
||||
endif()
|
||||
if(CMAKE_VERSION VERSION_LESS "2.8.3")
|
||||
message(FATAL_ERROR "CMake >= 2.8.3 required")
|
||||
endif()
|
||||
cmake_policy(PUSH)
|
||||
cmake_policy(VERSION 2.8.3...3.28)
|
||||
#----------------------------------------------------------------
|
||||
# Generated CMake target import file.
|
||||
#----------------------------------------------------------------
|
||||
|
||||
# Commands may need to know the format version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION 1)
|
||||
|
||||
# Protect against multiple inclusion, which would fail when already imported targets are added once more.
|
||||
set(_cmake_targets_defined "")
|
||||
set(_cmake_targets_not_defined "")
|
||||
set(_cmake_expected_targets "")
|
||||
foreach(_cmake_expected_target IN ITEMS cmark-gfm libcmark-gfm_static)
|
||||
list(APPEND _cmake_expected_targets "${_cmake_expected_target}")
|
||||
if(TARGET "${_cmake_expected_target}")
|
||||
list(APPEND _cmake_targets_defined "${_cmake_expected_target}")
|
||||
else()
|
||||
list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}")
|
||||
endif()
|
||||
endforeach()
|
||||
unset(_cmake_expected_target)
|
||||
if(_cmake_targets_defined STREQUAL _cmake_expected_targets)
|
||||
unset(_cmake_targets_defined)
|
||||
unset(_cmake_targets_not_defined)
|
||||
unset(_cmake_expected_targets)
|
||||
unset(CMAKE_IMPORT_FILE_VERSION)
|
||||
cmake_policy(POP)
|
||||
return()
|
||||
endif()
|
||||
if(NOT _cmake_targets_defined STREQUAL "")
|
||||
string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}")
|
||||
string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}")
|
||||
message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n")
|
||||
endif()
|
||||
unset(_cmake_targets_defined)
|
||||
unset(_cmake_targets_not_defined)
|
||||
unset(_cmake_expected_targets)
|
||||
|
||||
|
||||
# Compute the installation prefix relative to this file.
|
||||
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
|
||||
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
|
||||
if(_IMPORT_PREFIX STREQUAL "/")
|
||||
set(_IMPORT_PREFIX "")
|
||||
endif()
|
||||
|
||||
# Create imported target cmark-gfm
|
||||
add_executable(cmark-gfm IMPORTED)
|
||||
|
||||
# Create imported target libcmark-gfm_static
|
||||
add_library(libcmark-gfm_static STATIC IMPORTED)
|
||||
|
||||
# Load information for each installed configuration.
|
||||
file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/cmark-gfm-*.cmake")
|
||||
foreach(_cmake_config_file IN LISTS _cmake_config_files)
|
||||
include("${_cmake_config_file}")
|
||||
endforeach()
|
||||
unset(_cmake_config_file)
|
||||
unset(_cmake_config_files)
|
||||
|
||||
# Cleanup temporary variables.
|
||||
set(_IMPORT_PREFIX)
|
||||
|
||||
# Loop over all imported files and verify that they actually exist
|
||||
foreach(_cmake_target IN LISTS _cmake_import_check_targets)
|
||||
if(CMAKE_VERSION VERSION_LESS "3.28"
|
||||
OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target}
|
||||
OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}")
|
||||
foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}")
|
||||
if(NOT EXISTS "${_cmake_file}")
|
||||
message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file
|
||||
\"${_cmake_file}\"
|
||||
but this file does not exist. Possible reasons include:
|
||||
* The file was deleted, renamed, or moved to another location.
|
||||
* An install or uninstall procedure did not complete successfully.
|
||||
* The installation package was faulty and contained
|
||||
\"${CMAKE_CURRENT_LIST_FILE}\"
|
||||
but not all the files it references.
|
||||
")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
unset(_cmake_file)
|
||||
unset("_cmake_import_check_files_for_${_cmake_target}")
|
||||
endforeach()
|
||||
unset(_cmake_target)
|
||||
unset(_cmake_import_check_targets)
|
||||
|
||||
# This file does not depend on other imported targets which have
|
||||
# been exported from the same project but in a separate export set.
|
||||
|
||||
# Commands beyond this point should not need to know the version.
|
||||
set(CMAKE_IMPORT_FILE_VERSION)
|
||||
cmake_policy(POP)
|
||||
BIN
3rdparty/cmark-gfm/lib/libcmark-gfm-extensions.a
vendored
BIN
3rdparty/cmark-gfm/lib/libcmark-gfm-extensions.a
vendored
Binary file not shown.
BIN
3rdparty/cmark-gfm/lib/libcmark-gfm.a
vendored
BIN
3rdparty/cmark-gfm/lib/libcmark-gfm.a
vendored
Binary file not shown.
10
3rdparty/cmark-gfm/lib/pkgconfig/libcmark-gfm.pc
vendored
10
3rdparty/cmark-gfm/lib/pkgconfig/libcmark-gfm.pc
vendored
@ -1,10 +0,0 @@
|
||||
prefix=F:/SourceCode/ctai/3rdparty/cmark-gfm
|
||||
exec_prefix=F:/SourceCode/ctai/3rdparty/cmark-gfm
|
||||
libdir=F:/SourceCode/ctai/3rdparty/cmark-gfm/lib
|
||||
includedir=F:/SourceCode/ctai/3rdparty/cmark-gfm/include
|
||||
|
||||
Name: libcmark-gfm
|
||||
Description: CommonMark parsing, rendering, and manipulation with GitHub Flavored Markdown extensions
|
||||
Version: 0.29.0.gfm.13
|
||||
Libs: -L${libdir} -lcmark-gfm -lcmark-gfm-extensions
|
||||
Cflags: -I${includedir}
|
||||
10
3rdparty/cmark-gfm/man/CMakeLists.txt
vendored
Normal file
10
3rdparty/cmark-gfm/man/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
if (NOT MSVC)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man1/cmark-gfm.1
|
||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/man3/cmark-gfm.3
|
||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
|
||||
endif(NOT MSVC)
|
||||
133
3rdparty/cmark-gfm/man/make_man_page.py
vendored
Normal file
133
3rdparty/cmark-gfm/man/make_man_page.py
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Creates a man page from a C file.
|
||||
|
||||
# first argument if present is path to cmark dynamic library
|
||||
|
||||
# Comments beginning with `/**` are treated as Groff man, except that
|
||||
# 'this' is converted to \fIthis\f[], and ''this'' to \fBthis\f[].
|
||||
|
||||
# Non-blank lines immediately following a man page comment are treated
|
||||
# as function signatures or examples and parsed into .Ft, .Fo, .Fa, .Fc. The
|
||||
# immediately preceding man documentation chunk is printed after the example
|
||||
# as a comment on it.
|
||||
|
||||
# That's about it!
|
||||
|
||||
import sys, re, os, platform
|
||||
from datetime import date
|
||||
from ctypes import CDLL, c_char_p, c_long, c_void_p
|
||||
|
||||
sysname = platform.system()
|
||||
|
||||
if sysname == 'Darwin':
|
||||
cmark = CDLL("build/src/libcmark-gfm.dylib")
|
||||
else:
|
||||
cmark = CDLL("build/src/libcmark-gfm.so")
|
||||
|
||||
parse_document = cmark.cmark_parse_document
|
||||
parse_document.restype = c_void_p
|
||||
parse_document.argtypes = [c_char_p, c_long]
|
||||
|
||||
render_man = cmark.cmark_render_man
|
||||
render_man.restype = c_char_p
|
||||
render_man.argtypes = [c_void_p, c_long, c_long]
|
||||
|
||||
def md2man(text):
|
||||
if sys.version_info >= (3,0):
|
||||
textbytes = text.encode('utf-8')
|
||||
textlen = len(textbytes)
|
||||
return render_man(parse_document(textbytes, textlen), 0, 65).decode('utf-8')
|
||||
else:
|
||||
textbytes = text
|
||||
textlen = len(text)
|
||||
return render_man(parse_document(textbytes, textlen), 0, 72)
|
||||
|
||||
comment_start_re = re.compile('^\/\*\* ?')
|
||||
comment_delim_re = re.compile('^[/ ]\** ?')
|
||||
comment_end_re = re.compile('^ \**\/')
|
||||
function_re = re.compile('^ *(?:CMARK_GFM_EXPORT\s+)?(?P<type>(?:const\s+)?\w+(?:\s*[*])?)\s*(?P<name>\w+)\s*\((?P<args>[^)]*)\)')
|
||||
blank_re = re.compile('^\s*$')
|
||||
macro_re = re.compile('CMARK_GFM_EXPORT *')
|
||||
typedef_start_re = re.compile('typedef.*{$')
|
||||
typedef_end_re = re.compile('}')
|
||||
single_quote_re = re.compile("(?<!\w)'([^']+)'(?!\w)")
|
||||
double_quote_re = re.compile("(?<!\w)''([^']+)''(?!\w)")
|
||||
|
||||
def handle_quotes(s):
|
||||
return re.sub(double_quote_re, '**\g<1>**', re.sub(single_quote_re, '*\g<1>*', s))
|
||||
|
||||
typedef = False
|
||||
mdlines = []
|
||||
chunk = []
|
||||
sig = []
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
sourcefile = sys.argv[1]
|
||||
else:
|
||||
print("Usage: make_man_page.py sourcefile")
|
||||
exit(1)
|
||||
|
||||
with open(sourcefile, 'r') as cmarkh:
|
||||
state = 'default'
|
||||
for line in cmarkh:
|
||||
# state transition
|
||||
oldstate = state
|
||||
if comment_start_re.match(line):
|
||||
state = 'man'
|
||||
elif comment_end_re.match(line) and state == 'man':
|
||||
continue
|
||||
elif comment_delim_re.match(line) and state == 'man':
|
||||
state = 'man'
|
||||
elif not typedef and blank_re.match(line):
|
||||
state = 'default'
|
||||
elif typedef and typedef_end_re.match(line):
|
||||
typedef = False
|
||||
elif typedef_start_re.match(line):
|
||||
typedef = True
|
||||
state = 'signature'
|
||||
elif state == 'man':
|
||||
state = 'signature'
|
||||
|
||||
# handle line
|
||||
if state == 'man':
|
||||
chunk.append(handle_quotes(re.sub(comment_delim_re, '', line)))
|
||||
elif state == 'signature':
|
||||
ln = re.sub(macro_re, '', line)
|
||||
if typedef or not re.match(blank_re, ln):
|
||||
sig.append(ln)
|
||||
elif oldstate == 'signature' and state != 'signature':
|
||||
if len(mdlines) > 0 and mdlines[-1] != '\n':
|
||||
mdlines.append('\n')
|
||||
rawsig = ''.join(sig)
|
||||
m = function_re.match(rawsig)
|
||||
mdlines.append('.PP\n')
|
||||
if m:
|
||||
mdlines.append('\\fI' + m.group('type') + '\\f[]' + ' ')
|
||||
mdlines.append('\\fB' + m.group('name') + '\\f[]' + '(')
|
||||
first = True
|
||||
for argument in re.split(',', m.group('args')):
|
||||
if not first:
|
||||
mdlines.append(', ')
|
||||
first = False
|
||||
mdlines.append('\\fI' + argument.strip() + '\\f[]')
|
||||
mdlines.append(')\n')
|
||||
else:
|
||||
mdlines.append('.nf\n\\fC\n.RS 0n\n')
|
||||
mdlines += sig
|
||||
mdlines.append('.RE\n\\f[]\n.fi\n')
|
||||
if len(mdlines) > 0 and mdlines[-1] != '\n':
|
||||
mdlines.append('\n')
|
||||
mdlines += md2man(''.join(chunk))
|
||||
mdlines.append('\n')
|
||||
chunk = []
|
||||
sig = []
|
||||
elif oldstate == 'man' and state != 'signature':
|
||||
if len(mdlines) > 0 and mdlines[-1] != '\n':
|
||||
mdlines.append('\n')
|
||||
mdlines += md2man(''.join(chunk)) # add man chunk
|
||||
chunk = []
|
||||
mdlines.append('\n')
|
||||
|
||||
sys.stdout.write('.TH cmark-gfm 3 "' + date.today().strftime('%B %d, %Y') + '" "LOCAL" "Library Functions Manual"\n')
|
||||
sys.stdout.write(''.join(mdlines))
|
||||
1
3rdparty/cmark-gfm/nmake.bat
vendored
Normal file
1
3rdparty/cmark-gfm/nmake.bat
vendored
Normal file
@ -0,0 +1 @@
|
||||
@nmake.exe /nologo /f Makefile.nmake %*
|
||||
206
3rdparty/cmark-gfm/src/CMakeLists.txt
vendored
Normal file
206
3rdparty/cmark-gfm/src/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
if(${CMAKE_VERSION} VERSION_GREATER "3.3")
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(LIBRARY "libcmark-gfm")
|
||||
set(STATICLIBRARY "libcmark-gfm_static")
|
||||
set(HEADERS
|
||||
cmark-gfm.h
|
||||
cmark-gfm-extension_api.h
|
||||
parser.h
|
||||
buffer.h
|
||||
node.h
|
||||
iterator.h
|
||||
chunk.h
|
||||
references.h
|
||||
footnotes.h
|
||||
map.h
|
||||
utf8.h
|
||||
scanners.h
|
||||
inlines.h
|
||||
houdini.h
|
||||
cmark_ctype.h
|
||||
render.h
|
||||
registry.h
|
||||
syntax_extension.h
|
||||
plugin.h
|
||||
)
|
||||
set(LIBRARY_SOURCES
|
||||
cmark.c
|
||||
node.c
|
||||
iterator.c
|
||||
blocks.c
|
||||
inlines.c
|
||||
scanners.c
|
||||
scanners.re
|
||||
utf8.c
|
||||
buffer.c
|
||||
references.c
|
||||
footnotes.c
|
||||
map.c
|
||||
render.c
|
||||
man.c
|
||||
xml.c
|
||||
html.c
|
||||
commonmark.c
|
||||
plaintext.c
|
||||
latex.c
|
||||
houdini_href_e.c
|
||||
houdini_html_e.c
|
||||
houdini_html_u.c
|
||||
cmark_ctype.c
|
||||
arena.c
|
||||
linked_list.c
|
||||
syntax_extension.c
|
||||
registry.c
|
||||
plugin.c
|
||||
${HEADERS}
|
||||
)
|
||||
|
||||
include_directories(. ${CMAKE_CURRENT_BINARY_DIR})
|
||||
include_directories(
|
||||
${PROJECT_BINARY_DIR}/extensions
|
||||
)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmark-gfm_version.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmark-gfm_version.h)
|
||||
|
||||
include (GenerateExportHeader)
|
||||
|
||||
include("../CheckFileOffsetBits.cmake")
|
||||
CHECK_FILE_OFFSET_BITS()
|
||||
|
||||
# Check integrity of node structure when compiled as debug:
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DCMARK_DEBUG_NODES -DDEBUG")
|
||||
set(CMAKE_LINKER_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG}")
|
||||
|
||||
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE} -pg")
|
||||
set(CMAKE_LINKER_PROFILE "${CMAKE_LINKER_FLAGS_RELEASE} -pg")
|
||||
|
||||
# -fvisibility=hidden
|
||||
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
|
||||
|
||||
if (CMARK_SHARED)
|
||||
add_library(${LIBRARY} SHARED ${LIBRARY_SOURCES})
|
||||
# Include minor version and patch level in soname for now.
|
||||
set_target_properties(${LIBRARY} PROPERTIES
|
||||
OUTPUT_NAME "cmark-gfm"
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.gfm.${PROJECT_VERSION_GFM}
|
||||
VERSION ${PROJECT_VERSION})
|
||||
|
||||
set_property(TARGET ${LIBRARY}
|
||||
APPEND PROPERTY MACOSX_RPATH true)
|
||||
|
||||
# Avoid name clash between PROGRAM and LIBRARY pdb files.
|
||||
set_target_properties(${LIBRARY} PROPERTIES PDB_NAME cmark-gfm_dll)
|
||||
|
||||
generate_export_header(${LIBRARY}
|
||||
BASE_NAME ${PROJECT_NAME})
|
||||
|
||||
list(APPEND CMARK_INSTALL ${LIBRARY})
|
||||
endif()
|
||||
|
||||
if (CMARK_STATIC)
|
||||
add_library(${STATICLIBRARY} STATIC ${LIBRARY_SOURCES})
|
||||
set_target_properties(${STATICLIBRARY} PROPERTIES
|
||||
COMPILE_FLAGS -DCMARK_GFM_STATIC_DEFINE
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
AUTOMOC OFF
|
||||
AUTOUIC OFF
|
||||
AUTORCC OFF)
|
||||
|
||||
if (MSVC)
|
||||
set_target_properties(${STATICLIBRARY} PROPERTIES
|
||||
OUTPUT_NAME "cmark-gfm_static"
|
||||
VERSION ${PROJECT_VERSION})
|
||||
else()
|
||||
set_target_properties(${STATICLIBRARY} PROPERTIES
|
||||
OUTPUT_NAME "cmark-gfm"
|
||||
VERSION ${PROJECT_VERSION})
|
||||
endif(MSVC)
|
||||
|
||||
if (NOT CMARK_SHARED)
|
||||
generate_export_header(${STATICLIBRARY}
|
||||
BASE_NAME ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
list(APPEND CMARK_INSTALL ${STATICLIBRARY})
|
||||
endif()
|
||||
|
||||
|
||||
if(NOT MSVC OR CMAKE_HOST_SYSTEM_NAME STREQUAL Windows)
|
||||
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON)
|
||||
include(InstallRequiredSystemLibraries)
|
||||
endif()
|
||||
|
||||
set(libdir lib${LIB_SUFFIX})
|
||||
|
||||
|
||||
if(CMARK_SHARED OR CMARK_STATIC)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libcmark-gfm.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libcmark-gfm.pc @ONLY)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libcmark-gfm.pc
|
||||
DESTINATION ${libdir}/pkgconfig)
|
||||
|
||||
install(FILES
|
||||
cmark-gfm.h
|
||||
cmark-gfm-extension_api.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmark-gfm_export.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmark-gfm_version.h
|
||||
DESTINATION include
|
||||
)
|
||||
endif()
|
||||
|
||||
# Feature tests
|
||||
include(CheckIncludeFile)
|
||||
include(CheckCSourceCompiles)
|
||||
include(CheckCSourceRuns)
|
||||
include(CheckSymbolExists)
|
||||
CHECK_INCLUDE_FILE(stdbool.h HAVE_STDBOOL_H)
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"int main() { __builtin_expect(0,0); return 0; }"
|
||||
HAVE___BUILTIN_EXPECT)
|
||||
CHECK_C_SOURCE_COMPILES("
|
||||
int f(void) __attribute__ (());
|
||||
int main() { return 0; }
|
||||
" HAVE___ATTRIBUTE__)
|
||||
|
||||
CONFIGURE_FILE(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
# Always compile with warnings
|
||||
if(MSVC)
|
||||
# Force to always compile with W4
|
||||
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX /wd4706 /wd4204 /wd4221 /wd4100 /D_CRT_SECURE_NO_WARNINGS")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter -std=c99 -pedantic")
|
||||
endif()
|
||||
|
||||
# Compile as C++ under MSVC older than 12.0
|
||||
if(MSVC AND MSVC_VERSION LESS 1800)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /TP")
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Ubsan")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
|
||||
endif()
|
||||
|
||||
if(CMARK_LIB_FUZZER)
|
||||
set(FUZZ_HARNESS "cmark-fuzz")
|
||||
add_executable(${FUZZ_HARNESS} ../test/cmark-fuzz.c ${LIBRARY_SOURCES})
|
||||
target_link_libraries(${FUZZ_HARNESS} "${CMAKE_LIB_FUZZER_PATH}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-coverage=trace-pc-guard")
|
||||
|
||||
# cmark is written in C but the libFuzzer runtime is written in C++ which
|
||||
# needs to link against the C++ runtime. Explicitly link it into cmark-fuzz
|
||||
set_target_properties(${FUZZ_HARNESS} PROPERTIES LINK_FLAGS "-lstdc++")
|
||||
endif()
|
||||
104
3rdparty/cmark-gfm/src/arena.c
vendored
Normal file
104
3rdparty/cmark-gfm/src/arena.c
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#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;
|
||||
}
|
||||
1622
3rdparty/cmark-gfm/src/blocks.c
vendored
Normal file
1622
3rdparty/cmark-gfm/src/blocks.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
278
3rdparty/cmark-gfm/src/buffer.c
vendored
Normal file
278
3rdparty/cmark-gfm/src/buffer.c
vendored
Normal file
@ -0,0 +1,278 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
116
3rdparty/cmark-gfm/src/buffer.h
vendored
Normal file
116
3rdparty/cmark-gfm/src/buffer.h
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
#ifndef CMARK_BUFFER_H
|
||||
#define CMARK_BUFFER_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#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
|
||||
4327
3rdparty/cmark-gfm/src/case_fold_switch.inc
vendored
Normal file
4327
3rdparty/cmark-gfm/src/case_fold_switch.inc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
135
3rdparty/cmark-gfm/src/chunk.h
vendored
Normal file
135
3rdparty/cmark-gfm/src/chunk.h
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
#ifndef CMARK_CHUNK_H
|
||||
#define CMARK_CHUNK_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#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
|
||||
7
3rdparty/cmark-gfm/src/cmark-gfm_version.h.in
vendored
Normal file
7
3rdparty/cmark-gfm/src/cmark-gfm_version.h.in
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef CMARK_GFM_VERSION_H
|
||||
#define CMARK_GFM_VERSION_H
|
||||
|
||||
#define CMARK_GFM_VERSION ((@PROJECT_VERSION_MAJOR@ << 24) | (@PROJECT_VERSION_MINOR@ << 16) | (@PROJECT_VERSION_PATCH@ << 8) | @PROJECT_VERSION_GFM@)
|
||||
#define CMARK_GFM_VERSION_STRING "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.gfm.@PROJECT_VERSION_GFM@"
|
||||
|
||||
#endif
|
||||
55
3rdparty/cmark-gfm/src/cmark.c
vendored
Normal file
55
3rdparty/cmark-gfm/src/cmark.c
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#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;
|
||||
}
|
||||
44
3rdparty/cmark-gfm/src/cmark_ctype.c
vendored
Normal file
44
3rdparty/cmark-gfm/src/cmark_ctype.c
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#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; }
|
||||
33
3rdparty/cmark-gfm/src/cmark_ctype.h
vendored
Normal file
33
3rdparty/cmark-gfm/src/cmark_ctype.h
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user