diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 392772b..1a6d0dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@v6 @@ -57,12 +57,12 @@ jobs: python-version: "3.12" - name: Install cibuildwheel - run: pip install cibuildwheel==2.21.0 + run: pip install cibuildwheel==2.23.4 - name: Build wheels run: python -m cibuildwheel --output-dir wheelhouse env: - CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-*" + CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-* cp314-*" CIBW_SKIP: "*-win32 *-manylinux_i686 *-musllinux_i686" CIBW_ARCHS_MACOS: "x86_64 arm64" CIBW_ARCHS_LINUX: "x86_64" @@ -75,6 +75,26 @@ jobs: name: wheels-${{ matrix.os }} path: ./wheelhouse/*.whl + build_pyodide: + name: Build Pyodide wheel + runs-on: ubuntu-latest + needs: test + if: github.event_name == 'release' + + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - uses: pypa/cibuildwheel@v3.4.0 + env: + CIBW_PLATFORM: pyodide + + - uses: actions/upload-artifact@v4 + with: + name: wheels-pyodide + path: wheelhouse/*.whl + build_sdist: name: Build source distribution runs-on: ubuntu-latest @@ -100,7 +120,7 @@ jobs: publish: name: Publish to PyPI - needs: [build_wheels, build_sdist] + needs: [build_wheels, build_pyodide, build_sdist] runs-on: ubuntu-latest if: github.event_name == 'release' steps: diff --git a/Makefile b/Makefile index dae3ca5..e5cc6cf 100644 --- a/Makefile +++ b/Makefile @@ -29,3 +29,9 @@ clean-test: ## remove test and coverage artifacts dist: clean ## builds source and wheel package python3 -m build ls -l dist + +.PHONY: dist-pyodide +dist-pyodide: clean ## builds Pyodide/emscripten wheel (requires Linux or macOS) + pip install pyodide-build + pyodide build --outdir dist + ls -l dist diff --git a/multimark/_binding.c b/multimark/_binding.c new file mode 100644 index 0000000..241d7fd --- /dev/null +++ b/multimark/_binding.c @@ -0,0 +1,3660 @@ +#define _CFFI_ + +/* We try to define Py_LIMITED_API before including Python.h. + + Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and + Py_REF_DEBUG are not defined. This is a best-effort approximation: + we can learn about Py_DEBUG from pyconfig.h, but it is unclear if + the same works for the other two macros. Py_DEBUG implies them, + but not the other way around. + + The implementation is messy (issue #350): on Windows, with _MSC_VER, + we have to define Py_LIMITED_API even before including pyconfig.h. + In that case, we guess what pyconfig.h will do to the macros above, + and check our guess after the #include. + + Note that on Windows, with CPython 3.x, you need >= 3.5 and virtualenv + version >= 16.0.0. With older versions of either, you don't get a + copy of PYTHON3.DLL in the virtualenv. We can't check the version of + CPython *before* we even include pyconfig.h. ffi.set_source() puts + a ``#define _CFFI_NO_LIMITED_API'' at the start of this file if it is + running on Windows < 3.5, as an attempt at fixing it, but that's + arguably wrong because it may not be the target version of Python. + Still better than nothing I guess. As another workaround, you can + remove the definition of Py_LIMITED_API here. + + See also 'py_limited_api' in cffi/setuptools_ext.py. +*/ +#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API) +# ifdef _MSC_VER +# if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API) +# define Py_LIMITED_API +# endif +# include + /* sanity-check: Py_LIMITED_API will cause crashes if any of these + are also defined. Normally, the Python file PC/pyconfig.h does not + cause any of these to be defined, with the exception that _DEBUG + causes Py_DEBUG. Double-check that. */ +# ifdef Py_LIMITED_API +# if defined(Py_DEBUG) +# error "pyconfig.h unexpectedly defines Py_DEBUG, but Py_LIMITED_API is set" +# endif +# if defined(Py_TRACE_REFS) +# error "pyconfig.h unexpectedly defines Py_TRACE_REFS, but Py_LIMITED_API is set" +# endif +# if defined(Py_REF_DEBUG) +# error "pyconfig.h unexpectedly defines Py_REF_DEBUG, but Py_LIMITED_API is set" +# endif +# endif +# else +# include +# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API) +# define Py_LIMITED_API +# endif +# endif +#endif + +#include +#ifdef __cplusplus +extern "C" { +#endif +#include + +/* This part is from file 'cffi/parse_c_type.h'. It is copied at the + beginning of C sources generated by CFFI's ffi.set_source(). */ + +typedef void *_cffi_opcode_t; + +#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8)) +#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode) +#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8) + +#define _CFFI_OP_PRIMITIVE 1 +#define _CFFI_OP_POINTER 3 +#define _CFFI_OP_ARRAY 5 +#define _CFFI_OP_OPEN_ARRAY 7 +#define _CFFI_OP_STRUCT_UNION 9 +#define _CFFI_OP_ENUM 11 +#define _CFFI_OP_FUNCTION 13 +#define _CFFI_OP_FUNCTION_END 15 +#define _CFFI_OP_NOOP 17 +#define _CFFI_OP_BITFIELD 19 +#define _CFFI_OP_TYPENAME 21 +#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs +#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs +#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg) +#define _CFFI_OP_CONSTANT 29 +#define _CFFI_OP_CONSTANT_INT 31 +#define _CFFI_OP_GLOBAL_VAR 33 +#define _CFFI_OP_DLOPEN_FUNC 35 +#define _CFFI_OP_DLOPEN_CONST 37 +#define _CFFI_OP_GLOBAL_VAR_F 39 +#define _CFFI_OP_EXTERN_PYTHON 41 + +#define _CFFI_PRIM_VOID 0 +#define _CFFI_PRIM_BOOL 1 +#define _CFFI_PRIM_CHAR 2 +#define _CFFI_PRIM_SCHAR 3 +#define _CFFI_PRIM_UCHAR 4 +#define _CFFI_PRIM_SHORT 5 +#define _CFFI_PRIM_USHORT 6 +#define _CFFI_PRIM_INT 7 +#define _CFFI_PRIM_UINT 8 +#define _CFFI_PRIM_LONG 9 +#define _CFFI_PRIM_ULONG 10 +#define _CFFI_PRIM_LONGLONG 11 +#define _CFFI_PRIM_ULONGLONG 12 +#define _CFFI_PRIM_FLOAT 13 +#define _CFFI_PRIM_DOUBLE 14 +#define _CFFI_PRIM_LONGDOUBLE 15 + +#define _CFFI_PRIM_WCHAR 16 +#define _CFFI_PRIM_INT8 17 +#define _CFFI_PRIM_UINT8 18 +#define _CFFI_PRIM_INT16 19 +#define _CFFI_PRIM_UINT16 20 +#define _CFFI_PRIM_INT32 21 +#define _CFFI_PRIM_UINT32 22 +#define _CFFI_PRIM_INT64 23 +#define _CFFI_PRIM_UINT64 24 +#define _CFFI_PRIM_INTPTR 25 +#define _CFFI_PRIM_UINTPTR 26 +#define _CFFI_PRIM_PTRDIFF 27 +#define _CFFI_PRIM_SIZE 28 +#define _CFFI_PRIM_SSIZE 29 +#define _CFFI_PRIM_INT_LEAST8 30 +#define _CFFI_PRIM_UINT_LEAST8 31 +#define _CFFI_PRIM_INT_LEAST16 32 +#define _CFFI_PRIM_UINT_LEAST16 33 +#define _CFFI_PRIM_INT_LEAST32 34 +#define _CFFI_PRIM_UINT_LEAST32 35 +#define _CFFI_PRIM_INT_LEAST64 36 +#define _CFFI_PRIM_UINT_LEAST64 37 +#define _CFFI_PRIM_INT_FAST8 38 +#define _CFFI_PRIM_UINT_FAST8 39 +#define _CFFI_PRIM_INT_FAST16 40 +#define _CFFI_PRIM_UINT_FAST16 41 +#define _CFFI_PRIM_INT_FAST32 42 +#define _CFFI_PRIM_UINT_FAST32 43 +#define _CFFI_PRIM_INT_FAST64 44 +#define _CFFI_PRIM_UINT_FAST64 45 +#define _CFFI_PRIM_INTMAX 46 +#define _CFFI_PRIM_UINTMAX 47 +#define _CFFI_PRIM_FLOATCOMPLEX 48 +#define _CFFI_PRIM_DOUBLECOMPLEX 49 +#define _CFFI_PRIM_CHAR16 50 +#define _CFFI_PRIM_CHAR32 51 + +#define _CFFI__NUM_PRIM 52 +#define _CFFI__UNKNOWN_PRIM (-1) +#define _CFFI__UNKNOWN_FLOAT_PRIM (-2) +#define _CFFI__UNKNOWN_LONG_DOUBLE (-3) + +#define _CFFI__IO_FILE_STRUCT (-1) + + +struct _cffi_global_s { + const char *name; + void *address; + _cffi_opcode_t type_op; + void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown + // OP_CPYTHON_BLTN_*: addr of direct function +}; + +struct _cffi_getconst_s { + unsigned long long value; + const struct _cffi_type_context_s *ctx; + int gindex; +}; + +struct _cffi_struct_union_s { + const char *name; + int type_index; // -> _cffi_types, on a OP_STRUCT_UNION + int flags; // _CFFI_F_* flags below + size_t size; + int alignment; + int first_field_index; // -> _cffi_fields array + int num_fields; +}; +#define _CFFI_F_UNION 0x01 // is a union, not a struct +#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the + // "standard layout" or if some are missing +#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct +#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include() +#define _CFFI_F_OPAQUE 0x10 // opaque + +struct _cffi_field_s { + const char *name; + size_t field_offset; + size_t field_size; + _cffi_opcode_t field_type_op; +}; + +struct _cffi_enum_s { + const char *name; + int type_index; // -> _cffi_types, on a OP_ENUM + int type_prim; // _CFFI_PRIM_xxx + const char *enumerators; // comma-delimited string +}; + +struct _cffi_typename_s { + const char *name; + int type_index; /* if opaque, points to a possibly artificial + OP_STRUCT which is itself opaque */ +}; + +struct _cffi_type_context_s { + _cffi_opcode_t *types; + const struct _cffi_global_s *globals; + const struct _cffi_field_s *fields; + const struct _cffi_struct_union_s *struct_unions; + const struct _cffi_enum_s *enums; + const struct _cffi_typename_s *typenames; + int num_globals; + int num_struct_unions; + int num_enums; + int num_typenames; + const char *const *includes; + int num_types; + int flags; /* future extension */ +}; + +struct _cffi_parse_info_s { + const struct _cffi_type_context_s *ctx; + _cffi_opcode_t *output; + unsigned int output_size; + size_t error_location; + const char *error_message; +}; + +struct _cffi_externpy_s { + const char *name; + size_t size_of_result; + void *reserved1, *reserved2; +}; + +#ifdef _CFFI_INTERNAL +static int parse_c_type(struct _cffi_parse_info_s *info, const char *input); +static int search_in_globals(const struct _cffi_type_context_s *ctx, + const char *search, size_t search_len); +static int search_in_struct_unions(const struct _cffi_type_context_s *ctx, + const char *search, size_t search_len); +#endif + +/* this block of #ifs should be kept exactly identical between + c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py + and cffi/_cffi_include.h */ +#if defined(_MSC_VER) +# include /* for alloca() */ +# if _MSC_VER < 1600 /* MSVC < 2010 */ + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; +# else +# include +# endif +# if _MSC_VER < 1800 /* MSVC < 2013 */ +# ifndef __cplusplus + typedef unsigned char _Bool; +# endif +# endif +#else +# include +# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) +# include +# endif +#endif + +#ifdef __GNUC__ +# define _CFFI_UNUSED_FN __attribute__((unused)) +#else +# define _CFFI_UNUSED_FN /* nothing */ +#endif + +#ifdef __cplusplus +# ifndef _Bool + typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */ +# endif +#endif + +/********** CPython-specific section **********/ +#ifndef PYPY_VERSION + + +#if PY_MAJOR_VERSION >= 3 +# define PyInt_FromLong PyLong_FromLong +#endif + +#define _cffi_from_c_double PyFloat_FromDouble +#define _cffi_from_c_float PyFloat_FromDouble +#define _cffi_from_c_long PyInt_FromLong +#define _cffi_from_c_ulong PyLong_FromUnsignedLong +#define _cffi_from_c_longlong PyLong_FromLongLong +#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong +#define _cffi_from_c__Bool PyBool_FromLong + +#define _cffi_to_c_double PyFloat_AsDouble +#define _cffi_to_c_float PyFloat_AsDouble + +#define _cffi_from_c_int(x, type) \ + (((type)-1) > 0 ? /* unsigned */ \ + (sizeof(type) < sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + sizeof(type) == sizeof(long) ? \ + PyLong_FromUnsignedLong((unsigned long)x) : \ + PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ + (sizeof(type) <= sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + PyLong_FromLongLong((long long)x))) + +#define _cffi_to_c_int(o, type) \ + ((type)( \ + sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ + : (type)_cffi_to_c_i8(o)) : \ + sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ + : (type)_cffi_to_c_i16(o)) : \ + sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ + : (type)_cffi_to_c_i32(o)) : \ + sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ + : (type)_cffi_to_c_i64(o)) : \ + (Py_FatalError("unsupported size for type " #type), (type)0))) + +#define _cffi_to_c_i8 \ + ((int(*)(PyObject *))_cffi_exports[1]) +#define _cffi_to_c_u8 \ + ((int(*)(PyObject *))_cffi_exports[2]) +#define _cffi_to_c_i16 \ + ((int(*)(PyObject *))_cffi_exports[3]) +#define _cffi_to_c_u16 \ + ((int(*)(PyObject *))_cffi_exports[4]) +#define _cffi_to_c_i32 \ + ((int(*)(PyObject *))_cffi_exports[5]) +#define _cffi_to_c_u32 \ + ((unsigned int(*)(PyObject *))_cffi_exports[6]) +#define _cffi_to_c_i64 \ + ((long long(*)(PyObject *))_cffi_exports[7]) +#define _cffi_to_c_u64 \ + ((unsigned long long(*)(PyObject *))_cffi_exports[8]) +#define _cffi_to_c_char \ + ((int(*)(PyObject *))_cffi_exports[9]) +#define _cffi_from_c_pointer \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[10]) +#define _cffi_to_c_pointer \ + ((char *(*)(PyObject *, struct _cffi_ctypedescr *))_cffi_exports[11]) +#define _cffi_get_struct_layout \ + not used any more +#define _cffi_restore_errno \ + ((void(*)(void))_cffi_exports[13]) +#define _cffi_save_errno \ + ((void(*)(void))_cffi_exports[14]) +#define _cffi_from_c_char \ + ((PyObject *(*)(char))_cffi_exports[15]) +#define _cffi_from_c_deref \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[16]) +#define _cffi_to_c \ + ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[17]) +#define _cffi_from_c_struct \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[18]) +#define _cffi_to_c_wchar_t \ + ((_cffi_wchar_t(*)(PyObject *))_cffi_exports[19]) +#define _cffi_from_c_wchar_t \ + ((PyObject *(*)(_cffi_wchar_t))_cffi_exports[20]) +#define _cffi_to_c_long_double \ + ((long double(*)(PyObject *))_cffi_exports[21]) +#define _cffi_to_c__Bool \ + ((_Bool(*)(PyObject *))_cffi_exports[22]) +#define _cffi_prepare_pointer_call_argument \ + ((Py_ssize_t(*)(struct _cffi_ctypedescr *, \ + PyObject *, char **))_cffi_exports[23]) +#define _cffi_convert_array_from_object \ + ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[24]) +#define _CFFI_CPIDX 25 +#define _cffi_call_python \ + ((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[_CFFI_CPIDX]) +#define _cffi_to_c_wchar3216_t \ + ((int(*)(PyObject *))_cffi_exports[26]) +#define _cffi_from_c_wchar3216_t \ + ((PyObject *(*)(int))_cffi_exports[27]) +#define _CFFI_NUM_EXPORTS 28 + +struct _cffi_ctypedescr; + +static void *_cffi_exports[_CFFI_NUM_EXPORTS]; + +#define _cffi_type(index) ( \ + assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ + (struct _cffi_ctypedescr *)_cffi_types[index]) + +static PyObject *_cffi_init(const char *module_name, Py_ssize_t version, + const struct _cffi_type_context_s *ctx) +{ + PyObject *module, *o_arg, *new_module; + void *raw[] = { + (void *)module_name, + (void *)version, + (void *)_cffi_exports, + (void *)ctx, + }; + + module = PyImport_ImportModule("_cffi_backend"); + if (module == NULL) + goto failure; + + o_arg = PyLong_FromVoidPtr((void *)raw); + if (o_arg == NULL) + goto failure; + + new_module = PyObject_CallMethod( + module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg); + + Py_DECREF(o_arg); + Py_DECREF(module); + return new_module; + + failure: + Py_XDECREF(module); + return NULL; +} + + +#ifdef HAVE_WCHAR_H +typedef wchar_t _cffi_wchar_t; +#else +typedef uint16_t _cffi_wchar_t; /* same random pick as _cffi_backend.c */ +#endif + +_CFFI_UNUSED_FN static uint16_t _cffi_to_c_char16_t(PyObject *o) +{ + if (sizeof(_cffi_wchar_t) == 2) + return (uint16_t)_cffi_to_c_wchar_t(o); + else + return (uint16_t)_cffi_to_c_wchar3216_t(o); +} + +_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x) +{ + if (sizeof(_cffi_wchar_t) == 2) + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); + else + return _cffi_from_c_wchar3216_t((int)x); +} + +_CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o) +{ + if (sizeof(_cffi_wchar_t) == 4) + return (int)_cffi_to_c_wchar_t(o); + else + return (int)_cffi_to_c_wchar3216_t(o); +} + +_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(unsigned int x) +{ + if (sizeof(_cffi_wchar_t) == 4) + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); + else + return _cffi_from_c_wchar3216_t((int)x); +} + +union _cffi_union_alignment_u { + unsigned char m_char; + unsigned short m_short; + unsigned int m_int; + unsigned long m_long; + unsigned long long m_longlong; + float m_float; + double m_double; + long double m_longdouble; +}; + +struct _cffi_freeme_s { + struct _cffi_freeme_s *next; + union _cffi_union_alignment_u alignment; +}; + +_CFFI_UNUSED_FN static int +_cffi_convert_array_argument(struct _cffi_ctypedescr *ctptr, PyObject *arg, + char **output_data, Py_ssize_t datasize, + struct _cffi_freeme_s **freeme) +{ + char *p; + if (datasize < 0) + return -1; + + p = *output_data; + if (p == NULL) { + struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( + offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); + if (fp == NULL) + return -1; + fp->next = *freeme; + *freeme = fp; + p = *output_data = (char *)&fp->alignment; + } + memset((void *)p, 0, (size_t)datasize); + return _cffi_convert_array_from_object(p, ctptr, arg); +} + +_CFFI_UNUSED_FN static void +_cffi_free_array_arguments(struct _cffi_freeme_s *freeme) +{ + do { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } while (freeme != NULL); +} + +/********** end CPython-specific section **********/ +#else +_CFFI_UNUSED_FN +static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); +# define _cffi_call_python _cffi_call_python_org +#endif + + +#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0])) + +#define _cffi_prim_int(size, sign) \ + ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \ + (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \ + (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \ + (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ + _CFFI__UNKNOWN_PRIM) + +#define _cffi_prim_float(size) \ + ((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \ + (size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \ + (size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \ + _CFFI__UNKNOWN_FLOAT_PRIM) + +#define _cffi_check_int(got, got_nonpos, expected) \ + ((got_nonpos) == (expected <= 0) && \ + (got) == (unsigned long long)expected) + +#ifdef MS_WIN32 +# define _cffi_stdcall __stdcall +#else +# define _cffi_stdcall /* nothing */ +#endif + +#ifdef __cplusplus +} +#endif + +/************************************************************/ + + + #include "cmark-gfm.h" + #include "cmark-gfm-core-extensions.h" + + +/************************************************************/ + +static void *_cffi_types[] = { +/* 0 */ _CFFI_OP(_CFFI_OP_FUNCTION, 102), // char *()(cmark_node *, int) +/* 1 */ _CFFI_OP(_CFFI_OP_POINTER, 108), // cmark_node * +/* 2 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), // int +/* 3 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 4 */ _CFFI_OP(_CFFI_OP_FUNCTION, 102), // char *()(cmark_node *, int, cmark_llist *) +/* 5 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 6 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), +/* 7 */ _CFFI_OP(_CFFI_OP_POINTER, 107), // cmark_llist * +/* 8 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 9 */ _CFFI_OP(_CFFI_OP_FUNCTION, 102), // char *()(cmark_node *, int, int) +/* 10 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 11 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), +/* 12 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), +/* 13 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 14 */ _CFFI_OP(_CFFI_OP_FUNCTION, 35), // char const *()(cmark_node *) +/* 15 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 16 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 17 */ _CFFI_OP(_CFFI_OP_FUNCTION, 35), // char const *()(void) +/* 18 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 19 */ _CFFI_OP(_CFFI_OP_FUNCTION, 104), // cmark_delim_type()(cmark_node *) +/* 20 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 21 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 22 */ _CFFI_OP(_CFFI_OP_FUNCTION, 105), // cmark_event_type()(cmark_iter *) +/* 23 */ _CFFI_OP(_CFFI_OP_POINTER, 106), // cmark_iter * +/* 24 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 25 */ _CFFI_OP(_CFFI_OP_FUNCTION, 23), // cmark_iter *()(cmark_node *) +/* 26 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 27 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 28 */ _CFFI_OP(_CFFI_OP_FUNCTION, 69), // cmark_list_type()(cmark_node *) +/* 29 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 30 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 31 */ _CFFI_OP(_CFFI_OP_FUNCTION, 7), // cmark_llist *()(cmark_parser *) +/* 32 */ _CFFI_OP(_CFFI_OP_POINTER, 109), // cmark_parser * +/* 33 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 34 */ _CFFI_OP(_CFFI_OP_FUNCTION, 1), // cmark_node *()(char const *, size_t, int) +/* 35 */ _CFFI_OP(_CFFI_OP_POINTER, 103), // char const * +/* 36 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 28), // size_t +/* 37 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), +/* 38 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 39 */ _CFFI_OP(_CFFI_OP_FUNCTION, 1), // cmark_node *()(cmark_iter *) +/* 40 */ _CFFI_OP(_CFFI_OP_NOOP, 23), +/* 41 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 42 */ _CFFI_OP(_CFFI_OP_FUNCTION, 1), // cmark_node *()(cmark_node *) +/* 43 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 44 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 45 */ _CFFI_OP(_CFFI_OP_FUNCTION, 1), // cmark_node *()(cmark_node_type) +/* 46 */ _CFFI_OP(_CFFI_OP_ENUM, 3), // cmark_node_type +/* 47 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 48 */ _CFFI_OP(_CFFI_OP_FUNCTION, 1), // cmark_node *()(cmark_parser *) +/* 49 */ _CFFI_OP(_CFFI_OP_NOOP, 32), +/* 50 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 51 */ _CFFI_OP(_CFFI_OP_FUNCTION, 46), // cmark_node_type()(cmark_node *) +/* 52 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 53 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 54 */ _CFFI_OP(_CFFI_OP_FUNCTION, 32), // cmark_parser *()(int) +/* 55 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), +/* 56 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 57 */ _CFFI_OP(_CFFI_OP_FUNCTION, 81), // cmark_syntax_extension *()(char const *) +/* 58 */ _CFFI_OP(_CFFI_OP_NOOP, 35), +/* 59 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 60 */ _CFFI_OP(_CFFI_OP_FUNCTION, 2), // int()(cmark_node *) +/* 61 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 62 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 63 */ _CFFI_OP(_CFFI_OP_FUNCTION, 2), // int()(cmark_node *, char const *) +/* 64 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 65 */ _CFFI_OP(_CFFI_OP_NOOP, 35), +/* 66 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 67 */ _CFFI_OP(_CFFI_OP_FUNCTION, 2), // int()(cmark_node *, cmark_list_type) +/* 68 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 69 */ _CFFI_OP(_CFFI_OP_ENUM, 2), // cmark_list_type +/* 70 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 71 */ _CFFI_OP(_CFFI_OP_FUNCTION, 2), // int()(cmark_node *, cmark_node *) +/* 72 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 73 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 74 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 75 */ _CFFI_OP(_CFFI_OP_FUNCTION, 2), // int()(cmark_node *, int) +/* 76 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 77 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 7), +/* 78 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 79 */ _CFFI_OP(_CFFI_OP_FUNCTION, 2), // int()(cmark_parser *, cmark_syntax_extension *) +/* 80 */ _CFFI_OP(_CFFI_OP_NOOP, 32), +/* 81 */ _CFFI_OP(_CFFI_OP_POINTER, 110), // cmark_syntax_extension * +/* 82 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 83 */ _CFFI_OP(_CFFI_OP_FUNCTION, 111), // void()(cmark_iter *) +/* 84 */ _CFFI_OP(_CFFI_OP_NOOP, 23), +/* 85 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 86 */ _CFFI_OP(_CFFI_OP_FUNCTION, 111), // void()(cmark_node *) +/* 87 */ _CFFI_OP(_CFFI_OP_NOOP, 1), +/* 88 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 89 */ _CFFI_OP(_CFFI_OP_FUNCTION, 111), // void()(cmark_parser *) +/* 90 */ _CFFI_OP(_CFFI_OP_NOOP, 32), +/* 91 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 92 */ _CFFI_OP(_CFFI_OP_FUNCTION, 111), // void()(cmark_parser *, char const *, size_t) +/* 93 */ _CFFI_OP(_CFFI_OP_NOOP, 32), +/* 94 */ _CFFI_OP(_CFFI_OP_NOOP, 35), +/* 95 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 28), +/* 96 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 97 */ _CFFI_OP(_CFFI_OP_FUNCTION, 111), // void()(void *) +/* 98 */ _CFFI_OP(_CFFI_OP_POINTER, 111), // void * +/* 99 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 100 */ _CFFI_OP(_CFFI_OP_FUNCTION, 111), // void()(void) +/* 101 */ _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), +/* 102 */ _CFFI_OP(_CFFI_OP_POINTER, 103), // char * +/* 103 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 2), // char +/* 104 */ _CFFI_OP(_CFFI_OP_ENUM, 0), // cmark_delim_type +/* 105 */ _CFFI_OP(_CFFI_OP_ENUM, 1), // cmark_event_type +/* 106 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 1), // cmark_iter +/* 107 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 0), // cmark_llist +/* 108 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 2), // cmark_node +/* 109 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 3), // cmark_parser +/* 110 */ _CFFI_OP(_CFFI_OP_STRUCT_UNION, 4), // cmark_syntax_extension +/* 111 */ _CFFI_OP(_CFFI_OP_PRIMITIVE, 0), // void +}; + +static int _cffi_const_CMARK_NO_DELIM(unsigned long long *o) +{ + int n = (CMARK_NO_DELIM) <= 0; + *o = (unsigned long long)((CMARK_NO_DELIM) | 0); /* check that CMARK_NO_DELIM is an integer */ + return n; +} + +static int _cffi_const_CMARK_PERIOD_DELIM(unsigned long long *o) +{ + int n = (CMARK_PERIOD_DELIM) <= 0; + *o = (unsigned long long)((CMARK_PERIOD_DELIM) | 0); /* check that CMARK_PERIOD_DELIM is an integer */ + return n; +} + +static int _cffi_const_CMARK_PAREN_DELIM(unsigned long long *o) +{ + int n = (CMARK_PAREN_DELIM) <= 0; + *o = (unsigned long long)((CMARK_PAREN_DELIM) | 0); /* check that CMARK_PAREN_DELIM is an integer */ + return n; +} + +static int _cffi_const_CMARK_EVENT_NONE(unsigned long long *o) +{ + int n = (CMARK_EVENT_NONE) <= 0; + *o = (unsigned long long)((CMARK_EVENT_NONE) | 0); /* check that CMARK_EVENT_NONE is an integer */ + return n; +} + +static int _cffi_const_CMARK_EVENT_DONE(unsigned long long *o) +{ + int n = (CMARK_EVENT_DONE) <= 0; + *o = (unsigned long long)((CMARK_EVENT_DONE) | 0); /* check that CMARK_EVENT_DONE is an integer */ + return n; +} + +static int _cffi_const_CMARK_EVENT_ENTER(unsigned long long *o) +{ + int n = (CMARK_EVENT_ENTER) <= 0; + *o = (unsigned long long)((CMARK_EVENT_ENTER) | 0); /* check that CMARK_EVENT_ENTER is an integer */ + return n; +} + +static int _cffi_const_CMARK_EVENT_EXIT(unsigned long long *o) +{ + int n = (CMARK_EVENT_EXIT) <= 0; + *o = (unsigned long long)((CMARK_EVENT_EXIT) | 0); /* check that CMARK_EVENT_EXIT is an integer */ + return n; +} + +static int _cffi_const_CMARK_NO_LIST(unsigned long long *o) +{ + int n = (CMARK_NO_LIST) <= 0; + *o = (unsigned long long)((CMARK_NO_LIST) | 0); /* check that CMARK_NO_LIST is an integer */ + return n; +} + +static int _cffi_const_CMARK_BULLET_LIST(unsigned long long *o) +{ + int n = (CMARK_BULLET_LIST) <= 0; + *o = (unsigned long long)((CMARK_BULLET_LIST) | 0); /* check that CMARK_BULLET_LIST is an integer */ + return n; +} + +static int _cffi_const_CMARK_ORDERED_LIST(unsigned long long *o) +{ + int n = (CMARK_ORDERED_LIST) <= 0; + *o = (unsigned long long)((CMARK_ORDERED_LIST) | 0); /* check that CMARK_ORDERED_LIST is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_NONE(unsigned long long *o) +{ + int n = (CMARK_NODE_NONE) <= 0; + *o = (unsigned long long)((CMARK_NODE_NONE) | 0); /* check that CMARK_NODE_NONE is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_DOCUMENT(unsigned long long *o) +{ + int n = (CMARK_NODE_DOCUMENT) <= 0; + *o = (unsigned long long)((CMARK_NODE_DOCUMENT) | 0); /* check that CMARK_NODE_DOCUMENT is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_BLOCK_QUOTE(unsigned long long *o) +{ + int n = (CMARK_NODE_BLOCK_QUOTE) <= 0; + *o = (unsigned long long)((CMARK_NODE_BLOCK_QUOTE) | 0); /* check that CMARK_NODE_BLOCK_QUOTE is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_LIST(unsigned long long *o) +{ + int n = (CMARK_NODE_LIST) <= 0; + *o = (unsigned long long)((CMARK_NODE_LIST) | 0); /* check that CMARK_NODE_LIST is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_ITEM(unsigned long long *o) +{ + int n = (CMARK_NODE_ITEM) <= 0; + *o = (unsigned long long)((CMARK_NODE_ITEM) | 0); /* check that CMARK_NODE_ITEM is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_CODE_BLOCK(unsigned long long *o) +{ + int n = (CMARK_NODE_CODE_BLOCK) <= 0; + *o = (unsigned long long)((CMARK_NODE_CODE_BLOCK) | 0); /* check that CMARK_NODE_CODE_BLOCK is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_HTML_BLOCK(unsigned long long *o) +{ + int n = (CMARK_NODE_HTML_BLOCK) <= 0; + *o = (unsigned long long)((CMARK_NODE_HTML_BLOCK) | 0); /* check that CMARK_NODE_HTML_BLOCK is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_CUSTOM_BLOCK(unsigned long long *o) +{ + int n = (CMARK_NODE_CUSTOM_BLOCK) <= 0; + *o = (unsigned long long)((CMARK_NODE_CUSTOM_BLOCK) | 0); /* check that CMARK_NODE_CUSTOM_BLOCK is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_PARAGRAPH(unsigned long long *o) +{ + int n = (CMARK_NODE_PARAGRAPH) <= 0; + *o = (unsigned long long)((CMARK_NODE_PARAGRAPH) | 0); /* check that CMARK_NODE_PARAGRAPH is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_HEADING(unsigned long long *o) +{ + int n = (CMARK_NODE_HEADING) <= 0; + *o = (unsigned long long)((CMARK_NODE_HEADING) | 0); /* check that CMARK_NODE_HEADING is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_THEMATIC_BREAK(unsigned long long *o) +{ + int n = (CMARK_NODE_THEMATIC_BREAK) <= 0; + *o = (unsigned long long)((CMARK_NODE_THEMATIC_BREAK) | 0); /* check that CMARK_NODE_THEMATIC_BREAK is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_FOOTNOTE_DEFINITION(unsigned long long *o) +{ + int n = (CMARK_NODE_FOOTNOTE_DEFINITION) <= 0; + *o = (unsigned long long)((CMARK_NODE_FOOTNOTE_DEFINITION) | 0); /* check that CMARK_NODE_FOOTNOTE_DEFINITION is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_TEXT(unsigned long long *o) +{ + int n = (CMARK_NODE_TEXT) <= 0; + *o = (unsigned long long)((CMARK_NODE_TEXT) | 0); /* check that CMARK_NODE_TEXT is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_SOFTBREAK(unsigned long long *o) +{ + int n = (CMARK_NODE_SOFTBREAK) <= 0; + *o = (unsigned long long)((CMARK_NODE_SOFTBREAK) | 0); /* check that CMARK_NODE_SOFTBREAK is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_LINEBREAK(unsigned long long *o) +{ + int n = (CMARK_NODE_LINEBREAK) <= 0; + *o = (unsigned long long)((CMARK_NODE_LINEBREAK) | 0); /* check that CMARK_NODE_LINEBREAK is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_CODE(unsigned long long *o) +{ + int n = (CMARK_NODE_CODE) <= 0; + *o = (unsigned long long)((CMARK_NODE_CODE) | 0); /* check that CMARK_NODE_CODE is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_HTML_INLINE(unsigned long long *o) +{ + int n = (CMARK_NODE_HTML_INLINE) <= 0; + *o = (unsigned long long)((CMARK_NODE_HTML_INLINE) | 0); /* check that CMARK_NODE_HTML_INLINE is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_CUSTOM_INLINE(unsigned long long *o) +{ + int n = (CMARK_NODE_CUSTOM_INLINE) <= 0; + *o = (unsigned long long)((CMARK_NODE_CUSTOM_INLINE) | 0); /* check that CMARK_NODE_CUSTOM_INLINE is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_EMPH(unsigned long long *o) +{ + int n = (CMARK_NODE_EMPH) <= 0; + *o = (unsigned long long)((CMARK_NODE_EMPH) | 0); /* check that CMARK_NODE_EMPH is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_STRONG(unsigned long long *o) +{ + int n = (CMARK_NODE_STRONG) <= 0; + *o = (unsigned long long)((CMARK_NODE_STRONG) | 0); /* check that CMARK_NODE_STRONG is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_LINK(unsigned long long *o) +{ + int n = (CMARK_NODE_LINK) <= 0; + *o = (unsigned long long)((CMARK_NODE_LINK) | 0); /* check that CMARK_NODE_LINK is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_IMAGE(unsigned long long *o) +{ + int n = (CMARK_NODE_IMAGE) <= 0; + *o = (unsigned long long)((CMARK_NODE_IMAGE) | 0); /* check that CMARK_NODE_IMAGE is an integer */ + return n; +} + +static int _cffi_const_CMARK_NODE_FOOTNOTE_REFERENCE(unsigned long long *o) +{ + int n = (CMARK_NODE_FOOTNOTE_REFERENCE) <= 0; + *o = (unsigned long long)((CMARK_NODE_FOOTNOTE_REFERENCE) | 0); /* check that CMARK_NODE_FOOTNOTE_REFERENCE is an integer */ + return n; +} + +static cmark_syntax_extension * _cffi_d_cmark_find_syntax_extension(char const * x0) +{ + return cmark_find_syntax_extension(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_find_syntax_extension(PyObject *self, PyObject *arg0) +{ + char const * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_syntax_extension * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(35), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (char const *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(35), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_find_syntax_extension(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(81)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_find_syntax_extension _cffi_d_cmark_find_syntax_extension +#endif + +static void _cffi_d_cmark_gfm_core_extensions_ensure_registered(void) +{ + cmark_gfm_core_extensions_ensure_registered(); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_gfm_core_extensions_ensure_registered(PyObject *self, PyObject *noarg) +{ + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { cmark_gfm_core_extensions_ensure_registered(); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + (void)noarg; /* unused */ + Py_INCREF(Py_None); + return Py_None; +} +#else +# define _cffi_f_cmark_gfm_core_extensions_ensure_registered _cffi_d_cmark_gfm_core_extensions_ensure_registered +#endif + +static void _cffi_d_cmark_iter_free(cmark_iter * x0) +{ + cmark_iter_free(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_iter_free(PyObject *self, PyObject *arg0) +{ + cmark_iter * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(23), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_iter *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(23), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { cmark_iter_free(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + Py_INCREF(Py_None); + return Py_None; +} +#else +# define _cffi_f_cmark_iter_free _cffi_d_cmark_iter_free +#endif + +static cmark_event_type _cffi_d_cmark_iter_get_event_type(cmark_iter * x0) +{ + return cmark_iter_get_event_type(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_iter_get_event_type(PyObject *self, PyObject *arg0) +{ + cmark_iter * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_event_type result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(23), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_iter *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(23), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_iter_get_event_type(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_deref((char *)&result, _cffi_type(105)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_iter_get_event_type _cffi_d_cmark_iter_get_event_type +#endif + +static cmark_node * _cffi_d_cmark_iter_get_node(cmark_iter * x0) +{ + return cmark_iter_get_node(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_iter_get_node(PyObject *self, PyObject *arg0) +{ + cmark_iter * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_node * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(23), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_iter *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(23), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_iter_get_node(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(1)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_iter_get_node _cffi_d_cmark_iter_get_node +#endif + +static cmark_iter * _cffi_d_cmark_iter_new(cmark_node * x0) +{ + return cmark_iter_new(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_iter_new(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_iter * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_iter_new(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(23)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_iter_new _cffi_d_cmark_iter_new +#endif + +static cmark_event_type _cffi_d_cmark_iter_next(cmark_iter * x0) +{ + return cmark_iter_next(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_iter_next(PyObject *self, PyObject *arg0) +{ + cmark_iter * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_event_type result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(23), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_iter *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(23), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_iter_next(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_deref((char *)&result, _cffi_type(105)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_iter_next _cffi_d_cmark_iter_next +#endif + +static int _cffi_d_cmark_node_append_child(cmark_node * x0, cmark_node * x1) +{ + return cmark_node_append_child(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_append_child(PyObject *self, PyObject *args) +{ + cmark_node * x0; + cmark_node * x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_append_child", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_append_child(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_append_child _cffi_d_cmark_node_append_child +#endif + +static cmark_node * _cffi_d_cmark_node_first_child(cmark_node * x0) +{ + return cmark_node_first_child(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_first_child(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_node * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_first_child(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(1)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_first_child _cffi_d_cmark_node_first_child +#endif + +static void _cffi_d_cmark_node_free(cmark_node * x0) +{ + cmark_node_free(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_free(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { cmark_node_free(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + Py_INCREF(Py_None); + return Py_None; +} +#else +# define _cffi_f_cmark_node_free _cffi_d_cmark_node_free +#endif + +static int _cffi_d_cmark_node_get_end_column(cmark_node * x0) +{ + return cmark_node_get_end_column(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_end_column(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_end_column(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_end_column _cffi_d_cmark_node_get_end_column +#endif + +static int _cffi_d_cmark_node_get_end_line(cmark_node * x0) +{ + return cmark_node_get_end_line(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_end_line(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_end_line(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_end_line _cffi_d_cmark_node_get_end_line +#endif + +static char const * _cffi_d_cmark_node_get_fence_info(cmark_node * x0) +{ + return cmark_node_get_fence_info(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_fence_info(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + char const * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_fence_info(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(35)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_fence_info _cffi_d_cmark_node_get_fence_info +#endif + +static int _cffi_d_cmark_node_get_heading_level(cmark_node * x0) +{ + return cmark_node_get_heading_level(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_heading_level(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_heading_level(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_heading_level _cffi_d_cmark_node_get_heading_level +#endif + +static cmark_delim_type _cffi_d_cmark_node_get_list_delim(cmark_node * x0) +{ + return cmark_node_get_list_delim(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_list_delim(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_delim_type result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_list_delim(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_deref((char *)&result, _cffi_type(104)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_list_delim _cffi_d_cmark_node_get_list_delim +#endif + +static int _cffi_d_cmark_node_get_list_start(cmark_node * x0) +{ + return cmark_node_get_list_start(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_list_start(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_list_start(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_list_start _cffi_d_cmark_node_get_list_start +#endif + +static int _cffi_d_cmark_node_get_list_tight(cmark_node * x0) +{ + return cmark_node_get_list_tight(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_list_tight(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_list_tight(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_list_tight _cffi_d_cmark_node_get_list_tight +#endif + +static cmark_list_type _cffi_d_cmark_node_get_list_type(cmark_node * x0) +{ + return cmark_node_get_list_type(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_list_type(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_list_type result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_list_type(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_deref((char *)&result, _cffi_type(69)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_list_type _cffi_d_cmark_node_get_list_type +#endif + +static char const * _cffi_d_cmark_node_get_literal(cmark_node * x0) +{ + return cmark_node_get_literal(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_literal(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + char const * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_literal(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(35)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_literal _cffi_d_cmark_node_get_literal +#endif + +static int _cffi_d_cmark_node_get_start_column(cmark_node * x0) +{ + return cmark_node_get_start_column(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_start_column(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_start_column(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_start_column _cffi_d_cmark_node_get_start_column +#endif + +static int _cffi_d_cmark_node_get_start_line(cmark_node * x0) +{ + return cmark_node_get_start_line(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_start_line(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_start_line(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_start_line _cffi_d_cmark_node_get_start_line +#endif + +static char const * _cffi_d_cmark_node_get_title(cmark_node * x0) +{ + return cmark_node_get_title(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_title(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + char const * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_title(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(35)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_title _cffi_d_cmark_node_get_title +#endif + +static cmark_node_type _cffi_d_cmark_node_get_type(cmark_node * x0) +{ + return cmark_node_get_type(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_type(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_node_type result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_type(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_deref((char *)&result, _cffi_type(46)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_type _cffi_d_cmark_node_get_type +#endif + +static char const * _cffi_d_cmark_node_get_type_string(cmark_node * x0) +{ + return cmark_node_get_type_string(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_type_string(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + char const * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_type_string(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(35)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_type_string _cffi_d_cmark_node_get_type_string +#endif + +static char const * _cffi_d_cmark_node_get_url(cmark_node * x0) +{ + return cmark_node_get_url(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_get_url(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + char const * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_get_url(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(35)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_get_url _cffi_d_cmark_node_get_url +#endif + +static int _cffi_d_cmark_node_insert_after(cmark_node * x0, cmark_node * x1) +{ + return cmark_node_insert_after(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_insert_after(PyObject *self, PyObject *args) +{ + cmark_node * x0; + cmark_node * x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_insert_after", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_insert_after(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_insert_after _cffi_d_cmark_node_insert_after +#endif + +static int _cffi_d_cmark_node_insert_before(cmark_node * x0, cmark_node * x1) +{ + return cmark_node_insert_before(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_insert_before(PyObject *self, PyObject *args) +{ + cmark_node * x0; + cmark_node * x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_insert_before", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_insert_before(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_insert_before _cffi_d_cmark_node_insert_before +#endif + +static cmark_node * _cffi_d_cmark_node_last_child(cmark_node * x0) +{ + return cmark_node_last_child(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_last_child(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_node * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_last_child(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(1)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_last_child _cffi_d_cmark_node_last_child +#endif + +static cmark_node * _cffi_d_cmark_node_new(cmark_node_type x0) +{ + return cmark_node_new(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_new(PyObject *self, PyObject *arg0) +{ + cmark_node_type x0; + cmark_node * result; + PyObject *pyresult; + + if (_cffi_to_c((char *)&x0, _cffi_type(46), arg0) < 0) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_new(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(1)); + return pyresult; +} +#else +# define _cffi_f_cmark_node_new _cffi_d_cmark_node_new +#endif + +static cmark_node * _cffi_d_cmark_node_next(cmark_node * x0) +{ + return cmark_node_next(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_next(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_node * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_next(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(1)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_next _cffi_d_cmark_node_next +#endif + +static cmark_node * _cffi_d_cmark_node_parent(cmark_node * x0) +{ + return cmark_node_parent(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_parent(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_node * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_parent(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(1)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_parent _cffi_d_cmark_node_parent +#endif + +static int _cffi_d_cmark_node_prepend_child(cmark_node * x0, cmark_node * x1) +{ + return cmark_node_prepend_child(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_prepend_child(PyObject *self, PyObject *args) +{ + cmark_node * x0; + cmark_node * x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_prepend_child", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_prepend_child(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_prepend_child _cffi_d_cmark_node_prepend_child +#endif + +static cmark_node * _cffi_d_cmark_node_previous(cmark_node * x0) +{ + return cmark_node_previous(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_previous(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_node * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_previous(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(1)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_previous _cffi_d_cmark_node_previous +#endif + +static int _cffi_d_cmark_node_replace(cmark_node * x0, cmark_node * x1) +{ + return cmark_node_replace(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_replace(PyObject *self, PyObject *args) +{ + cmark_node * x0; + cmark_node * x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_replace", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_replace(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_replace _cffi_d_cmark_node_replace +#endif + +static int _cffi_d_cmark_node_set_fence_info(cmark_node * x0, char const * x1) +{ + return cmark_node_set_fence_info(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_set_fence_info(PyObject *self, PyObject *args) +{ + cmark_node * x0; + char const * x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_set_fence_info", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(35), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (char const *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(35), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_set_fence_info(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_set_fence_info _cffi_d_cmark_node_set_fence_info +#endif + +static int _cffi_d_cmark_node_set_heading_level(cmark_node * x0, int x1) +{ + return cmark_node_set_heading_level(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_set_heading_level(PyObject *self, PyObject *args) +{ + cmark_node * x0; + int x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_set_heading_level", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_set_heading_level(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_set_heading_level _cffi_d_cmark_node_set_heading_level +#endif + +static int _cffi_d_cmark_node_set_list_start(cmark_node * x0, int x1) +{ + return cmark_node_set_list_start(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_set_list_start(PyObject *self, PyObject *args) +{ + cmark_node * x0; + int x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_set_list_start", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_set_list_start(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_set_list_start _cffi_d_cmark_node_set_list_start +#endif + +static int _cffi_d_cmark_node_set_list_tight(cmark_node * x0, int x1) +{ + return cmark_node_set_list_tight(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_set_list_tight(PyObject *self, PyObject *args) +{ + cmark_node * x0; + int x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_set_list_tight", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_set_list_tight(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_set_list_tight _cffi_d_cmark_node_set_list_tight +#endif + +static int _cffi_d_cmark_node_set_list_type(cmark_node * x0, cmark_list_type x1) +{ + return cmark_node_set_list_type(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_set_list_type(PyObject *self, PyObject *args) +{ + cmark_node * x0; + cmark_list_type x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_set_list_type", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + if (_cffi_to_c((char *)&x1, _cffi_type(69), arg1) < 0) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_set_list_type(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_set_list_type _cffi_d_cmark_node_set_list_type +#endif + +static int _cffi_d_cmark_node_set_literal(cmark_node * x0, char const * x1) +{ + return cmark_node_set_literal(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_set_literal(PyObject *self, PyObject *args) +{ + cmark_node * x0; + char const * x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_set_literal", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(35), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (char const *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(35), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_set_literal(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_set_literal _cffi_d_cmark_node_set_literal +#endif + +static int _cffi_d_cmark_node_set_title(cmark_node * x0, char const * x1) +{ + return cmark_node_set_title(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_set_title(PyObject *self, PyObject *args) +{ + cmark_node * x0; + char const * x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_set_title", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(35), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (char const *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(35), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_set_title(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_set_title _cffi_d_cmark_node_set_title +#endif + +static int _cffi_d_cmark_node_set_url(cmark_node * x0, char const * x1) +{ + return cmark_node_set_url(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_set_url(PyObject *self, PyObject *args) +{ + cmark_node * x0; + char const * x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_node_set_url", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(35), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (char const *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(35), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_node_set_url(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_node_set_url _cffi_d_cmark_node_set_url +#endif + +static void _cffi_d_cmark_node_unlink(cmark_node * x0) +{ + cmark_node_unlink(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_node_unlink(PyObject *self, PyObject *arg0) +{ + cmark_node * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { cmark_node_unlink(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + Py_INCREF(Py_None); + return Py_None; +} +#else +# define _cffi_f_cmark_node_unlink _cffi_d_cmark_node_unlink +#endif + +static cmark_node * _cffi_d_cmark_parse_document(char const * x0, size_t x1, int x2) +{ + return cmark_parse_document(x0, x1, x2); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_parse_document(PyObject *self, PyObject *args) +{ + char const * x0; + size_t x1; + int x2; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_node * result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + PyObject *arg2; + + if (!PyArg_UnpackTuple(args, "cmark_parse_document", 3, 3, &arg0, &arg1, &arg2)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(35), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (char const *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(35), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, size_t); + if (x1 == (size_t)-1 && PyErr_Occurred()) + return NULL; + + x2 = _cffi_to_c_int(arg2, int); + if (x2 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_parse_document(x0, x1, x2); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(1)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_parse_document _cffi_d_cmark_parse_document +#endif + +static int _cffi_d_cmark_parser_attach_syntax_extension(cmark_parser * x0, cmark_syntax_extension * x1) +{ + return cmark_parser_attach_syntax_extension(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_parser_attach_syntax_extension(PyObject *self, PyObject *args) +{ + cmark_parser * x0; + cmark_syntax_extension * x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + int result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_parser_attach_syntax_extension", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(32), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_parser *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(32), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(81), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (cmark_syntax_extension *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(81), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_parser_attach_syntax_extension(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_int(result, int); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_parser_attach_syntax_extension _cffi_d_cmark_parser_attach_syntax_extension +#endif + +static void _cffi_d_cmark_parser_feed(cmark_parser * x0, char const * x1, size_t x2) +{ + cmark_parser_feed(x0, x1, x2); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_parser_feed(PyObject *self, PyObject *args) +{ + cmark_parser * x0; + char const * x1; + size_t x2; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + PyObject *arg0; + PyObject *arg1; + PyObject *arg2; + + if (!PyArg_UnpackTuple(args, "cmark_parser_feed", 3, 3, &arg0, &arg1, &arg2)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(32), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_parser *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(32), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(35), arg1, (char **)&x1); + if (datasize != 0) { + x1 = ((size_t)datasize) <= 640 ? (char const *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(35), arg1, (char **)&x1, + datasize, &large_args_free) < 0) + return NULL; + } + + x2 = _cffi_to_c_int(arg2, size_t); + if (x2 == (size_t)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { cmark_parser_feed(x0, x1, x2); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + Py_INCREF(Py_None); + return Py_None; +} +#else +# define _cffi_f_cmark_parser_feed _cffi_d_cmark_parser_feed +#endif + +static cmark_node * _cffi_d_cmark_parser_finish(cmark_parser * x0) +{ + return cmark_parser_finish(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_parser_finish(PyObject *self, PyObject *arg0) +{ + cmark_parser * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_node * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(32), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_parser *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(32), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_parser_finish(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(1)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_parser_finish _cffi_d_cmark_parser_finish +#endif + +static void _cffi_d_cmark_parser_free(cmark_parser * x0) +{ + cmark_parser_free(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_parser_free(PyObject *self, PyObject *arg0) +{ + cmark_parser * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(32), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_parser *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(32), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { cmark_parser_free(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + Py_INCREF(Py_None); + return Py_None; +} +#else +# define _cffi_f_cmark_parser_free _cffi_d_cmark_parser_free +#endif + +static cmark_llist * _cffi_d_cmark_parser_get_syntax_extensions(cmark_parser * x0) +{ + return cmark_parser_get_syntax_extensions(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_parser_get_syntax_extensions(PyObject *self, PyObject *arg0) +{ + cmark_parser * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + cmark_llist * result; + PyObject *pyresult; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(32), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_parser *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(32), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_parser_get_syntax_extensions(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(7)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_parser_get_syntax_extensions _cffi_d_cmark_parser_get_syntax_extensions +#endif + +static cmark_parser * _cffi_d_cmark_parser_new(int x0) +{ + return cmark_parser_new(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_parser_new(PyObject *self, PyObject *arg0) +{ + int x0; + cmark_parser * result; + PyObject *pyresult; + + x0 = _cffi_to_c_int(arg0, int); + if (x0 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_parser_new(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(32)); + return pyresult; +} +#else +# define _cffi_f_cmark_parser_new _cffi_d_cmark_parser_new +#endif + +static char * _cffi_d_cmark_render_commonmark(cmark_node * x0, int x1, int x2) +{ + return cmark_render_commonmark(x0, x1, x2); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_render_commonmark(PyObject *self, PyObject *args) +{ + cmark_node * x0; + int x1; + int x2; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + char * result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + PyObject *arg2; + + if (!PyArg_UnpackTuple(args, "cmark_render_commonmark", 3, 3, &arg0, &arg1, &arg2)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + x2 = _cffi_to_c_int(arg2, int); + if (x2 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_render_commonmark(x0, x1, x2); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(102)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_render_commonmark _cffi_d_cmark_render_commonmark +#endif + +static char * _cffi_d_cmark_render_html(cmark_node * x0, int x1, cmark_llist * x2) +{ + return cmark_render_html(x0, x1, x2); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_render_html(PyObject *self, PyObject *args) +{ + cmark_node * x0; + int x1; + cmark_llist * x2; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + char * result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + PyObject *arg2; + + if (!PyArg_UnpackTuple(args, "cmark_render_html", 3, 3, &arg0, &arg1, &arg2)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(7), arg2, (char **)&x2); + if (datasize != 0) { + x2 = ((size_t)datasize) <= 640 ? (cmark_llist *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(7), arg2, (char **)&x2, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_render_html(x0, x1, x2); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(102)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_render_html _cffi_d_cmark_render_html +#endif + +static char * _cffi_d_cmark_render_latex(cmark_node * x0, int x1, int x2) +{ + return cmark_render_latex(x0, x1, x2); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_render_latex(PyObject *self, PyObject *args) +{ + cmark_node * x0; + int x1; + int x2; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + char * result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + PyObject *arg2; + + if (!PyArg_UnpackTuple(args, "cmark_render_latex", 3, 3, &arg0, &arg1, &arg2)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + x2 = _cffi_to_c_int(arg2, int); + if (x2 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_render_latex(x0, x1, x2); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(102)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_render_latex _cffi_d_cmark_render_latex +#endif + +static char * _cffi_d_cmark_render_man(cmark_node * x0, int x1, int x2) +{ + return cmark_render_man(x0, x1, x2); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_render_man(PyObject *self, PyObject *args) +{ + cmark_node * x0; + int x1; + int x2; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + char * result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + PyObject *arg2; + + if (!PyArg_UnpackTuple(args, "cmark_render_man", 3, 3, &arg0, &arg1, &arg2)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + x2 = _cffi_to_c_int(arg2, int); + if (x2 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_render_man(x0, x1, x2); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(102)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_render_man _cffi_d_cmark_render_man +#endif + +static char * _cffi_d_cmark_render_xml(cmark_node * x0, int x1) +{ + return cmark_render_xml(x0, x1); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_render_xml(PyObject *self, PyObject *args) +{ + cmark_node * x0; + int x1; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + char * result; + PyObject *pyresult; + PyObject *arg0; + PyObject *arg1; + + if (!PyArg_UnpackTuple(args, "cmark_render_xml", 2, 2, &arg0, &arg1)) + return NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(1), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (cmark_node *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(1), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + x1 = _cffi_to_c_int(arg1, int); + if (x1 == (int)-1 && PyErr_Occurred()) + return NULL; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_render_xml(x0, x1); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(102)); + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + return pyresult; +} +#else +# define _cffi_f_cmark_render_xml _cffi_d_cmark_render_xml +#endif + +static char const * _cffi_d_cmark_version_string(void) +{ + return cmark_version_string(); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_cmark_version_string(PyObject *self, PyObject *noarg) +{ + char const * result; + PyObject *pyresult; + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { result = cmark_version_string(); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + (void)noarg; /* unused */ + pyresult = _cffi_from_c_pointer((char *)result, _cffi_type(35)); + return pyresult; +} +#else +# define _cffi_f_cmark_version_string _cffi_d_cmark_version_string +#endif + +static void _cffi_d_free(void * x0) +{ + free(x0); +} +#ifndef PYPY_VERSION +static PyObject * +_cffi_f_free(PyObject *self, PyObject *arg0) +{ + void * x0; + Py_ssize_t datasize; + struct _cffi_freeme_s *large_args_free = NULL; + + datasize = _cffi_prepare_pointer_call_argument( + _cffi_type(98), arg0, (char **)&x0); + if (datasize != 0) { + x0 = ((size_t)datasize) <= 640 ? (void *)alloca((size_t)datasize) : NULL; + if (_cffi_convert_array_argument(_cffi_type(98), arg0, (char **)&x0, + datasize, &large_args_free) < 0) + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + _cffi_restore_errno(); + { free(x0); } + _cffi_save_errno(); + Py_END_ALLOW_THREADS + + (void)self; /* unused */ + if (large_args_free != NULL) _cffi_free_array_arguments(large_args_free); + Py_INCREF(Py_None); + return Py_None; +} +#else +# define _cffi_f_free _cffi_d_free +#endif + +static int _cffi_const_CMARK_OPT_DEFAULT(unsigned long long *o) +{ + int n = (CMARK_OPT_DEFAULT) <= 0; + *o = (unsigned long long)((CMARK_OPT_DEFAULT) | 0); /* check that CMARK_OPT_DEFAULT is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_FOOTNOTES(unsigned long long *o) +{ + int n = (CMARK_OPT_FOOTNOTES) <= 0; + *o = (unsigned long long)((CMARK_OPT_FOOTNOTES) | 0); /* check that CMARK_OPT_FOOTNOTES is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_FULL_INFO_STRING(unsigned long long *o) +{ + int n = (CMARK_OPT_FULL_INFO_STRING) <= 0; + *o = (unsigned long long)((CMARK_OPT_FULL_INFO_STRING) | 0); /* check that CMARK_OPT_FULL_INFO_STRING is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_GITHUB_PRE_LANG(unsigned long long *o) +{ + int n = (CMARK_OPT_GITHUB_PRE_LANG) <= 0; + *o = (unsigned long long)((CMARK_OPT_GITHUB_PRE_LANG) | 0); /* check that CMARK_OPT_GITHUB_PRE_LANG is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_HARDBREAKS(unsigned long long *o) +{ + int n = (CMARK_OPT_HARDBREAKS) <= 0; + *o = (unsigned long long)((CMARK_OPT_HARDBREAKS) | 0); /* check that CMARK_OPT_HARDBREAKS is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_LIBERAL_HTML_TAG(unsigned long long *o) +{ + int n = (CMARK_OPT_LIBERAL_HTML_TAG) <= 0; + *o = (unsigned long long)((CMARK_OPT_LIBERAL_HTML_TAG) | 0); /* check that CMARK_OPT_LIBERAL_HTML_TAG is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_NOBREAKS(unsigned long long *o) +{ + int n = (CMARK_OPT_NOBREAKS) <= 0; + *o = (unsigned long long)((CMARK_OPT_NOBREAKS) | 0); /* check that CMARK_OPT_NOBREAKS is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_NORMALIZE(unsigned long long *o) +{ + int n = (CMARK_OPT_NORMALIZE) <= 0; + *o = (unsigned long long)((CMARK_OPT_NORMALIZE) | 0); /* check that CMARK_OPT_NORMALIZE is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_SAFE(unsigned long long *o) +{ + int n = (CMARK_OPT_SAFE) <= 0; + *o = (unsigned long long)((CMARK_OPT_SAFE) | 0); /* check that CMARK_OPT_SAFE is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_SMART(unsigned long long *o) +{ + int n = (CMARK_OPT_SMART) <= 0; + *o = (unsigned long long)((CMARK_OPT_SMART) | 0); /* check that CMARK_OPT_SMART is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_SOURCEPOS(unsigned long long *o) +{ + int n = (CMARK_OPT_SOURCEPOS) <= 0; + *o = (unsigned long long)((CMARK_OPT_SOURCEPOS) | 0); /* check that CMARK_OPT_SOURCEPOS is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE(unsigned long long *o) +{ + int n = (CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE) <= 0; + *o = (unsigned long long)((CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE) | 0); /* check that CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES(unsigned long long *o) +{ + int n = (CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES) <= 0; + *o = (unsigned long long)((CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES) | 0); /* check that CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_UNSAFE(unsigned long long *o) +{ + int n = (CMARK_OPT_UNSAFE) <= 0; + *o = (unsigned long long)((CMARK_OPT_UNSAFE) | 0); /* check that CMARK_OPT_UNSAFE is an integer */ + return n; +} + +static int _cffi_const_CMARK_OPT_VALIDATE_UTF8(unsigned long long *o) +{ + int n = (CMARK_OPT_VALIDATE_UTF8) <= 0; + *o = (unsigned long long)((CMARK_OPT_VALIDATE_UTF8) | 0); /* check that CMARK_OPT_VALIDATE_UTF8 is an integer */ + return n; +} + +_CFFI_UNUSED_FN +static void _cffi_checkfld__cmark_llist(cmark_llist *p) +{ + /* only to generate compile-time warnings or errors */ + (void)p; + { cmark_llist * *tmp = &p->next; (void)tmp; } + { void * *tmp = &p->data; (void)tmp; } +} +struct _cffi_align__cmark_llist { char x; cmark_llist y; }; + +static const struct _cffi_global_s _cffi_globals[] = { + { "CMARK_BULLET_LIST", (void *)_cffi_const_CMARK_BULLET_LIST, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_EVENT_DONE", (void *)_cffi_const_CMARK_EVENT_DONE, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_EVENT_ENTER", (void *)_cffi_const_CMARK_EVENT_ENTER, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_EVENT_EXIT", (void *)_cffi_const_CMARK_EVENT_EXIT, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_EVENT_NONE", (void *)_cffi_const_CMARK_EVENT_NONE, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_BLOCK_QUOTE", (void *)_cffi_const_CMARK_NODE_BLOCK_QUOTE, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_CODE", (void *)_cffi_const_CMARK_NODE_CODE, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_CODE_BLOCK", (void *)_cffi_const_CMARK_NODE_CODE_BLOCK, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_CUSTOM_BLOCK", (void *)_cffi_const_CMARK_NODE_CUSTOM_BLOCK, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_CUSTOM_INLINE", (void *)_cffi_const_CMARK_NODE_CUSTOM_INLINE, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_DOCUMENT", (void *)_cffi_const_CMARK_NODE_DOCUMENT, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_EMPH", (void *)_cffi_const_CMARK_NODE_EMPH, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_FOOTNOTE_DEFINITION", (void *)_cffi_const_CMARK_NODE_FOOTNOTE_DEFINITION, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_FOOTNOTE_REFERENCE", (void *)_cffi_const_CMARK_NODE_FOOTNOTE_REFERENCE, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_HEADING", (void *)_cffi_const_CMARK_NODE_HEADING, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_HTML_BLOCK", (void *)_cffi_const_CMARK_NODE_HTML_BLOCK, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_HTML_INLINE", (void *)_cffi_const_CMARK_NODE_HTML_INLINE, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_IMAGE", (void *)_cffi_const_CMARK_NODE_IMAGE, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_ITEM", (void *)_cffi_const_CMARK_NODE_ITEM, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_LINEBREAK", (void *)_cffi_const_CMARK_NODE_LINEBREAK, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_LINK", (void *)_cffi_const_CMARK_NODE_LINK, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_LIST", (void *)_cffi_const_CMARK_NODE_LIST, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_NONE", (void *)_cffi_const_CMARK_NODE_NONE, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_PARAGRAPH", (void *)_cffi_const_CMARK_NODE_PARAGRAPH, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_SOFTBREAK", (void *)_cffi_const_CMARK_NODE_SOFTBREAK, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_STRONG", (void *)_cffi_const_CMARK_NODE_STRONG, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_TEXT", (void *)_cffi_const_CMARK_NODE_TEXT, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NODE_THEMATIC_BREAK", (void *)_cffi_const_CMARK_NODE_THEMATIC_BREAK, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NO_DELIM", (void *)_cffi_const_CMARK_NO_DELIM, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_NO_LIST", (void *)_cffi_const_CMARK_NO_LIST, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_OPT_DEFAULT", (void *)_cffi_const_CMARK_OPT_DEFAULT, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_FOOTNOTES", (void *)_cffi_const_CMARK_OPT_FOOTNOTES, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_FULL_INFO_STRING", (void *)_cffi_const_CMARK_OPT_FULL_INFO_STRING, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_GITHUB_PRE_LANG", (void *)_cffi_const_CMARK_OPT_GITHUB_PRE_LANG, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_HARDBREAKS", (void *)_cffi_const_CMARK_OPT_HARDBREAKS, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_LIBERAL_HTML_TAG", (void *)_cffi_const_CMARK_OPT_LIBERAL_HTML_TAG, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_NOBREAKS", (void *)_cffi_const_CMARK_OPT_NOBREAKS, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_NORMALIZE", (void *)_cffi_const_CMARK_OPT_NORMALIZE, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_SAFE", (void *)_cffi_const_CMARK_OPT_SAFE, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_SMART", (void *)_cffi_const_CMARK_OPT_SMART, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_SOURCEPOS", (void *)_cffi_const_CMARK_OPT_SOURCEPOS, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE", (void *)_cffi_const_CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES", (void *)_cffi_const_CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_UNSAFE", (void *)_cffi_const_CMARK_OPT_UNSAFE, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_OPT_VALIDATE_UTF8", (void *)_cffi_const_CMARK_OPT_VALIDATE_UTF8, _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), (void *)0 }, + { "CMARK_ORDERED_LIST", (void *)_cffi_const_CMARK_ORDERED_LIST, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_PAREN_DELIM", (void *)_cffi_const_CMARK_PAREN_DELIM, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "CMARK_PERIOD_DELIM", (void *)_cffi_const_CMARK_PERIOD_DELIM, _CFFI_OP(_CFFI_OP_ENUM, -1), (void *)0 }, + { "cmark_find_syntax_extension", (void *)_cffi_f_cmark_find_syntax_extension, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 57), (void *)_cffi_d_cmark_find_syntax_extension }, + { "cmark_gfm_core_extensions_ensure_registered", (void *)_cffi_f_cmark_gfm_core_extensions_ensure_registered, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_N, 100), (void *)_cffi_d_cmark_gfm_core_extensions_ensure_registered }, + { "cmark_iter_free", (void *)_cffi_f_cmark_iter_free, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 83), (void *)_cffi_d_cmark_iter_free }, + { "cmark_iter_get_event_type", (void *)_cffi_f_cmark_iter_get_event_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 22), (void *)_cffi_d_cmark_iter_get_event_type }, + { "cmark_iter_get_node", (void *)_cffi_f_cmark_iter_get_node, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 39), (void *)_cffi_d_cmark_iter_get_node }, + { "cmark_iter_new", (void *)_cffi_f_cmark_iter_new, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 25), (void *)_cffi_d_cmark_iter_new }, + { "cmark_iter_next", (void *)_cffi_f_cmark_iter_next, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 22), (void *)_cffi_d_cmark_iter_next }, + { "cmark_node_append_child", (void *)_cffi_f_cmark_node_append_child, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 71), (void *)_cffi_d_cmark_node_append_child }, + { "cmark_node_first_child", (void *)_cffi_f_cmark_node_first_child, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 42), (void *)_cffi_d_cmark_node_first_child }, + { "cmark_node_free", (void *)_cffi_f_cmark_node_free, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 86), (void *)_cffi_d_cmark_node_free }, + { "cmark_node_get_end_column", (void *)_cffi_f_cmark_node_get_end_column, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 60), (void *)_cffi_d_cmark_node_get_end_column }, + { "cmark_node_get_end_line", (void *)_cffi_f_cmark_node_get_end_line, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 60), (void *)_cffi_d_cmark_node_get_end_line }, + { "cmark_node_get_fence_info", (void *)_cffi_f_cmark_node_get_fence_info, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 14), (void *)_cffi_d_cmark_node_get_fence_info }, + { "cmark_node_get_heading_level", (void *)_cffi_f_cmark_node_get_heading_level, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 60), (void *)_cffi_d_cmark_node_get_heading_level }, + { "cmark_node_get_list_delim", (void *)_cffi_f_cmark_node_get_list_delim, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 19), (void *)_cffi_d_cmark_node_get_list_delim }, + { "cmark_node_get_list_start", (void *)_cffi_f_cmark_node_get_list_start, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 60), (void *)_cffi_d_cmark_node_get_list_start }, + { "cmark_node_get_list_tight", (void *)_cffi_f_cmark_node_get_list_tight, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 60), (void *)_cffi_d_cmark_node_get_list_tight }, + { "cmark_node_get_list_type", (void *)_cffi_f_cmark_node_get_list_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 28), (void *)_cffi_d_cmark_node_get_list_type }, + { "cmark_node_get_literal", (void *)_cffi_f_cmark_node_get_literal, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 14), (void *)_cffi_d_cmark_node_get_literal }, + { "cmark_node_get_start_column", (void *)_cffi_f_cmark_node_get_start_column, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 60), (void *)_cffi_d_cmark_node_get_start_column }, + { "cmark_node_get_start_line", (void *)_cffi_f_cmark_node_get_start_line, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 60), (void *)_cffi_d_cmark_node_get_start_line }, + { "cmark_node_get_title", (void *)_cffi_f_cmark_node_get_title, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 14), (void *)_cffi_d_cmark_node_get_title }, + { "cmark_node_get_type", (void *)_cffi_f_cmark_node_get_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 51), (void *)_cffi_d_cmark_node_get_type }, + { "cmark_node_get_type_string", (void *)_cffi_f_cmark_node_get_type_string, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 14), (void *)_cffi_d_cmark_node_get_type_string }, + { "cmark_node_get_url", (void *)_cffi_f_cmark_node_get_url, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 14), (void *)_cffi_d_cmark_node_get_url }, + { "cmark_node_insert_after", (void *)_cffi_f_cmark_node_insert_after, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 71), (void *)_cffi_d_cmark_node_insert_after }, + { "cmark_node_insert_before", (void *)_cffi_f_cmark_node_insert_before, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 71), (void *)_cffi_d_cmark_node_insert_before }, + { "cmark_node_last_child", (void *)_cffi_f_cmark_node_last_child, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 42), (void *)_cffi_d_cmark_node_last_child }, + { "cmark_node_new", (void *)_cffi_f_cmark_node_new, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 45), (void *)_cffi_d_cmark_node_new }, + { "cmark_node_next", (void *)_cffi_f_cmark_node_next, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 42), (void *)_cffi_d_cmark_node_next }, + { "cmark_node_parent", (void *)_cffi_f_cmark_node_parent, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 42), (void *)_cffi_d_cmark_node_parent }, + { "cmark_node_prepend_child", (void *)_cffi_f_cmark_node_prepend_child, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 71), (void *)_cffi_d_cmark_node_prepend_child }, + { "cmark_node_previous", (void *)_cffi_f_cmark_node_previous, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 42), (void *)_cffi_d_cmark_node_previous }, + { "cmark_node_replace", (void *)_cffi_f_cmark_node_replace, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 71), (void *)_cffi_d_cmark_node_replace }, + { "cmark_node_set_fence_info", (void *)_cffi_f_cmark_node_set_fence_info, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 63), (void *)_cffi_d_cmark_node_set_fence_info }, + { "cmark_node_set_heading_level", (void *)_cffi_f_cmark_node_set_heading_level, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 75), (void *)_cffi_d_cmark_node_set_heading_level }, + { "cmark_node_set_list_start", (void *)_cffi_f_cmark_node_set_list_start, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 75), (void *)_cffi_d_cmark_node_set_list_start }, + { "cmark_node_set_list_tight", (void *)_cffi_f_cmark_node_set_list_tight, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 75), (void *)_cffi_d_cmark_node_set_list_tight }, + { "cmark_node_set_list_type", (void *)_cffi_f_cmark_node_set_list_type, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 67), (void *)_cffi_d_cmark_node_set_list_type }, + { "cmark_node_set_literal", (void *)_cffi_f_cmark_node_set_literal, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 63), (void *)_cffi_d_cmark_node_set_literal }, + { "cmark_node_set_title", (void *)_cffi_f_cmark_node_set_title, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 63), (void *)_cffi_d_cmark_node_set_title }, + { "cmark_node_set_url", (void *)_cffi_f_cmark_node_set_url, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 63), (void *)_cffi_d_cmark_node_set_url }, + { "cmark_node_unlink", (void *)_cffi_f_cmark_node_unlink, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 86), (void *)_cffi_d_cmark_node_unlink }, + { "cmark_parse_document", (void *)_cffi_f_cmark_parse_document, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 34), (void *)_cffi_d_cmark_parse_document }, + { "cmark_parser_attach_syntax_extension", (void *)_cffi_f_cmark_parser_attach_syntax_extension, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 79), (void *)_cffi_d_cmark_parser_attach_syntax_extension }, + { "cmark_parser_feed", (void *)_cffi_f_cmark_parser_feed, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 92), (void *)_cffi_d_cmark_parser_feed }, + { "cmark_parser_finish", (void *)_cffi_f_cmark_parser_finish, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 48), (void *)_cffi_d_cmark_parser_finish }, + { "cmark_parser_free", (void *)_cffi_f_cmark_parser_free, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 89), (void *)_cffi_d_cmark_parser_free }, + { "cmark_parser_get_syntax_extensions", (void *)_cffi_f_cmark_parser_get_syntax_extensions, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 31), (void *)_cffi_d_cmark_parser_get_syntax_extensions }, + { "cmark_parser_new", (void *)_cffi_f_cmark_parser_new, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 54), (void *)_cffi_d_cmark_parser_new }, + { "cmark_render_commonmark", (void *)_cffi_f_cmark_render_commonmark, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 9), (void *)_cffi_d_cmark_render_commonmark }, + { "cmark_render_html", (void *)_cffi_f_cmark_render_html, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 4), (void *)_cffi_d_cmark_render_html }, + { "cmark_render_latex", (void *)_cffi_f_cmark_render_latex, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 9), (void *)_cffi_d_cmark_render_latex }, + { "cmark_render_man", (void *)_cffi_f_cmark_render_man, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 9), (void *)_cffi_d_cmark_render_man }, + { "cmark_render_xml", (void *)_cffi_f_cmark_render_xml, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 0), (void *)_cffi_d_cmark_render_xml }, + { "cmark_version_string", (void *)_cffi_f_cmark_version_string, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_N, 17), (void *)_cffi_d_cmark_version_string }, + { "free", (void *)_cffi_f_free, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 97), (void *)_cffi_d_free }, +}; + +static const struct _cffi_field_s _cffi_fields[] = { + { "next", offsetof(cmark_llist, next), + sizeof(((cmark_llist *)0)->next), + _CFFI_OP(_CFFI_OP_NOOP, 7) }, + { "data", offsetof(cmark_llist, data), + sizeof(((cmark_llist *)0)->data), + _CFFI_OP(_CFFI_OP_NOOP, 98) }, +}; + +static const struct _cffi_struct_union_s _cffi_struct_unions[] = { + { "_cmark_llist", 107, _CFFI_F_CHECK_FIELDS, + sizeof(cmark_llist), offsetof(struct _cffi_align__cmark_llist, y), 0, 2 }, + { "cmark_iter", 106, _CFFI_F_OPAQUE, + (size_t)-1, -1, -1, 0 /* opaque */ }, + { "cmark_node", 108, _CFFI_F_OPAQUE, + (size_t)-1, -1, -1, 0 /* opaque */ }, + { "cmark_parser", 109, _CFFI_F_OPAQUE, + (size_t)-1, -1, -1, 0 /* opaque */ }, + { "cmark_syntax_extension", 110, _CFFI_F_OPAQUE, + (size_t)-1, -1, -1, 0 /* opaque */ }, +}; + +static const struct _cffi_enum_s _cffi_enums[] = { + { "$cmark_delim_type", 104, _cffi_prim_int(sizeof(cmark_delim_type), ((cmark_delim_type)-1) <= 0), + "CMARK_NO_DELIM,CMARK_PERIOD_DELIM,CMARK_PAREN_DELIM" }, + { "$cmark_event_type", 105, _cffi_prim_int(sizeof(cmark_event_type), ((cmark_event_type)-1) <= 0), + "CMARK_EVENT_NONE,CMARK_EVENT_DONE,CMARK_EVENT_ENTER,CMARK_EVENT_EXIT" }, + { "$cmark_list_type", 69, _cffi_prim_int(sizeof(cmark_list_type), ((cmark_list_type)-1) <= 0), + "CMARK_NO_LIST,CMARK_BULLET_LIST,CMARK_ORDERED_LIST" }, + { "$cmark_node_type", 46, _cffi_prim_int(sizeof(cmark_node_type), ((cmark_node_type)-1) <= 0), + "CMARK_NODE_NONE,CMARK_NODE_DOCUMENT,CMARK_NODE_BLOCK_QUOTE,CMARK_NODE_LIST,CMARK_NODE_ITEM,CMARK_NODE_CODE_BLOCK,CMARK_NODE_HTML_BLOCK,CMARK_NODE_CUSTOM_BLOCK,CMARK_NODE_PARAGRAPH,CMARK_NODE_HEADING,CMARK_NODE_THEMATIC_BREAK,CMARK_NODE_FOOTNOTE_DEFINITION,CMARK_NODE_TEXT,CMARK_NODE_SOFTBREAK,CMARK_NODE_LINEBREAK,CMARK_NODE_CODE,CMARK_NODE_HTML_INLINE,CMARK_NODE_CUSTOM_INLINE,CMARK_NODE_EMPH,CMARK_NODE_STRONG,CMARK_NODE_LINK,CMARK_NODE_IMAGE,CMARK_NODE_FOOTNOTE_REFERENCE" }, +}; + +static const struct _cffi_typename_s _cffi_typenames[] = { + { "cmark_delim_type", 104 }, + { "cmark_event_type", 105 }, + { "cmark_iter", 106 }, + { "cmark_list_type", 69 }, + { "cmark_llist", 107 }, + { "cmark_node", 108 }, + { "cmark_node_type", 46 }, + { "cmark_parser", 109 }, + { "cmark_syntax_extension", 110 }, +}; + +static const struct _cffi_type_context_s _cffi_type_context = { + _cffi_types, + _cffi_globals, + _cffi_fields, + _cffi_struct_unions, + _cffi_enums, + _cffi_typenames, + 105, /* num_globals */ + 5, /* num_struct_unions */ + 4, /* num_enums */ + 9, /* num_typenames */ + NULL, /* no includes */ + 112, /* num_types */ + 0, /* flags */ +}; + +#ifdef __GNUC__ +# pragma GCC visibility push(default) /* for -fvisibility= */ +#endif + +#ifdef PYPY_VERSION +PyMODINIT_FUNC +_cffi_pypyinit__binding(const void *p[]) +{ + p[0] = (const void *)0x2601; + p[1] = &_cffi_type_context; +#if PY_MAJOR_VERSION >= 3 + return NULL; +#endif +} +# ifdef _MSC_VER + PyMODINIT_FUNC +# if PY_MAJOR_VERSION >= 3 + PyInit__binding(void) { return NULL; } +# else + init_binding(void) { } +# endif +# endif +#elif PY_MAJOR_VERSION >= 3 +PyMODINIT_FUNC +PyInit__binding(void) +{ + return _cffi_init("multimark._binding", 0x2601, &_cffi_type_context); +} +#else +PyMODINIT_FUNC +init_binding(void) +{ + _cffi_init("multimark._binding", 0x2601, &_cffi_type_context); +} +#endif + +#ifdef __GNUC__ +# pragma GCC visibility pop +#endif diff --git a/multimark/_binding.o b/multimark/_binding.o new file mode 100644 index 0000000..b10c400 Binary files /dev/null and b/multimark/_binding.o differ diff --git a/pyproject.toml b/pyproject.toml index 0c17020..4917b92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Text Processing :: Markup :: Markdown", ] @@ -43,6 +44,10 @@ multimark = ["*.h"] [tool.setuptools_scm] +[tool.cibuildwheel.pyodide] +test-requires = ["pytest"] +test-command = "python -m pytest {project}/tests -x --ignore={project}/tests/test_cli.py" + [tool.pytest.ini_options] testpaths = ["tests"] diff --git a/src/multimark/__init__.py b/src/multimark/__init__.py index 6813e96..e064488 100644 --- a/src/multimark/__init__.py +++ b/src/multimark/__init__.py @@ -15,6 +15,8 @@ cmark_version, VALID_EXTENSIONS, ) +from multimark._parser import Parser +from multimark._node import Node, NodeType, ListType, DelimType, parse from multimark._binding import lib diff --git a/src/multimark/_node.py b/src/multimark/_node.py new file mode 100644 index 0000000..43b30cc --- /dev/null +++ b/src/multimark/_node.py @@ -0,0 +1,623 @@ +from __future__ import annotations + +import weakref +from enum import IntEnum +from typing import Generator, Sequence + +from multimark._binding import ffi, lib +from multimark._cmark import _build_options, _get_extension, VALID_EXTENSIONS + + +class NodeType(IntEnum): + """CommonMark/GFM AST node types.""" + + NONE = lib.CMARK_NODE_NONE + # Block nodes + DOCUMENT = lib.CMARK_NODE_DOCUMENT + BLOCK_QUOTE = lib.CMARK_NODE_BLOCK_QUOTE + LIST = lib.CMARK_NODE_LIST + ITEM = lib.CMARK_NODE_ITEM + CODE_BLOCK = lib.CMARK_NODE_CODE_BLOCK + HTML_BLOCK = lib.CMARK_NODE_HTML_BLOCK + CUSTOM_BLOCK = lib.CMARK_NODE_CUSTOM_BLOCK + PARAGRAPH = lib.CMARK_NODE_PARAGRAPH + HEADING = lib.CMARK_NODE_HEADING + THEMATIC_BREAK = lib.CMARK_NODE_THEMATIC_BREAK + FOOTNOTE_DEFINITION = lib.CMARK_NODE_FOOTNOTE_DEFINITION + # Inline nodes + TEXT = lib.CMARK_NODE_TEXT + SOFTBREAK = lib.CMARK_NODE_SOFTBREAK + LINEBREAK = lib.CMARK_NODE_LINEBREAK + CODE = lib.CMARK_NODE_CODE + HTML_INLINE = lib.CMARK_NODE_HTML_INLINE + CUSTOM_INLINE = lib.CMARK_NODE_CUSTOM_INLINE + EMPH = lib.CMARK_NODE_EMPH + STRONG = lib.CMARK_NODE_STRONG + LINK = lib.CMARK_NODE_LINK + IMAGE = lib.CMARK_NODE_IMAGE + FOOTNOTE_REFERENCE = lib.CMARK_NODE_FOOTNOTE_REFERENCE + + +class ListType(IntEnum): + """List type for LIST nodes.""" + + NONE = lib.CMARK_NO_LIST + BULLET = lib.CMARK_BULLET_LIST + ORDERED = lib.CMARK_ORDERED_LIST + + +class DelimType(IntEnum): + """Delimiter type for ordered lists.""" + + NONE = lib.CMARK_NO_DELIM + PERIOD = lib.CMARK_PERIOD_DELIM + PAREN = lib.CMARK_PAREN_DELIM + + +class Node: + """A node in the CommonMark/GFM abstract syntax tree. + + Nodes are obtained by calling `parse()` or `Parser.finish()`. They should not be + instantiated directly. + + Provides tree traversal, node property access, and rendering methods. + """ + + # Identity map: pointer address → weak reference to Node wrapper. + # Ensures `node.next is node.next` holds True for the same tree. + _identity_map: dict[int, weakref.ref[Node]] = {} + + __slots__ = ("_ptr", "_owner", "__weakref__") + + def __init__(self, ptr, owner): + self._ptr = ptr + # owner keeps the root node (and thus the whole C tree) alive. + # For root nodes, owner is the Parser or a ref-holding sentinel. + self._owner = owner + + @classmethod + def _from_ptr(cls, ptr, owner) -> Node | None: + """Get or create a Node wrapper for a C pointer.""" + if ptr == ffi.NULL: + return None + addr = int(ffi.cast("uintptr_t", ptr)) + ref = cls._identity_map.get(addr) + if ref is not None: + node = ref() + if node is not None: + return node + node = cls.__new__(cls) + node._ptr = ptr + node._owner = owner + cls._identity_map[addr] = weakref.ref(node, lambda r, a=addr: cls._identity_map.pop(a, None)) + return node + + @classmethod + def new(cls, node_type: NodeType) -> Node: + """Create a new detached node of the given type. + + The node is not part of any tree. Use mutation methods + (`append_child()`, `insert_before()`, etc.) to attach it. + + Parameters + ---------- + node_type : NodeType + The type of node to create. + + Returns + ------- + Node + A new detached node. + """ + ptr = lib.cmark_node_new(int(node_type)) + if ptr == ffi.NULL: + raise MemoryError("Failed to create node") + node = cls.__new__(cls) + node._ptr = ptr + + # Detached nodes own themselves; stored as a prevent-GC ref. + node._owner = node + addr = int(ffi.cast("uintptr_t", ptr)) + cls._identity_map[addr] = weakref.ref(node, lambda r, a=addr: cls._identity_map.pop(a, None)) + return node + + def _check_alive(self): + if self._ptr == ffi.NULL: + raise ValueError("Node has been freed") + + # -- Tree traversal -- + + @property + def type(self) -> NodeType: + """The node type.""" + self._check_alive() + raw = lib.cmark_node_get_type(self._ptr) + try: + return NodeType(raw) + except ValueError: + # Extension node types may not be in our enum + return raw + + @property + def type_string(self) -> str: + """Human-readable node type name from cmark (e.g., `'heading'`).""" + self._check_alive() + ptr = lib.cmark_node_get_type_string(self._ptr) + if ptr == ffi.NULL: + return "none" + return ffi.string(ptr).decode("utf-8") + + @property + def parent(self) -> Node | None: + """The parent node, or `None` if this is the root.""" + self._check_alive() + return Node._from_ptr(lib.cmark_node_parent(self._ptr), self._owner) + + @property + def first_child(self) -> Node | None: + """The first child node, or `None`.""" + self._check_alive() + return Node._from_ptr(lib.cmark_node_first_child(self._ptr), self._owner) + + @property + def last_child(self) -> Node | None: + """The last child node, or `None`.""" + self._check_alive() + return Node._from_ptr(lib.cmark_node_last_child(self._ptr), self._owner) + + @property + def next(self) -> Node | None: + """The next sibling, or `None`.""" + self._check_alive() + return Node._from_ptr(lib.cmark_node_next(self._ptr), self._owner) + + @property + def previous(self) -> Node | None: + """The previous sibling, or `None`.""" + self._check_alive() + return Node._from_ptr(lib.cmark_node_previous(self._ptr), self._owner) + + @property + def children(self) -> Generator[Node, None, None]: + """Iterate over direct child nodes.""" + self._check_alive() + child = lib.cmark_node_first_child(self._ptr) + while child != ffi.NULL: + yield Node._from_ptr(child, self._owner) + child = lib.cmark_node_next(child) + + # -- Node properties -- + + @property + def literal(self) -> str | None: + """Text content for text, code, and HTML nodes. `None` if not applicable.""" + self._check_alive() + ptr = lib.cmark_node_get_literal(self._ptr) + if ptr == ffi.NULL: + return None + return ffi.string(ptr).decode("utf-8") + + @literal.setter + def literal(self, value: str) -> None: + self._check_alive() + if not isinstance(value, str): + raise TypeError(f"Expected str, got {type(value).__name__}") + rc = lib.cmark_node_set_literal(self._ptr, value.encode("utf-8")) + if rc == 0: + raise ValueError("Cannot set literal on this node type") + + @property + def url(self) -> str | None: + """URL for link and image nodes. `None` if not applicable.""" + self._check_alive() + ptr = lib.cmark_node_get_url(self._ptr) + if ptr == ffi.NULL: + return None + return ffi.string(ptr).decode("utf-8") + + @url.setter + def url(self, value: str) -> None: + self._check_alive() + if not isinstance(value, str): + raise TypeError(f"Expected str, got {type(value).__name__}") + rc = lib.cmark_node_set_url(self._ptr, value.encode("utf-8")) + if rc == 0: + raise ValueError("Cannot set URL on this node type") + + @property + def title(self) -> str | None: + """Title for link and image nodes. `None` if not applicable.""" + self._check_alive() + ptr = lib.cmark_node_get_title(self._ptr) + if ptr == ffi.NULL: + return None + return ffi.string(ptr).decode("utf-8") + + @title.setter + def title(self, value: str) -> None: + self._check_alive() + if not isinstance(value, str): + raise TypeError(f"Expected str, got {type(value).__name__}") + rc = lib.cmark_node_set_title(self._ptr, value.encode("utf-8")) + if rc == 0: + raise ValueError("Cannot set title on this node type") + + @property + def heading_level(self) -> int: + """Heading level (1–6) for `HEADING` nodes; 0 otherwise.""" + self._check_alive() + return lib.cmark_node_get_heading_level(self._ptr) + + @heading_level.setter + def heading_level(self, value: int) -> None: + self._check_alive() + rc = lib.cmark_node_set_heading_level(self._ptr, value) + if rc == 0: + raise ValueError("Cannot set heading level on this node type") + + @property + def list_type(self) -> ListType: + """List type (`BULLET` or `ORDERED`) for `LIST` nodes.""" + self._check_alive() + return ListType(lib.cmark_node_get_list_type(self._ptr)) + + @list_type.setter + def list_type(self, value: ListType) -> None: + self._check_alive() + rc = lib.cmark_node_set_list_type(self._ptr, int(value)) + if rc == 0: + raise ValueError("Cannot set list type on this node type") + + @property + def list_delim(self) -> DelimType: + """Delimiter type for ordered `LIST` nodes.""" + self._check_alive() + return DelimType(lib.cmark_node_get_list_delim(self._ptr)) + + @property + def list_start(self) -> int: + """Starting number for ordered `LIST` nodes; 0 otherwise.""" + self._check_alive() + return lib.cmark_node_get_list_start(self._ptr) + + @list_start.setter + def list_start(self, value: int) -> None: + self._check_alive() + rc = lib.cmark_node_set_list_start(self._ptr, value) + if rc == 0: + raise ValueError("Cannot set list start on this node type") + + @property + def list_tight(self) -> bool: + """Whether a `LIST` node is tight (no blank lines between items).""" + self._check_alive() + return bool(lib.cmark_node_get_list_tight(self._ptr)) + + @list_tight.setter + def list_tight(self, value: bool) -> None: + self._check_alive() + rc = lib.cmark_node_set_list_tight(self._ptr, int(value)) + if rc == 0: + raise ValueError("Cannot set list tight on this node type") + + @property + def fence_info(self) -> str | None: + """Info string for fenced `CODE_BLOCK` nodes (e.g., `'python'`).""" + self._check_alive() + ptr = lib.cmark_node_get_fence_info(self._ptr) + if ptr == ffi.NULL: + return None + return ffi.string(ptr).decode("utf-8") + + @fence_info.setter + def fence_info(self, value: str) -> None: + self._check_alive() + if not isinstance(value, str): + raise TypeError(f"Expected str, got {type(value).__name__}") + rc = lib.cmark_node_set_fence_info(self._ptr, value.encode("utf-8")) + if rc == 0: + raise ValueError("Cannot set fence info on this node type") + + # -- Source positions -- + + @property + def start_line(self) -> int: + """Start line (1-based) in source. 0 if not available.""" + self._check_alive() + return lib.cmark_node_get_start_line(self._ptr) + + @property + def start_column(self) -> int: + """Start column (1-based) in source. 0 if not available.""" + self._check_alive() + return lib.cmark_node_get_start_column(self._ptr) + + @property + def end_line(self) -> int: + """End line (1-based) in source. 0 if not available.""" + self._check_alive() + return lib.cmark_node_get_end_line(self._ptr) + + @property + def end_column(self) -> int: + """End column (1-based) in source. 0 if not available.""" + self._check_alive() + return lib.cmark_node_get_end_column(self._ptr) + + # -- Iterator / walk -- + + def walk(self) -> Generator[tuple[str, Node], None, None]: + """Depth-first walk of the subtree rooted at this node. + + Yields `(event, node)` pairs where *event* is `"enter"` or `"exit"`. + Leaf nodes (`text`, `softbreak`, `linebreak`, `code`, `thematic_break`, `html`) only + produce an `"enter"` event. + + Examples + -------- + ```python + for event, node in doc.walk(): + if event == "enter" and node.type == NodeType.HEADING: + print(f"Heading level {node.heading_level}") + ``` + """ + self._check_alive() + it = lib.cmark_iter_new(self._ptr) + if it == ffi.NULL: + raise MemoryError("Failed to create iterator") + try: + while True: + ev = lib.cmark_iter_next(it) + if ev == lib.CMARK_EVENT_DONE: + break + cur = lib.cmark_iter_get_node(it) + event_str = "enter" if ev == lib.CMARK_EVENT_ENTER else "exit" + yield event_str, Node._from_ptr(cur, self._owner) + finally: + lib.cmark_iter_free(it) + + # -- Mutation -- + + def unlink(self) -> None: + """Remove this node from its parent tree.""" + self._check_alive() + lib.cmark_node_unlink(self._ptr) + # After unlinking, this node owns itself + self._owner = self + + def insert_before(self, sibling: Node) -> None: + """Insert *sibling* as the node immediately before this one.""" + self._check_alive() + sibling._check_alive() + rc = lib.cmark_node_insert_before(self._ptr, sibling._ptr) + if rc == 0: + raise ValueError("Failed to insert node before") + sibling._owner = self._owner + + def insert_after(self, sibling: Node) -> None: + """Insert *sibling* as the node immediately after this one.""" + self._check_alive() + sibling._check_alive() + rc = lib.cmark_node_insert_after(self._ptr, sibling._ptr) + if rc == 0: + raise ValueError("Failed to insert node after") + sibling._owner = self._owner + + def append_child(self, child: Node) -> None: + """Append *child* as the last child of this node.""" + self._check_alive() + child._check_alive() + rc = lib.cmark_node_append_child(self._ptr, child._ptr) + if rc == 0: + raise ValueError("Failed to append child") + child._owner = self._owner + + def prepend_child(self, child: Node) -> None: + """Prepend *child* as the first child of this node.""" + self._check_alive() + child._check_alive() + rc = lib.cmark_node_prepend_child(self._ptr, child._ptr) + if rc == 0: + raise ValueError("Failed to prepend child") + child._owner = self._owner + + def replace(self, new_node: Node) -> None: + """Replace this node in the tree with *new_node*.""" + self._check_alive() + new_node._check_alive() + rc = lib.cmark_node_replace(self._ptr, new_node._ptr) + if rc == 0: + raise ValueError("Failed to replace node") + new_node._owner = self._owner + self._owner = self # detached now + + # -- Rendering -- + + def render_html(self, *, sourcepos: bool = False, unsafe: bool = False) -> str: + """Render this subtree as HTML.""" + self._check_alive() + opts = 0 + if sourcepos: + opts |= lib.CMARK_OPT_SOURCEPOS + if unsafe: + opts |= lib.CMARK_OPT_UNSAFE + result_ptr = lib.cmark_render_html(self._ptr, opts, ffi.NULL) + if result_ptr == ffi.NULL: + raise MemoryError("Failed to render") + result = ffi.string(result_ptr).decode("utf-8") + lib.free(result_ptr) + return result + + def render_xml(self, *, sourcepos: bool = False) -> str: + """Render this subtree as XML.""" + self._check_alive() + opts = 0 + if sourcepos: + opts |= lib.CMARK_OPT_SOURCEPOS + result_ptr = lib.cmark_render_xml(self._ptr, opts) + if result_ptr == ffi.NULL: + raise MemoryError("Failed to render") + result = ffi.string(result_ptr).decode("utf-8") + lib.free(result_ptr) + return result + + def render_latex(self, *, width: int = 0) -> str: + """Render this subtree as LaTeX.""" + self._check_alive() + result_ptr = lib.cmark_render_latex(self._ptr, 0, width) + if result_ptr == ffi.NULL: + raise MemoryError("Failed to render") + result = ffi.string(result_ptr).decode("utf-8", errors="replace") + lib.free(result_ptr) + return result + + def render_man(self, *, width: int = 0) -> str: + """Render this subtree as a groff man page.""" + self._check_alive() + result_ptr = lib.cmark_render_man(self._ptr, 0, width) + if result_ptr == ffi.NULL: + raise MemoryError("Failed to render") + result = ffi.string(result_ptr).decode("utf-8", errors="replace") + lib.free(result_ptr) + return result + + def render_commonmark(self, *, width: int = 0) -> str: + """Render this subtree as normalized CommonMark.""" + self._check_alive() + result_ptr = lib.cmark_render_commonmark(self._ptr, 0, width) + if result_ptr == ffi.NULL: + raise MemoryError("Failed to render") + result = ffi.string(result_ptr).decode("utf-8", errors="replace") + lib.free(result_ptr) + return result + + # -- Dunder methods -- + + def __repr__(self) -> str: + if self._ptr == ffi.NULL: + return "" + type_str = self.type_string + extra = "" + if self.type == NodeType.HEADING: + extra = f" level={self.heading_level}" + elif self.type in (NodeType.TEXT, NodeType.CODE): + lit = self.literal + if lit and len(lit) > 30: + lit = lit[:27] + "..." + extra = f" {lit!r}" + elif self.type in (NodeType.LINK, NodeType.IMAGE): + extra = f" url={self.url!r}" + return f"" + + def __eq__(self, other): + if not isinstance(other, Node): + return NotImplemented + return self._ptr == other._ptr + + def __hash__(self): + return hash(int(ffi.cast("uintptr_t", self._ptr))) + + +def parse( + text: str, + *, + hardbreaks: bool = False, + smart: bool = False, + normalize: bool = False, + unsafe: bool = False, + footnotes: bool = False, + extensions: Sequence[str] = (), + options: int = 0, +) -> Node: + """Parse a Markdown string and return the root AST node. + + This is the primary entry point for AST-based document inspection and transformation. The + returned `Node` provides tree traversal, property access, mutation, and rendering methods. + + Parameters + ---------- + text + The Markdown string to parse. + hardbreaks + Render soft breaks as hard breaks. Default `False`. + smart + Enable smart punctuation. Default `False`. + normalize + Consolidate adjacent text nodes. Default `False`. + unsafe + Allow raw HTML passthrough. Default `False`. + footnotes + Enable footnote syntax. Default `False`. + extensions + GFM extensions to enable. + options + Raw `Options` bitmask. + + Returns + ------- + Node + The root document node. Its `~Node.type()` is `NodeType.DOCUMENT`. + + Examples + -------- + ```python + from multimark import parse, NodeType + + doc = parse("# Hello\\n\\nWorld!\\n") + for event, node in doc.walk(): + if event == "enter" and node.type == NodeType.HEADING: + print(f"Found heading level {node.heading_level}") + ``` + """ + if not isinstance(text, str): + raise TypeError(f"Expected str, got {type(text).__name__}") + + opts = _build_options(options, hardbreaks, smart, normalize, False, unsafe, footnotes) + encoded = text.encode("utf-8") + + if extensions: + # Validate extension names + for ext_name in extensions: + if ext_name not in VALID_EXTENSIONS: + raise ValueError( + f"Unknown extension: {ext_name!r}. " + f"Valid extensions: {sorted(VALID_EXTENSIONS)}" + ) + + parser_ptr = lib.cmark_parser_new(opts) + if parser_ptr == ffi.NULL: + raise MemoryError("Failed to create parser") + for ext_name in extensions: + lib.cmark_parser_attach_syntax_extension(parser_ptr, _get_extension(ext_name)) + lib.cmark_parser_feed(parser_ptr, encoded, len(encoded)) + node_ptr = lib.cmark_parser_finish(parser_ptr) + if node_ptr == ffi.NULL: + lib.cmark_parser_free(parser_ptr) + raise MemoryError("Failed to parse document") + # Create an owner object that will free both node and parser on GC + owner = _ParseResult(node_ptr, parser_ptr) + else: + node_ptr = lib.cmark_parse_document(encoded, len(encoded), opts) + if node_ptr == ffi.NULL: + raise MemoryError("Failed to parse document") + owner = _ParseResult(node_ptr, ffi.NULL) + + return Node._from_ptr(node_ptr, owner) + + +class _ParseResult: + """Ref-holding sentinel that frees the AST when garbage collected.""" + + __slots__ = ("_node", "_parser") + + def __init__(self, node, parser): + self._node = node + self._parser = parser + + def __del__(self): + if self._node != ffi.NULL: + lib.cmark_node_free(self._node) + self._node = ffi.NULL + if self._parser != ffi.NULL: + lib.cmark_parser_free(self._parser) + self._parser = ffi.NULL diff --git a/src/multimark/_parser.py b/src/multimark/_parser.py new file mode 100644 index 0000000..e73ec2f --- /dev/null +++ b/src/multimark/_parser.py @@ -0,0 +1,280 @@ +from __future__ import annotations + +from typing import Sequence + +from multimark._binding import ffi, lib +from multimark._cmark import _build_options, _get_extension, VALID_EXTENSIONS + + +class Parser: + """Streaming CommonMark/GFM parser. + + Wraps the cmark-gfm streaming parser, allowing incremental feeding of Markdown + content and rendering to any output format. Useful for processing large documents + or streaming input without buffering the entire source in memory. + + Parameters + ---------- + hardbreaks + Render soft line breaks as hard breaks. Default `False`. + smart + Enable smart punctuation. Default `False`. + normalize + Consolidate adjacent text nodes. Default `False`. + unsafe + Allow raw HTML passthrough. Default `False`. + footnotes + Enable footnote syntax. Default `False`. + extensions + GFM extensions to enable (e.g., `["table", "strikethrough"]`). + options + Raw `Options` bitmask, OR'd with boolean kwargs. + + Examples + -------- + Basic streaming usage: + + ```python + from multimark import Parser + + parser = Parser(smart=True) + parser.feed("# Hello\\n\\n") + parser.feed("World!\\n") + html = parser.render_html() + ``` + + Context manager: + + ```python + with Parser(extensions=["table"]) as p: + p.feed("| A | B |\\n|---|---|\\n| 1 | 2 |\\n") + html = p.render_html() + ``` + """ + + def __init__( + self, + *, + hardbreaks: bool = False, + smart: bool = False, + normalize: bool = False, + unsafe: bool = False, + footnotes: bool = False, + extensions: Sequence[str] = (), + options: int = 0, + ) -> None: + self._opts = _build_options( + options, hardbreaks, smart, normalize, False, unsafe, footnotes + ) + self._extensions = list(extensions) + self._finished = False + self._node = ffi.NULL + self._parser = lib.cmark_parser_new(self._opts) + if self._parser == ffi.NULL: + raise MemoryError("Failed to create parser") + + for ext_name in self._extensions: + if ext_name not in VALID_EXTENSIONS: + lib.cmark_parser_free(self._parser) + self._parser = ffi.NULL + raise ValueError( + f"Unknown extension: {ext_name!r}. " + f"Valid extensions: {sorted(VALID_EXTENSIONS)}" + ) + lib.cmark_parser_attach_syntax_extension( + self._parser, _get_extension(ext_name) + ) + + def feed(self, text: str) -> None: + """Feed a chunk of Markdown text to the parser. + + May be called multiple times before finishing. The concatenation of all fed + chunks forms the complete document. + + Parameters + ---------- + text + Markdown content to append to the parse buffer. + + Raises + ------ + ValueError + If the parser has already been finished or closed. + TypeError + If *text* is not a string. + """ + if self._parser == ffi.NULL: + raise ValueError("Parser is closed") + if self._finished: + raise ValueError("Parser has already been finished; create a new Parser") + if not isinstance(text, str): + raise TypeError(f"Expected str, got {type(text).__name__}") + encoded = text.encode("utf-8") + lib.cmark_parser_feed(self._parser, encoded, len(encoded)) + + def _finish(self) -> None: + """Finalize parsing and obtain the AST root node.""" + if self._finished: + return + if self._parser == ffi.NULL: + raise ValueError("Parser is closed") + self._node = lib.cmark_parser_finish(self._parser) + if self._node == ffi.NULL: + raise MemoryError("Failed to parse document") + self._finished = True + + def finish(self): + """Finalize parsing and return the root Node of the AST. + + After calling this method, no more text can be fed to the parser. + The returned Node can be used for tree inspection or rendering. + + Returns + ------- + Node + The root document node of the parsed AST. + + Raises + ------ + ValueError + If the parser is closed. + """ + from multimark._node import Node + + self._finish() + return Node._from_ptr(self._node, owner=self) + + def render_html(self, *, sourcepos: bool = False) -> str: + """Finish parsing (if needed) and render as HTML. + + Parameters + ---------- + sourcepos + Include `data-sourcepos` attributes. Default `False`. + + Returns + ------- + str + The rendered HTML string. + """ + self._finish() + opts = self._opts + if sourcepos: + opts |= lib.CMARK_OPT_SOURCEPOS + ext_list = lib.cmark_parser_get_syntax_extensions(self._parser) + result_ptr = lib.cmark_render_html(self._node, opts, ext_list) + if result_ptr == ffi.NULL: + raise MemoryError("Failed to render document") + result = ffi.string(result_ptr).decode("utf-8") + lib.free(result_ptr) + return result + + def render_xml(self, *, sourcepos: bool = False) -> str: + """Finish parsing (if needed) and render as XML. + + Parameters + ---------- + sourcepos + Include `sourcepos` attributes. Default `False`. + + Returns + ------- + str + The rendered XML string. + """ + self._finish() + opts = self._opts + if sourcepos: + opts |= lib.CMARK_OPT_SOURCEPOS + result_ptr = lib.cmark_render_xml(self._node, opts) + if result_ptr == ffi.NULL: + raise MemoryError("Failed to render document") + result = ffi.string(result_ptr).decode("utf-8") + lib.free(result_ptr) + return result + + def render_latex(self, *, width: int = 0) -> str: + """Finish parsing (if needed) and render as LaTeX. + + Parameters + ---------- + width + Line wrapping column (0 = no wrapping). Default `0`. + + Returns + ------- + str + The rendered LaTeX string. + """ + self._finish() + result_ptr = lib.cmark_render_latex(self._node, self._opts, width) + if result_ptr == ffi.NULL: + raise MemoryError("Failed to render document") + result = ffi.string(result_ptr).decode("utf-8", errors="replace") + lib.free(result_ptr) + return result + + def render_man(self, *, width: int = 0) -> str: + """Finish parsing (if needed) and render as a groff man page. + + Parameters + ---------- + width + Line wrapping column (0 = no wrapping). Default `0`. + + Returns + ------- + str + The rendered man page string. + """ + self._finish() + result_ptr = lib.cmark_render_man(self._node, self._opts, width) + if result_ptr == ffi.NULL: + raise MemoryError("Failed to render document") + result = ffi.string(result_ptr).decode("utf-8", errors="replace") + lib.free(result_ptr) + return result + + def render_commonmark(self, *, width: int = 0) -> str: + """Finish parsing (if needed) and render as normalized CommonMark. + + Parameters + ---------- + width + Line wrapping column (0 = no wrapping). Default `0`. + + Returns + ------- + str + The normalized CommonMark string. + """ + self._finish() + result_ptr = lib.cmark_render_commonmark(self._node, self._opts, width) + if result_ptr == ffi.NULL: + raise MemoryError("Failed to render document") + result = ffi.string(result_ptr).decode("utf-8", errors="replace") + lib.free(result_ptr) + return result + + def close(self) -> None: + """Release all C resources held by this parser. + + After closing, the parser cannot be used. This is called automatically + when used as a context manager. + """ + if self._node != ffi.NULL: + lib.cmark_node_free(self._node) + self._node = ffi.NULL + if self._parser != ffi.NULL: + lib.cmark_parser_free(self._parser) + self._parser = ffi.NULL + + def __enter__(self): + return self + + def __exit__(self, *exc): + self.close() + return False + + def __del__(self): + self.close() diff --git a/src/multimark/cmark.cffi.h b/src/multimark/cmark.cffi.h index 686517a..078cd0b 100644 --- a/src/multimark/cmark.cffi.h +++ b/src/multimark/cmark.cffi.h @@ -34,6 +34,104 @@ const char *cmark_version_string(void); void free(void *ptr); +/* Tree traversal */ +cmark_node *cmark_node_next(cmark_node *node); +cmark_node *cmark_node_previous(cmark_node *node); +cmark_node *cmark_node_parent(cmark_node *node); +cmark_node *cmark_node_first_child(cmark_node *node); +cmark_node *cmark_node_last_child(cmark_node *node); + +/* Node type enum */ +typedef enum { + CMARK_NODE_NONE = ..., + CMARK_NODE_DOCUMENT = ..., + CMARK_NODE_BLOCK_QUOTE = ..., + CMARK_NODE_LIST = ..., + CMARK_NODE_ITEM = ..., + CMARK_NODE_CODE_BLOCK = ..., + CMARK_NODE_HTML_BLOCK = ..., + CMARK_NODE_CUSTOM_BLOCK = ..., + CMARK_NODE_PARAGRAPH = ..., + CMARK_NODE_HEADING = ..., + CMARK_NODE_THEMATIC_BREAK = ..., + CMARK_NODE_FOOTNOTE_DEFINITION = ..., + CMARK_NODE_TEXT = ..., + CMARK_NODE_SOFTBREAK = ..., + CMARK_NODE_LINEBREAK = ..., + CMARK_NODE_CODE = ..., + CMARK_NODE_HTML_INLINE = ..., + CMARK_NODE_CUSTOM_INLINE = ..., + CMARK_NODE_EMPH = ..., + CMARK_NODE_STRONG = ..., + CMARK_NODE_LINK = ..., + CMARK_NODE_IMAGE = ..., + CMARK_NODE_FOOTNOTE_REFERENCE = ..., +} cmark_node_type; + +/* List type enum */ +typedef enum { + CMARK_NO_LIST = ..., + CMARK_BULLET_LIST = ..., + CMARK_ORDERED_LIST = ..., +} cmark_list_type; + +/* Delimiter type enum */ +typedef enum { + CMARK_NO_DELIM = ..., + CMARK_PERIOD_DELIM = ..., + CMARK_PAREN_DELIM = ..., +} cmark_delim_type; + +/* Event type enum */ +typedef enum { + CMARK_EVENT_NONE = ..., + CMARK_EVENT_DONE = ..., + CMARK_EVENT_ENTER = ..., + CMARK_EVENT_EXIT = ..., +} cmark_event_type; + +/* Node introspection */ +cmark_node_type cmark_node_get_type(cmark_node *node); +const char *cmark_node_get_type_string(cmark_node *node); +const char *cmark_node_get_literal(cmark_node *node); +int cmark_node_get_heading_level(cmark_node *node); +cmark_list_type cmark_node_get_list_type(cmark_node *node); +cmark_delim_type cmark_node_get_list_delim(cmark_node *node); +int cmark_node_get_list_start(cmark_node *node); +int cmark_node_get_list_tight(cmark_node *node); +const char *cmark_node_get_fence_info(cmark_node *node); +const char *cmark_node_get_url(cmark_node *node); +const char *cmark_node_get_title(cmark_node *node); +int cmark_node_get_start_line(cmark_node *node); +int cmark_node_get_start_column(cmark_node *node); +int cmark_node_get_end_line(cmark_node *node); +int cmark_node_get_end_column(cmark_node *node); + +/* Node creation and mutation */ +cmark_node *cmark_node_new(cmark_node_type type); +void cmark_node_unlink(cmark_node *node); +int cmark_node_insert_before(cmark_node *node, cmark_node *sibling); +int cmark_node_insert_after(cmark_node *node, cmark_node *sibling); +int cmark_node_prepend_child(cmark_node *node, cmark_node *child); +int cmark_node_append_child(cmark_node *node, cmark_node *child); +int cmark_node_replace(cmark_node *oldnode, cmark_node *newnode); +int cmark_node_set_literal(cmark_node *node, const char *content); +int cmark_node_set_heading_level(cmark_node *node, int level); +int cmark_node_set_url(cmark_node *node, const char *url); +int cmark_node_set_title(cmark_node *node, const char *title); +int cmark_node_set_list_type(cmark_node *node, cmark_list_type type); +int cmark_node_set_list_start(cmark_node *node, int start); +int cmark_node_set_list_tight(cmark_node *node, int tight); +int cmark_node_set_fence_info(cmark_node *node, const char *info); + +/* Iterator */ +typedef struct cmark_iter cmark_iter; +cmark_iter *cmark_iter_new(cmark_node *root); +void cmark_iter_free(cmark_iter *iter); +cmark_event_type cmark_iter_next(cmark_iter *iter); +cmark_node *cmark_iter_get_node(cmark_iter *iter); +cmark_event_type cmark_iter_get_event_type(cmark_iter *iter); + /* Core options */ #define CMARK_OPT_DEFAULT ... #define CMARK_OPT_SOURCEPOS ... diff --git a/tests/test_ast.py b/tests/test_ast.py new file mode 100644 index 0000000..9b4b6bb --- /dev/null +++ b/tests/test_ast.py @@ -0,0 +1,629 @@ +import pytest + +from multimark import parse, Node, NodeType, ListType, DelimType, Options + + +class TestParse: + """Tests for the parse() function.""" + + def test_basic_parse(self): + doc = parse("hello") + assert doc.type == NodeType.DOCUMENT + + def test_empty_string(self): + doc = parse("") + assert doc.type == NodeType.DOCUMENT + assert doc.first_child is None + + def test_parse_type_error(self): + with pytest.raises(TypeError, match="Expected str"): + parse(123) + + def test_parse_bytes_type_error(self): + with pytest.raises(TypeError, match="Expected str"): + parse(b"hello") + + def test_parse_with_extensions(self): + doc = parse("| A |\n|---|\n| 1 |\n", extensions=["table"]) + found_table = False + for event, node in doc.walk(): + if event == "enter" and node.type_string == "table": + found_table = True + assert found_table + + def test_parse_invalid_extension(self): + with pytest.raises(ValueError, match="Unknown extension"): + parse("hello", extensions=["bogus"]) + + def test_parse_smart(self): + doc = parse('"Hello"', smart=True) + for event, node in doc.walk(): + if node.type == NodeType.TEXT: + assert "\u201c" in node.literal + break + + def test_parse_with_options_bitmask(self): + doc = parse("# Hello\n", options=int(Options.SMART)) + assert doc.type == NodeType.DOCUMENT + + +class TestNodeType: + """Tests for NodeType enum.""" + + def test_block_types(self): + assert NodeType.DOCUMENT is not None + assert NodeType.PARAGRAPH is not None + assert NodeType.HEADING is not None + assert NodeType.BLOCK_QUOTE is not None + assert NodeType.LIST is not None + assert NodeType.ITEM is not None + assert NodeType.CODE_BLOCK is not None + assert NodeType.THEMATIC_BREAK is not None + + def test_inline_types(self): + assert NodeType.TEXT is not None + assert NodeType.EMPH is not None + assert NodeType.STRONG is not None + assert NodeType.LINK is not None + assert NodeType.IMAGE is not None + assert NodeType.CODE is not None + assert NodeType.SOFTBREAK is not None + assert NodeType.LINEBREAK is not None + + def test_html_types(self): + assert NodeType.HTML_BLOCK is not None + assert NodeType.HTML_INLINE is not None + + def test_node_type_values_are_ints(self): + assert isinstance(NodeType.DOCUMENT.value, int) + assert isinstance(NodeType.TEXT.value, int) + + +class TestNodeTraversal: + """Tests for tree traversal properties.""" + + def test_first_child(self): + doc = parse("# Hello\n\nWorld\n") + heading = doc.first_child + assert heading.type == NodeType.HEADING + + def test_last_child(self): + doc = parse("# Hello\n\nWorld\n") + para = doc.last_child + assert para.type == NodeType.PARAGRAPH + + def test_next_sibling(self): + doc = parse("# Hello\n\nWorld\n") + heading = doc.first_child + para = heading.next + assert para.type == NodeType.PARAGRAPH + + def test_previous_sibling(self): + doc = parse("# Hello\n\nWorld\n") + para = doc.last_child + heading = para.previous + assert heading.type == NodeType.HEADING + + def test_parent(self): + doc = parse("**bold**") + para = doc.first_child + assert para.parent is doc + + def test_parent_of_root_is_none(self): + doc = parse("hello") + assert doc.parent is None + + def test_next_of_last_is_none(self): + doc = parse("hello") + last = doc.last_child + assert last.next is None + + def test_previous_of_first_is_none(self): + doc = parse("hello") + first = doc.first_child + assert first.previous is None + + def test_children_iterator(self): + doc = parse("# One\n\nTwo\n\nThree\n") + children = list(doc.children) + assert len(children) == 3 + assert children[0].type == NodeType.HEADING + assert children[1].type == NodeType.PARAGRAPH + assert children[2].type == NodeType.PARAGRAPH + + def test_children_of_leaf(self): + doc = parse("hello") + text_node = doc.first_child.first_child # paragraph > text + children = list(text_node.children) + assert children == [] + + def test_node_identity(self): + doc = parse("hello") + assert doc.first_child is doc.first_child + + +class TestNodeWalk: + """Tests for the walk() iterator.""" + + def test_walk_events(self): + doc = parse("**bold**") + events = list(doc.walk()) + # Should have enter/exit pairs for container nodes + event_types = [e for e, _ in events] + assert "enter" in event_types + assert "exit" in event_types + + def test_walk_enter_exit_pairs(self): + doc = parse("**bold**") + enters = [(e, n.type_string) for e, n in doc.walk() if e == "enter"] + exits = [(e, n.type_string) for e, n in doc.walk() if e == "exit"] + # Container nodes should have matching enter/exit + enter_types = [t for _, t in enters] + exit_types = [t for _, t in exits] + assert "document" in enter_types + assert "document" in exit_types + + def test_walk_text_only_enter(self): + doc = parse("hello") + for event, node in doc.walk(): + if node.type == NodeType.TEXT: + assert event == "enter" + + def test_walk_heading(self): + doc = parse("# Hello\n") + found = False + for event, node in doc.walk(): + if event == "enter" and node.type == NodeType.HEADING: + assert node.heading_level == 1 + found = True + assert found + + def test_walk_link(self): + doc = parse("[text](http://example.com)\n") + found = False + for event, node in doc.walk(): + if event == "enter" and node.type == NodeType.LINK: + assert node.url == "http://example.com" + found = True + assert found + + def test_walk_collect_all_text(self): + doc = parse("Hello **world** end") + texts = [] + for event, node in doc.walk(): + if event == "enter" and node.type == NodeType.TEXT: + texts.append(node.literal) + assert texts == ["Hello ", "world", " end"] + + +class TestNodeProperties: + """Tests for node property accessors.""" + + def test_heading_level(self): + for level in range(1, 7): + doc = parse(f"{'#' * level} Heading\n") + h = doc.first_child + assert h.heading_level == level + + def test_literal_text(self): + doc = parse("hello world") + text_node = doc.first_child.first_child + assert text_node.literal == "hello world" + + def test_literal_code(self): + doc = parse("`code`") + for event, node in doc.walk(): + if node.type == NodeType.CODE: + assert node.literal == "code" + + def test_literal_none_for_containers(self): + doc = parse("hello") + assert doc.literal is None # DOCUMENT has no literal + + def test_url_link(self): + doc = parse("[text](http://example.com)\n") + for event, node in doc.walk(): + if node.type == NodeType.LINK: + assert node.url == "http://example.com" + break + + def test_title_link(self): + doc = parse('[text](http://x.com "My Title")\n') + for event, node in doc.walk(): + if node.type == NodeType.LINK: + assert node.title == "My Title" + break + + def test_url_image(self): + doc = parse("![alt](http://img.com/photo.png)\n") + for event, node in doc.walk(): + if node.type == NodeType.IMAGE: + assert node.url == "http://img.com/photo.png" + break + + def test_list_type_bullet(self): + doc = parse("- one\n- two\n") + for event, node in doc.walk(): + if node.type == NodeType.LIST: + assert node.list_type == ListType.BULLET + break + + def test_list_type_ordered(self): + doc = parse("1. one\n2. two\n") + for event, node in doc.walk(): + if node.type == NodeType.LIST: + assert node.list_type == ListType.ORDERED + assert node.list_start == 1 + break + + def test_list_start_nonone(self): + doc = parse("3. three\n4. four\n") + for event, node in doc.walk(): + if node.type == NodeType.LIST: + assert node.list_start == 3 + break + + def test_list_tight(self): + doc = parse("- one\n- two\n") + for event, node in doc.walk(): + if node.type == NodeType.LIST: + assert node.list_tight is True + break + + def test_list_loose(self): + doc = parse("- one\n\n- two\n") + for event, node in doc.walk(): + if node.type == NodeType.LIST: + assert node.list_tight is False + break + + def test_fence_info(self): + doc = parse("```python\ncode\n```\n") + for event, node in doc.walk(): + if node.type == NodeType.CODE_BLOCK: + assert node.fence_info == "python" + break + + def test_fence_info_empty(self): + doc = parse("```\ncode\n```\n") + for event, node in doc.walk(): + if node.type == NodeType.CODE_BLOCK: + assert node.fence_info == "" + break + + def test_type_string(self): + doc = parse("hello") + assert doc.type_string == "document" + assert doc.first_child.type_string == "paragraph" + + +class TestNodeSourcepos: + """Tests for source position properties.""" + + def test_heading_sourcepos(self): + doc = parse("# Hello\n", options=int(Options.SOURCEPOS)) + h = doc.first_child + assert h.start_line == 1 + assert h.start_column == 1 + assert h.end_line == 1 + + def test_multiline_sourcepos(self): + doc = parse("# H1\n\npara\n", options=int(Options.SOURCEPOS)) + para = doc.last_child + assert para.start_line == 3 + + def test_sourcepos_zero_without_flag(self): + # Without SOURCEPOS option, positions should still be available + # (cmark always tracks them; the option controls HTML output) + doc = parse("# Hello\n") + h = doc.first_child + assert h.start_line == 1 + + +class TestNodeRendering: + """Tests for rendering from Node.""" + + def test_render_html(self): + doc = parse("**bold**") + assert doc.render_html() == "

bold

\n" + + def test_render_html_unsafe(self): + doc = parse("
raw
", unsafe=True) + html = doc.render_html(unsafe=True) + assert "
raw
" in html + + def test_render_html_sourcepos(self): + doc = parse("hello") + html = doc.render_html(sourcepos=True) + assert "data-sourcepos" in html + + def test_render_xml(self): + doc = parse("**bold**") + xml = doc.render_xml() + assert "" in xml + + def test_render_latex(self): + doc = parse("**bold**") + latex = doc.render_latex() + assert "\\textbf{bold}" in latex + + def test_render_man(self): + doc = parse("**bold**") + man = doc.render_man() + assert "\\f[B]bold\\f[]" in man + + def test_render_commonmark(self): + doc = parse("*italic*") + cm = doc.render_commonmark() + assert "*italic*" in cm + + def test_render_subtree(self): + doc = parse("# Heading\n\nParagraph\n") + para = doc.last_child + html = para.render_html() + assert "

Paragraph

" in html + assert "

" not in html + + +class TestNodeMutation: + """Tests for AST mutation.""" + + def test_set_literal(self): + doc = parse("hello") + text_node = doc.first_child.first_child + text_node.literal = "goodbye" + assert "goodbye" in doc.render_html() + assert "hello" not in doc.render_html() + + def test_set_url(self): + doc = parse("[text](http://old.com)\n") + for _, node in doc.walk(): + if node.type == NodeType.LINK: + node.url = "http://new.com" + break + assert "http://new.com" in doc.render_html() + + def test_set_title(self): + doc = parse('[text](http://x.com "old")\n') + for _, node in doc.walk(): + if node.type == NodeType.LINK: + node.title = "new title" + break + # Title appears in rendered HTML + assert "new title" in doc.render_html() + + def test_set_heading_level(self): + doc = parse("# H1\n") + h = doc.first_child + h.heading_level = 3 + assert "

" in doc.render_html() + + def test_set_list_type(self): + doc = parse("- one\n- two\n") + for _, node in doc.walk(): + if node.type == NodeType.LIST: + node.list_type = ListType.ORDERED + node.list_start = 1 + break + html = doc.render_html() + assert "
    " in html + + def test_set_list_start(self): + doc = parse("1. one\n2. two\n") + for _, node in doc.walk(): + if node.type == NodeType.LIST: + node.list_start = 5 + break + html = doc.render_html() + assert 'start="5"' in html + + def test_set_list_tight(self): + doc = parse("- one\n- two\n") + for _, node in doc.walk(): + if node.type == NodeType.LIST: + node.list_tight = False + break + # Loose lists have

    inside items + html = doc.render_html() + assert "

    " in html + + def test_set_fence_info(self): + doc = parse("```\ncode\n```\n") + for _, node in doc.walk(): + if node.type == NodeType.CODE_BLOCK: + node.fence_info = "python" + break + html = doc.render_html() + assert "python" in html + + def test_unlink(self): + doc = parse("# Heading\n\nPara\n") + heading = doc.first_child + heading.unlink() + html = doc.render_html() + assert "

    " not in html + assert "

    Para

    " in html + + def test_append_child(self): + doc = parse("hello\n") + new_para = Node.new(NodeType.PARAGRAPH) + new_text = Node.new(NodeType.TEXT) + new_text.literal = "appended" + new_para.append_child(new_text) + doc.append_child(new_para) + html = doc.render_html() + assert "appended" in html + + def test_prepend_child(self): + doc = parse("hello\n") + heading = Node.new(NodeType.HEADING) + heading.heading_level = 1 + text = Node.new(NodeType.TEXT) + text.literal = "Title" + heading.append_child(text) + doc.prepend_child(heading) + html = doc.render_html() + assert html.startswith("

    Title

    \n

    hello

    ") + + def test_insert_before(self): + doc = parse("# H1\n\nParagraph\n") + para = doc.last_child + new_para = Node.new(NodeType.PARAGRAPH) + text = Node.new(NodeType.TEXT) + text.literal = "inserted" + new_para.append_child(text) + para.insert_before(new_para) + html = doc.render_html() + # "inserted" should come before "Paragraph" + assert html.index("inserted") < html.index("Paragraph") + + def test_insert_after(self): + doc = parse("# H1\n\nParagraph\n") + heading = doc.first_child + new_para = Node.new(NodeType.PARAGRAPH) + text = Node.new(NodeType.TEXT) + text.literal = "after heading" + new_para.append_child(text) + heading.insert_after(new_para) + html = doc.render_html() + assert html.index("after heading") < html.index("Paragraph") + + def test_replace(self): + doc = parse("# Old\n\nPara\n") + heading = doc.first_child + new_heading = Node.new(NodeType.HEADING) + new_heading.heading_level = 2 + text = Node.new(NodeType.TEXT) + text.literal = "New" + new_heading.append_child(text) + heading.replace(new_heading) + html = doc.render_html() + assert "

    New

    " in html + assert "

    " not in html + + +class TestNodeNew: + """Tests for Node.new() factory.""" + + def test_new_text(self): + n = Node.new(NodeType.TEXT) + assert n.type == NodeType.TEXT + n.literal = "hello" + assert n.literal == "hello" + + def test_new_heading(self): + n = Node.new(NodeType.HEADING) + n.heading_level = 3 + assert n.heading_level == 3 + + def test_new_paragraph(self): + n = Node.new(NodeType.PARAGRAPH) + assert n.type == NodeType.PARAGRAPH + + def test_new_link(self): + n = Node.new(NodeType.LINK) + n.url = "http://example.com" + n.title = "Example" + assert n.url == "http://example.com" + assert n.title == "Example" + + def test_new_code_block(self): + n = Node.new(NodeType.CODE_BLOCK) + n.literal = "print('hello')" + n.fence_info = "python" + assert n.literal == "print('hello')" + assert n.fence_info == "python" + + def test_new_list(self): + n = Node.new(NodeType.LIST) + n.list_type = ListType.ORDERED + n.list_start = 1 + assert n.list_type == ListType.ORDERED + + +class TestNodeRepr: + """Tests for Node.__repr__.""" + + def test_document_repr(self): + doc = parse("hello") + assert "document" in repr(doc) + + def test_heading_repr(self): + doc = parse("# Hello\n") + h = doc.first_child + assert "heading" in repr(h) + assert "level=1" in repr(h) + + def test_text_repr(self): + doc = parse("hello world") + text = doc.first_child.first_child + r = repr(text) + assert "text" in r + assert "hello" in r + + def test_link_repr(self): + doc = parse("[t](http://x.com)\n") + for _, node in doc.walk(): + if node.type == NodeType.LINK: + assert "http://x.com" in repr(node) + break + + def test_long_text_truncated(self): + doc = parse("a" * 100) + text = doc.first_child.first_child + r = repr(text) + assert "..." in r + assert len(r) < 100 + + +class TestNodeEquality: + """Tests for Node equality and hashing.""" + + def test_same_node_equal(self): + doc = parse("hello") + assert doc.first_child == doc.first_child + + def test_different_nodes_not_equal(self): + doc = parse("# A\n\nB\n") + assert doc.first_child != doc.last_child + + def test_node_hashable(self): + doc = parse("hello") + s = {doc, doc.first_child} + assert len(s) == 2 + + def test_identity_preserved(self): + doc = parse("hello") + a = doc.first_child + b = doc.first_child + assert a is b + + +class TestNodeErrors: + """Tests for error handling in Node operations.""" + + def test_set_literal_type_error(self): + doc = parse("hello") + text = doc.first_child.first_child + with pytest.raises(TypeError): + text.literal = 123 + + def test_set_url_type_error(self): + doc = parse("[t](http://x.com)\n") + for _, node in doc.walk(): + if node.type == NodeType.LINK: + with pytest.raises(TypeError): + node.url = 123 + break + + def test_set_heading_level_on_non_heading(self): + doc = parse("hello") + para = doc.first_child + with pytest.raises(ValueError): + para.heading_level = 1 + + def test_set_literal_on_container(self): + doc = parse("hello") + with pytest.raises(ValueError): + doc.literal = "text" diff --git a/tests/test_parser.py b/tests/test_parser.py new file mode 100644 index 0000000..163ca49 --- /dev/null +++ b/tests/test_parser.py @@ -0,0 +1,274 @@ +"""Tests for the streaming Parser class.""" + +import pytest + +from multimark import Parser, markdown_to_html + + +class TestParserBasic: + """Basic Parser lifecycle.""" + + def test_simple_render_html(self): + p = Parser() + p.feed("**bold**") + assert p.render_html() == "

    bold

    \n" + + def test_multiple_feeds(self): + p = Parser() + p.feed("# Title\n\n") + p.feed("Para ") + p.feed("text.\n") + assert p.render_html() == "

    Title

    \n

    Para text.

    \n" + + def test_empty_document(self): + p = Parser() + p.feed("") + assert p.render_html() == "" + + def test_no_feed(self): + p = Parser() + assert p.render_html() == "" + + def test_render_multiple_times(self): + p = Parser() + p.feed("hello") + html1 = p.render_html() + html2 = p.render_html() + assert html1 == html2 + + def test_equivalence_with_one_shot(self): + text = "# Hello\n\nA *paragraph* with `code`.\n\n> blockquote\n" + p = Parser() + p.feed(text) + assert p.render_html() == markdown_to_html(text) + + def test_chunked_equivalence(self): + text = "# Hello\n\nA *paragraph* with `code`.\n\n> blockquote\n" + p = Parser() + for char in text: + p.feed(char) + assert p.render_html() == markdown_to_html(text) + + +class TestParserOptions: + """Parser options (smart, unsafe, etc.).""" + + def test_smart(self): + p = Parser(smart=True) + p.feed('"Hello" -- world') + html = p.render_html() + assert "\u201c" in html # left curly quote + assert "\u2013" in html # en-dash + + def test_unsafe(self): + p = Parser(unsafe=True) + p.feed("
    raw
    ") + assert "
    raw
    " in p.render_html() + + def test_safe_default(self): + p = Parser() + p.feed("
    raw
    ") + assert "
    " not in p.render_html() + + def test_hardbreaks(self): + p = Parser(hardbreaks=True) + p.feed("line1\nline2") + assert "
    " in p.render_html() + + def test_footnotes(self): + p = Parser(footnotes=True) + p.feed("Text[^1]\n\n[^1]: Footnote\n") + html = p.render_html() + assert "footnote" in html.lower() or "fn" in html.lower() + + def test_sourcepos(self): + p = Parser() + p.feed("# Hello\n") + html = p.render_html(sourcepos=True) + assert "data-sourcepos" in html + + +class TestParserExtensions: + """Parser with GFM extensions.""" + + def test_table(self): + p = Parser(extensions=["table"]) + p.feed("| A | B |\n|---|---|\n| 1 | 2 |\n") + html = p.render_html() + assert "" in html + assert "" in html + + def test_strikethrough(self): + p = Parser(extensions=["strikethrough"]) + p.feed("~~deleted~~") + assert "deleted" in p.render_html() + + def test_autolink(self): + p = Parser(extensions=["autolink"]) + p.feed("Visit https://example.com today") + html = p.render_html() + assert 'href="https://example.com"' in html + + def test_tasklist(self): + p = Parser(extensions=["tasklist"], unsafe=True) + p.feed("- [ ] todo\n- [x] done\n") + html = p.render_html() + assert "checkbox" in html or "type=\"checkbox\"" in html + + def test_multiple_extensions(self): + p = Parser(extensions=["table", "strikethrough", "autolink"]) + p.feed("~~del~~ and https://x.com\n\n| A |\n|---|\n| 1 |\n") + html = p.render_html() + assert "" in html + assert "
    1
    " in html + assert "href" in html + + def test_invalid_extension(self): + with pytest.raises(ValueError, match="Unknown extension"): + Parser(extensions=["nonexistent"]) + + def test_extension_equivalence(self): + text = "| A | B |\n|---|---|\n| 1 | 2 |\n" + p = Parser(extensions=["table"]) + p.feed(text) + assert p.render_html() == markdown_to_html(text, extensions=["table"]) + + +class TestParserRenderers: + """Parser rendering to all output formats.""" + + def test_render_xml(self): + p = Parser() + p.feed("**bold**") + xml = p.render_xml() + assert "" in xml + assert "hello

    \n" + + def test_context_manager_cleanup(self): + with Parser() as p: + p.feed("hello") + with pytest.raises(ValueError, match="closed"): + p.feed("more") + + def test_feed_after_close(self): + p = Parser() + p.feed("hello") + p.close() + with pytest.raises(ValueError, match="closed"): + p.feed("more") + + def test_render_after_close(self): + p = Parser() + p.feed("hello") + p.close() + with pytest.raises(ValueError, match="closed"): + p.render_html() + + def test_feed_after_finish(self): + p = Parser() + p.feed("hello") + p.render_html() # implicitly finishes + with pytest.raises(ValueError, match="finished"): + p.feed("more") + + def test_double_close(self): + p = Parser() + p.close() + p.close() # should not raise + + def test_feed_type_error(self): + p = Parser() + with pytest.raises(TypeError, match="Expected str"): + p.feed(123) + + def test_feed_bytes_type_error(self): + p = Parser() + with pytest.raises(TypeError, match="Expected str"): + p.feed(b"hello") + + +class TestParserFinish: + """Parser.finish() returning a Node.""" + + def test_finish_returns_node(self): + from multimark import NodeType + + p = Parser() + p.feed("# Hello\n") + root = p.finish() + assert root.type == NodeType.DOCUMENT + assert root.first_child.type == NodeType.HEADING + + def test_finish_with_extensions(self): + from multimark import NodeType + + p = Parser(extensions=["table"]) + p.feed("| A |\n|---|\n| 1 |\n") + root = p.finish() + # Walk to find table node + found_table = False + for event, node in root.walk(): + if event == "enter" and node.type_string == "table": + found_table = True + assert found_table + + def test_finish_and_render_equivalence(self): + p = Parser(smart=True) + p.feed('"Hello" -- world') + root = p.finish() + # Rendering from the Node should match rendering from Parser + node_html = root.render_html() + # Both should contain smart punctuation since parsed with smart=True + assert "\u201c" in node_html diff --git a/third_party/cmark-gfm/extensions/autolink.o b/third_party/cmark-gfm/extensions/autolink.o new file mode 100644 index 0000000..fbd81a2 Binary files /dev/null and b/third_party/cmark-gfm/extensions/autolink.o differ diff --git a/third_party/cmark-gfm/extensions/core-extensions.o b/third_party/cmark-gfm/extensions/core-extensions.o new file mode 100644 index 0000000..4e19cde Binary files /dev/null and b/third_party/cmark-gfm/extensions/core-extensions.o differ diff --git a/third_party/cmark-gfm/extensions/ext_scanners.o b/third_party/cmark-gfm/extensions/ext_scanners.o new file mode 100644 index 0000000..b392c56 Binary files /dev/null and b/third_party/cmark-gfm/extensions/ext_scanners.o differ diff --git a/third_party/cmark-gfm/extensions/strikethrough.o b/third_party/cmark-gfm/extensions/strikethrough.o new file mode 100644 index 0000000..6b70f51 Binary files /dev/null and b/third_party/cmark-gfm/extensions/strikethrough.o differ diff --git a/third_party/cmark-gfm/extensions/table.o b/third_party/cmark-gfm/extensions/table.o new file mode 100644 index 0000000..416ce2d Binary files /dev/null and b/third_party/cmark-gfm/extensions/table.o differ diff --git a/third_party/cmark-gfm/extensions/tagfilter.o b/third_party/cmark-gfm/extensions/tagfilter.o new file mode 100644 index 0000000..c04e84c Binary files /dev/null and b/third_party/cmark-gfm/extensions/tagfilter.o differ diff --git a/third_party/cmark-gfm/extensions/tasklist.o b/third_party/cmark-gfm/extensions/tasklist.o new file mode 100644 index 0000000..0ba2d84 Binary files /dev/null and b/third_party/cmark-gfm/extensions/tasklist.o differ diff --git a/third_party/cmark-gfm/src/arena.o b/third_party/cmark-gfm/src/arena.o new file mode 100644 index 0000000..099bee9 Binary files /dev/null and b/third_party/cmark-gfm/src/arena.o differ diff --git a/third_party/cmark-gfm/src/blocks.o b/third_party/cmark-gfm/src/blocks.o new file mode 100644 index 0000000..fb14980 Binary files /dev/null and b/third_party/cmark-gfm/src/blocks.o differ diff --git a/third_party/cmark-gfm/src/buffer.o b/third_party/cmark-gfm/src/buffer.o new file mode 100644 index 0000000..2fdc934 Binary files /dev/null and b/third_party/cmark-gfm/src/buffer.o differ diff --git a/third_party/cmark-gfm/src/cmark.o b/third_party/cmark-gfm/src/cmark.o new file mode 100644 index 0000000..efe312f Binary files /dev/null and b/third_party/cmark-gfm/src/cmark.o differ diff --git a/third_party/cmark-gfm/src/cmark_ctype.o b/third_party/cmark-gfm/src/cmark_ctype.o new file mode 100644 index 0000000..2f48ab9 Binary files /dev/null and b/third_party/cmark-gfm/src/cmark_ctype.o differ diff --git a/third_party/cmark-gfm/src/commonmark.o b/third_party/cmark-gfm/src/commonmark.o new file mode 100644 index 0000000..4ea837e Binary files /dev/null and b/third_party/cmark-gfm/src/commonmark.o differ diff --git a/third_party/cmark-gfm/src/footnotes.o b/third_party/cmark-gfm/src/footnotes.o new file mode 100644 index 0000000..85e7b98 Binary files /dev/null and b/third_party/cmark-gfm/src/footnotes.o differ diff --git a/third_party/cmark-gfm/src/houdini_href_e.o b/third_party/cmark-gfm/src/houdini_href_e.o new file mode 100644 index 0000000..718ea27 Binary files /dev/null and b/third_party/cmark-gfm/src/houdini_href_e.o differ diff --git a/third_party/cmark-gfm/src/houdini_html_e.o b/third_party/cmark-gfm/src/houdini_html_e.o new file mode 100644 index 0000000..1017f9b Binary files /dev/null and b/third_party/cmark-gfm/src/houdini_html_e.o differ diff --git a/third_party/cmark-gfm/src/houdini_html_u.o b/third_party/cmark-gfm/src/houdini_html_u.o new file mode 100644 index 0000000..ecb7ed6 Binary files /dev/null and b/third_party/cmark-gfm/src/houdini_html_u.o differ diff --git a/third_party/cmark-gfm/src/html.o b/third_party/cmark-gfm/src/html.o new file mode 100644 index 0000000..ddac245 Binary files /dev/null and b/third_party/cmark-gfm/src/html.o differ diff --git a/third_party/cmark-gfm/src/inlines.o b/third_party/cmark-gfm/src/inlines.o new file mode 100644 index 0000000..c9cc30d Binary files /dev/null and b/third_party/cmark-gfm/src/inlines.o differ diff --git a/third_party/cmark-gfm/src/iterator.o b/third_party/cmark-gfm/src/iterator.o new file mode 100644 index 0000000..022ba47 Binary files /dev/null and b/third_party/cmark-gfm/src/iterator.o differ diff --git a/third_party/cmark-gfm/src/latex.o b/third_party/cmark-gfm/src/latex.o new file mode 100644 index 0000000..7b7899f Binary files /dev/null and b/third_party/cmark-gfm/src/latex.o differ diff --git a/third_party/cmark-gfm/src/linked_list.o b/third_party/cmark-gfm/src/linked_list.o new file mode 100644 index 0000000..070cbac Binary files /dev/null and b/third_party/cmark-gfm/src/linked_list.o differ diff --git a/third_party/cmark-gfm/src/man.o b/third_party/cmark-gfm/src/man.o new file mode 100644 index 0000000..4c21028 Binary files /dev/null and b/third_party/cmark-gfm/src/man.o differ diff --git a/third_party/cmark-gfm/src/map.o b/third_party/cmark-gfm/src/map.o new file mode 100644 index 0000000..090aa93 Binary files /dev/null and b/third_party/cmark-gfm/src/map.o differ diff --git a/third_party/cmark-gfm/src/node.o b/third_party/cmark-gfm/src/node.o new file mode 100644 index 0000000..7c9db3b Binary files /dev/null and b/third_party/cmark-gfm/src/node.o differ diff --git a/third_party/cmark-gfm/src/plaintext.o b/third_party/cmark-gfm/src/plaintext.o new file mode 100644 index 0000000..75b20ec Binary files /dev/null and b/third_party/cmark-gfm/src/plaintext.o differ diff --git a/third_party/cmark-gfm/src/plugin.o b/third_party/cmark-gfm/src/plugin.o new file mode 100644 index 0000000..9a87d52 Binary files /dev/null and b/third_party/cmark-gfm/src/plugin.o differ diff --git a/third_party/cmark-gfm/src/references.o b/third_party/cmark-gfm/src/references.o new file mode 100644 index 0000000..3e108e0 Binary files /dev/null and b/third_party/cmark-gfm/src/references.o differ diff --git a/third_party/cmark-gfm/src/registry.o b/third_party/cmark-gfm/src/registry.o new file mode 100644 index 0000000..2dcfa35 Binary files /dev/null and b/third_party/cmark-gfm/src/registry.o differ diff --git a/third_party/cmark-gfm/src/render.o b/third_party/cmark-gfm/src/render.o new file mode 100644 index 0000000..12acdd9 Binary files /dev/null and b/third_party/cmark-gfm/src/render.o differ diff --git a/third_party/cmark-gfm/src/scanners.o b/third_party/cmark-gfm/src/scanners.o new file mode 100644 index 0000000..0bdeebf Binary files /dev/null and b/third_party/cmark-gfm/src/scanners.o differ diff --git a/third_party/cmark-gfm/src/syntax_extension.o b/third_party/cmark-gfm/src/syntax_extension.o new file mode 100644 index 0000000..b03c974 Binary files /dev/null and b/third_party/cmark-gfm/src/syntax_extension.o differ diff --git a/third_party/cmark-gfm/src/utf8.o b/third_party/cmark-gfm/src/utf8.o new file mode 100644 index 0000000..b572fc7 Binary files /dev/null and b/third_party/cmark-gfm/src/utf8.o differ diff --git a/third_party/cmark-gfm/src/xml.o b/third_party/cmark-gfm/src/xml.o new file mode 100644 index 0000000..ec494ae Binary files /dev/null and b/third_party/cmark-gfm/src/xml.o differ