crt: Add a UCRT import library suitable for UWP use
This adds libucrtapp.a, which is the same as libucrt.a, but excluding
libapi-ms-win-crt-private-l1-1-0.a, and with a few statically
linked functions added that otherwise normally are linked from
libapi-ms-win-crt-private-l1-1-0.a.
Linking against the private dll (and ucrtbase.dll) is prohibited when
targeting UWP. An app built and packaged with MSVC would link against
these functions from vcruntime140_app.dll, which ends up bundled with
the app itself. However, the goal of this patch is to make it possible
to build a UWP app with mingw tools and redistribute it without bundling
vcruntime140_app.dll or similar ones from MSVC.
By using a separate copy of libucrt*.a, without the forbidden bits, it
gives a clear linker error if an app requires linking against other
functions that aren't implemented yet, instead of silently ending up
depending on the forbidden api-ms-win-crt-private-l1-1-0.dll.
The functions from this DLL, that end up linked in a mingw build,
are primarily one of the these four areas:
- __C_specific_handler
The implementation so far is a dummy; wine should have a suitable
proper implementation for reference. This shouldn't matter much, except
potentially for turning unhandled exceptions into signals (but that
might also be handled via a different mechanism).
- setjmp/longjmp
The implementation should be ok, but doesn't do a SEH unwind (yet) but
just a plain longjmp. A full implementation should be doable, but is
not really needed for mingw code.
- string functions: memcpy and memmove
Added minimal wrappers that just call memcpy_s and memmove_s from
api-ms-win-crt-string-l1-1-0.dll, as that one should have implementations
with good performance.
- string functions: memchr, memcmp, strchr, strrchr, strstr, wcschr, wcsrchr, wcsstr
These are copied from musl (with minor modifications to make them
compile in mingw-w64, and with an added copyright header).
By naming the library libucrtapp.a, clang users can choose to link
against this by passing -lucrtapp (which makes clang omit the default
-lmsvcrt, which would be equal to libucrt.a in such a case).
Signed-off-by: Martin Storsjö <martin@martin.st>
diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index c30e22c..b104da3 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -241,6 +241,23 @@
stdio/ucrt_vsnprintf.c \
stdio/ucrt_vsprintf.c
+src_ucrtapp=\
+ crt/__C_specific_handler.c \
+ misc/longjmp.S \
+ misc/setjmp.S \
+ string/memchr.c \
+ string/memcmp.c \
+ string/memcpy.c \
+ string/memmove.c \
+ string/memrchr.c \
+ string/strchr.c \
+ string/strchrnul.c \
+ string/strrchr.c \
+ string/strstr.c \
+ string/wcschr.c \
+ string/wcsrchr.c \
+ string/wcsstr.c
+
src_msvcrt32=\
$(src_msvcrt) \
math/x86/_copysignf.c \
@@ -862,10 +879,12 @@
lib32_libucrtbase_a_CPPFLAGS=$(CPPFLAGS32) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
EXTRA_lib32_libucrtbase_a_DEPENDENCIES=lib32/ucrtbase.def
-lib32_DATA += lib32/libucrt.a
-noinst_LIBRARIES += lib32/libucrt_extra.a
+lib32_DATA += lib32/libucrt.a lib32/libucrtapp.a
+noinst_LIBRARIES += lib32/libucrt_extra.a lib32/libucrtapp_extra.a
lib32_libucrt_extra_a_SOURCES = $(src_ucrtbase)
lib32_libucrt_extra_a_CPPFLAGS=$(CPPFLAGS32) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
+lib32_libucrtapp_extra_a_SOURCES = $(src_ucrtapp)
+lib32_libucrtapp_extra_a_CPPFLAGS=$(CPPFLAGS32) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
lib32_DATA += lib32/libvcruntime140_app.a
endif
@@ -1189,10 +1208,12 @@
lib64_libucrtbase_a_CPPFLAGS=$(CPPFLAGS64) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
EXTRA_lib64_libucrtbase_a_DEPENDENCIES=lib64/ucrtbase.def
-lib64_DATA += lib64/libucrt.a
-noinst_LIBRARIES += lib64/libucrt_extra.a
+lib64_DATA += lib64/libucrt.a lib64/libucrtapp.a
+noinst_LIBRARIES += lib64/libucrt_extra.a lib64/libucrtapp_extra.a
lib64_libucrt_extra_a_SOURCES = $(src_ucrtbase)
lib64_libucrt_extra_a_CPPFLAGS=$(CPPFLAGS64) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
+lib64_libucrtapp_extra_a_SOURCES = $(src_ucrtapp)
+lib64_libucrtapp_extra_a_CPPFLAGS=$(CPPFLAGS64) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
lib64_DATA += lib64/libvcruntime140_app.a
endif
@@ -1476,10 +1497,12 @@
libarm32_libucrtbase_a_CPPFLAGS=$(CPPFLAGSARM32) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
EXTRA_libarm32_libucrtbase_a_DEPENDENCIES=libarm32/ucrtbase.def
-libarm32_DATA += libarm32/libucrt.a
-noinst_LIBRARIES += libarm32/libucrt_extra.a
+libarm32_DATA += libarm32/libucrt.a libarm32/libucrtapp.a
+noinst_LIBRARIES += libarm32/libucrt_extra.a libarm32/libucrtapp_extra.a
libarm32_libucrt_extra_a_SOURCES = $(src_ucrtbase)
libarm32_libucrt_extra_a_CPPFLAGS=$(CPPFLAGSARM32) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
+libarm32_libucrtapp_extra_a_SOURCES = $(src_ucrtapp)
+libarm32_libucrtapp_extra_a_CPPFLAGS=$(CPPFLAGSARM32) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
libarm32_DATA += libarm32/libvcruntime140_app.a
endif
@@ -1731,10 +1754,12 @@
libarm64_libucrtbase_a_CPPFLAGS=$(CPPFLAGSARM64) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
EXTRA_libarm64_libucrtbase_a_DEPENDENCIES=libarm64/ucrtbase.def
-libarm64_DATA += libarm64/libucrt.a
-noinst_LIBRARIES += libarm64/libucrt_extra.a
+libarm64_DATA += libarm64/libucrt.a libarm64/libucrtapp.a
+noinst_LIBRARIES += libarm64/libucrt_extra.a libarm64/libucrtapp_extra.a
libarm64_libucrt_extra_a_SOURCES = $(src_ucrtbase)
libarm64_libucrt_extra_a_CPPFLAGS=$(CPPFLAGSARM64) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
+libarm64_libucrtapp_extra_a_SOURCES = $(src_ucrtapp)
+libarm64_libucrtapp_extra_a_CPPFLAGS=$(CPPFLAGSARM64) -D__LIBMSVCRT__ $(extra_include) $(sysincludes)
libarm64_DATA += libarm64/libvcruntime140_app.a
endif
@@ -2072,6 +2097,18 @@
cd $(dir $@) && $(AR) -M < $(abspath $<)
$(RANLIB) $@
+# The same as libucrt.a above, but without the -private lib and with some more
+# statically linked functions.
+%/libucrtapp.a: lib-common/ucrtapp.mri %/libucrt_extra.a %/libucrtapp_extra.a \
+ %/libapi-ms-win-crt-conio-l1-1-0.a %/libapi-ms-win-crt-convert-l1-1-0.a %/libapi-ms-win-crt-environment-l1-1-0.a \
+ %/libapi-ms-win-crt-filesystem-l1-1-0.a %/libapi-ms-win-crt-heap-l1-1-0.a %/libapi-ms-win-crt-locale-l1-1-0.a \
+ %/libapi-ms-win-crt-math-l1-1-0.a %/libapi-ms-win-crt-multibyte-l1-1-0.a \
+ %/libapi-ms-win-crt-process-l1-1-0.a %/libapi-ms-win-crt-runtime-l1-1-0.a %/libapi-ms-win-crt-stdio-l1-1-0.a \
+ %/libapi-ms-win-crt-string-l1-1-0.a %/libapi-ms-win-crt-time-l1-1-0.a %/libapi-ms-win-crt-utility-l1-1-0.a
+ rm -f $@
+ cd $(dir $@) && $(AR) -M < $(abspath $<)
+ $(RANLIB) $@
+
%.def: %.def.in
$(MKDIR_P) $(@D) && $(CPP) -x c $< -Wp,-w -undef -P -I$(top_srcdir)/def-include > $@
diff --git a/mingw-w64-crt/crt/__C_specific_handler.c b/mingw-w64-crt/crt/__C_specific_handler.c
new file mode 100644
index 0000000..07f8927
--- /dev/null
+++ b/mingw-w64-crt/crt/__C_specific_handler.c
@@ -0,0 +1,34 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <excpt.h>
+
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
+EXCEPTION_DISPOSITION __cdecl
+__C_specific_handler(struct _EXCEPTION_RECORD *_ExceptionRecord,
+ void *_EstablisherFrame,
+ struct _CONTEXT *_ContextRecord,
+ struct _DISPATCHER_CONTEXT *_DispatcherContext)
+{
+ (void)_ExceptionRecord;
+ (void)_EstablisherFrame;
+ (void)_ContextRecord;
+ (void)_DispatcherContext;
+ // TODO A more comprehensive implementation. Normally this is only used
+ // by the toplevel SEH handler for uncaught exceptions, for calling
+ // signal handlers. If signal handling isn't used, this no-op implementation
+ // should be ok. Wine does contain a supposedly correct implementation of
+ // this for x86_64 at least.
+ return ExceptionContinueSearch;
+}
+
+EXCEPTION_DISPOSITION
+(__cdecl *__MINGW_IMP_SYMBOL(__C_specific_handler))(
+ struct _EXCEPTION_RECORD *_ExceptionRecord,
+ void *_EstablisherFrame,
+ struct _CONTEXT *_ContextRecord,
+ struct _DISPATCHER_CONTEXT *_DispatcherContext) = __C_specific_handler;
+#endif
diff --git a/mingw-w64-crt/lib-common/ucrtapp.mri b/mingw-w64-crt/lib-common/ucrtapp.mri
new file mode 100644
index 0000000..c9c0fb0
--- /dev/null
+++ b/mingw-w64-crt/lib-common/ucrtapp.mri
@@ -0,0 +1,19 @@
+CREATE libucrtapp.a
+ADDLIB libapi-ms-win-crt-conio-l1-1-0.a
+ADDLIB libapi-ms-win-crt-convert-l1-1-0.a
+ADDLIB libapi-ms-win-crt-environment-l1-1-0.a
+ADDLIB libapi-ms-win-crt-filesystem-l1-1-0.a
+ADDLIB libapi-ms-win-crt-heap-l1-1-0.a
+ADDLIB libapi-ms-win-crt-locale-l1-1-0.a
+ADDLIB libapi-ms-win-crt-math-l1-1-0.a
+ADDLIB libapi-ms-win-crt-multibyte-l1-1-0.a
+ADDLIB libapi-ms-win-crt-process-l1-1-0.a
+ADDLIB libapi-ms-win-crt-runtime-l1-1-0.a
+ADDLIB libapi-ms-win-crt-stdio-l1-1-0.a
+ADDLIB libapi-ms-win-crt-string-l1-1-0.a
+ADDLIB libapi-ms-win-crt-time-l1-1-0.a
+ADDLIB libapi-ms-win-crt-utility-l1-1-0.a
+ADDLIB libucrt_extra.a
+ADDLIB libucrtapp_extra.a
+SAVE
+END
diff --git a/mingw-w64-crt/misc/longjmp.S b/mingw-w64-crt/misc/longjmp.S
new file mode 100644
index 0000000..a1318dc
--- /dev/null
+++ b/mingw-w64-crt/misc/longjmp.S
@@ -0,0 +1,97 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <_mingw_mac.h>
+
+ .globl __MINGW_USYMBOL(longjmp)
+ .def __MINGW_USYMBOL(longjmp); .scl 2; .type 32; .endef
+
+__MINGW_USYMBOL(longjmp):
+#if defined(__i386__)
+ movl 4(%esp),%ecx /* jmp_buf */
+ movl 8(%esp),%eax /* retval */
+ movl 0(%ecx),%ebp /* jmp_buf.Ebp */
+ movl 4(%ecx),%ebx /* jmp_buf.Ebx */
+ movl 8(%ecx),%edi /* jmp_buf.Edi */
+ movl 12(%ecx),%esi /* jmp_buf.Esi */
+ movl 16(%ecx),%esp /* jmp_buf.Esp */
+ addl $4,%esp /* get rid of return address */
+ jmp *20(%ecx) /* jmp_buf.Eip */
+#elif defined(__x86_64__)
+ movq %rdx,%rax /* retval */
+ movq 0x8(%rcx),%rbx /* jmp_buf->Rbx */
+ movq 0x18(%rcx),%rbp /* jmp_buf->Rbp */
+ movq 0x20(%rcx),%rsi /* jmp_buf->Rsi */
+ movq 0x28(%rcx),%rdi /* jmp_buf->Rdi */
+ movq 0x30(%rcx),%r12 /* jmp_buf->R12 */
+ movq 0x38(%rcx),%r13 /* jmp_buf->R13 */
+ movq 0x40(%rcx),%r14 /* jmp_buf->R14 */
+ movq 0x48(%rcx),%r15 /* jmp_buf->R15 */
+ movdqa 0x60(%rcx),%xmm6 /* jmp_buf->Xmm6 */
+ movdqa 0x70(%rcx),%xmm7 /* jmp_buf->Xmm7 */
+ movdqa 0x80(%rcx),%xmm8 /* jmp_buf->Xmm8 */
+ movdqa 0x90(%rcx),%xmm9 /* jmp_buf->Xmm9 */
+ movdqa 0xa0(%rcx),%xmm10 /* jmp_buf->Xmm10 */
+ movdqa 0xb0(%rcx),%xmm11 /* jmp_buf->Xmm11 */
+ movdqa 0xc0(%rcx),%xmm12 /* jmp_buf->Xmm12 */
+ movdqa 0xd0(%rcx),%xmm13 /* jmp_buf->Xmm13 */
+ movdqa 0xe0(%rcx),%xmm14 /* jmp_buf->Xmm14 */
+ movdqa 0xf0(%rcx),%xmm15 /* jmp_buf->Xmm15 */
+ movq 0x50(%rcx),%rdx /* jmp_buf->Rip */
+ movq 0x10(%rcx),%rsp /* jmp_buf->Rsp */
+ jmp *%rdx
+#elif defined(__arm__)
+ ldr r4, [r0, #0x4] /* jmp_buf->R4 */
+ ldr r5, [r0, #0x8] /* jmp_buf->R5 */
+ ldr r6, [r0, #0xc] /* jmp_buf->R6 */
+ ldr r7, [r0, #0x10] /* jmp_buf->R7 */
+ ldr r8, [r0, #0x14] /* jmp_buf->R8 */
+ ldr r9, [r0, #0x18] /* jmp_buf->R9 */
+ ldr r10, [r0, #0x1c] /* jmp_buf->R10 */
+ ldr r11, [r0, #0x20] /* jmp_buf->R11 */
+ ldr sp, [r0, #0x24] /* jmp_buf->Sp */
+ ldr r2, [r0, #0x28] /* jmp_buf->Pc */
+ ldr r3, [r0, #0x2c] /* jmp_buf->Fpscr */
+ vmsr fpscr, r3
+ vldr d8, [r0, #0x30] /* jmp_buf->D[0] */
+ vldr d9, [r0, #0x38] /* jmp_buf->D[1] */
+ vldr d10, [r0, #0x40] /* jmp_buf->D[2] */
+ vldr d11, [r0, #0x48] /* jmp_buf->D[3] */
+ vldr d12, [r0, #0x50] /* jmp_buf->D[4] */
+ vldr d13, [r0, #0x58] /* jmp_buf->D[5] */
+ vldr d14, [r0, #0x60] /* jmp_buf->D[6] */
+ vldr d15, [r0, #0x68] /* jmp_buf->D[7] */
+ mov r0, r1 /* retval */
+ bx r2
+#elif defined(__aarch64__)
+ ldp x19, x20, [x0, #0x10] /* jmp_buf->X19, X20 */
+ ldp x21, x22, [x0, #0x20] /* jmp_buf->X21, X22 */
+ ldp x23, x24, [x0, #0x30] /* jmp_buf->X23, X24 */
+ ldp x25, x26, [x0, #0x40] /* jmp_buf->X25, X26 */
+ ldp x27, x28, [x0, #0x50] /* jmp_buf->X27, X28 */
+ ldp x29, x30, [x0, #0x60] /* jmp_buf->Fp, Lr */
+ ldr x2, [x0, #0x70] /* jmp_buf->Sp */
+ mov sp, x2
+ ldr w2, [x0, #0x78] /* jmp_buf->Fpcr */
+ msr fpcr, x2
+ ldr w2, [x0, #0x7c] /* jmp_buf->Fpsr */
+ msr fpsr, x2
+ ldp d8, d9, [x0, #0x80] /* jmp_buf->D[0-1] */
+ ldp d10, d11, [x0, #0x90] /* jmp_buf->D[2-3] */
+ ldp d12, d13, [x0, #0xa0] /* jmp_buf->D[4-5] */
+ ldp d14, d15, [x0, #0xb0] /* jmp_buf->D[6-7] */
+ mov x0, x1 /* retval */
+ ret
+#endif
+
+ .data
+ .globl __MINGW_IMP_LSYMBOL(longjmp)
+__MINGW_IMP_LSYMBOL(longjmp):
+#ifdef _WIN64
+ .quad __MINGW_USYMBOL(longjmp)
+#else
+ .long __MINGW_USYMBOL(longjmp)
+#endif
diff --git a/mingw-w64-crt/misc/setjmp.S b/mingw-w64-crt/misc/setjmp.S
new file mode 100644
index 0000000..b2058e9
--- /dev/null
+++ b/mingw-w64-crt/misc/setjmp.S
@@ -0,0 +1,115 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <_mingw_mac.h>
+
+ .globl __MINGW_USYMBOL(__intrinsic_setjmp)
+ .def __MINGW_USYMBOL(__intrinsic_setjmp); .scl 2; .type 32; .endef
+
+#if defined(_WIN64)
+ .globl __MINGW_USYMBOL(__intrinsic_setjmpex)
+ .def __MINGW_USYMBOL(__intrinsic_setjmpex); .scl 2; .type 32; .endef
+#endif
+
+#if defined(__i386__)
+ .globl __MINGW_USYMBOL(_setjmp3)
+ .def __MINGW_USYMBOL(_setjmp3); .scl 2; .type 32; .endef
+__MINGW_USYMBOL(_setjmp3):
+__MINGW_USYMBOL(__intrinsic_setjmp):
+ movl 4(%esp),%ecx /* jmp_buf */
+ movl %ebp,0(%ecx) /* jmp_buf.Ebp */
+ movl %ebx,4(%ecx) /* jmp_buf.Ebx */
+ movl %edi,8(%ecx) /* jmp_buf.Edi */
+ movl %esi,12(%ecx) /* jmp_buf.Esi */
+ movl %esp,16(%ecx) /* jmp_buf.Esp */
+ movl 0(%esp),%eax
+ movl %eax,20(%ecx) /* jmp_buf.Eip */
+ xorl %eax, %eax
+ retl
+
+#elif defined(__x86_64__)
+ .globl __MINGW_USYMBOL(setjmp)
+ .def __MINGW_USYMBOL(setjmp); .scl 2; .type 32; .endef
+__MINGW_USYMBOL(setjmp):
+__MINGW_USYMBOL(__intrinsic_setjmp):
+ xorq %rdx,%rdx
+__MINGW_USYMBOL(__intrinsic_setjmpex):
+ movq %rdx,(%rcx) /* jmp_buf->Frame */
+ movq %rbx,0x8(%rcx) /* jmp_buf->Rbx */
+ leaq 0x8(%rsp),%rax
+ movq %rax,0x10(%rcx) /* jmp_buf->Rsp */
+ movq %rbp,0x18(%rcx) /* jmp_buf->Rbp */
+ movq %rsi,0x20(%rcx) /* jmp_buf->Rsi */
+ movq %rdi,0x28(%rcx) /* jmp_buf->Rdi */
+ movq %r12,0x30(%rcx) /* jmp_buf->R12 */
+ movq %r13,0x38(%rcx) /* jmp_buf->R13 */
+ movq %r14,0x40(%rcx) /* jmp_buf->R14 */
+ movq %r15,0x48(%rcx) /* jmp_buf->R15 */
+ movq (%rsp),%rax
+ movq %rax,0x50(%rcx) /* jmp_buf->Rip */
+ movdqa %xmm6,0x60(%rcx) /* jmp_buf->Xmm6 */
+ movdqa %xmm7,0x70(%rcx) /* jmp_buf->Xmm7 */
+ movdqa %xmm8,0x80(%rcx) /* jmp_buf->Xmm8 */
+ movdqa %xmm9,0x90(%rcx) /* jmp_buf->Xmm9 */
+ movdqa %xmm10,0xa0(%rcx) /* jmp_buf->Xmm10 */
+ movdqa %xmm11,0xb0(%rcx) /* jmp_buf->Xmm11 */
+ movdqa %xmm12,0xc0(%rcx) /* jmp_buf->Xmm12 */
+ movdqa %xmm13,0xd0(%rcx) /* jmp_buf->Xmm13 */
+ movdqa %xmm14,0xe0(%rcx) /* jmp_buf->Xmm14 */
+ movdqa %xmm15,0xf0(%rcx) /* jmp_buf->Xmm15 */
+ xorq %rax,%rax
+ retq
+
+#elif defined(__arm__)
+__MINGW_USYMBOL(__intrinsic_setjmp):
+ mov r1, #0
+ str r1, [r0] /* jmp_buf->Frame */
+ str r4, [r0, #0x4] /* jmp_buf->R4 */
+ str r5, [r0, #0x8] /* jmp_buf->R5 */
+ str r6, [r0, #0xc] /* jmp_buf->R6 */
+ str r7, [r0, #0x10] /* jmp_buf->R7 */
+ str r8, [r0, #0x14] /* jmp_buf->R8 */
+ str r9, [r0, #0x18] /* jmp_buf->R9 */
+ str r10, [r0, #0x1c] /* jmp_buf->R10 */
+ str r11, [r0, #0x20] /* jmp_buf->R11 */
+ str sp, [r0, #0x24] /* jmp_buf->Sp */
+ str lr, [r0, #0x28] /* jmp_buf->Pc */
+ vmrs r2, fpscr
+ str r2, [r0, #0x2c] /* jmp_buf->Fpscr */
+ vstr d8, [r0, #0x30] /* jmp_buf->D[0] */
+ vstr d9, [r0, #0x38] /* jmp_buf->D[1] */
+ vstr d10, [r0, #0x40] /* jmp_buf->D[2] */
+ vstr d11, [r0, #0x48] /* jmp_buf->D[3] */
+ vstr d12, [r0, #0x50] /* jmp_buf->D[4] */
+ vstr d13, [r0, #0x58] /* jmp_buf->D[5] */
+ vstr d14, [r0, #0x60] /* jmp_buf->D[6] */
+ vstr d15, [r0, #0x68] /* jmp_buf->D[7] */
+ mov r0, #0
+ bx lr
+#elif defined(__aarch64__)
+__MINGW_USYMBOL(__intrinsic_setjmp):
+ mov x1, #0
+__MINGW_USYMBOL(__intrinsic_setjmpex):
+ str x1, [x0] /* jmp_buf->Frame */
+ stp x19, x20, [x0, #0x10] /* jmp_buf->X19, X20 */
+ stp x21, x22, [x0, #0x20] /* jmp_buf->X21, X22 */
+ stp x23, x24, [x0, #0x30] /* jmp_buf->X23, X24 */
+ stp x25, x26, [x0, #0x40] /* jmp_buf->X25, X26 */
+ stp x27, x28, [x0, #0x50] /* jmp_buf->X27, X28 */
+ stp x29, x30, [x0, #0x60] /* jmp_buf->Fp, Lr */
+ mov x2, sp
+ str x2, [x0, #0x70] /* jmp_buf->Sp */
+ mrs x2, fpcr
+ str w2, [x0, #0x78] /* jmp_buf->Fpcr */
+ mrs x2, fpsr
+ str w2, [x0, #0x7c] /* jmp_buf->Fpsr */
+ stp d8, d9, [x0, #0x80] /* jmp_buf->D[0-1] */
+ stp d10, d11, [x0, #0x90] /* jmp_buf->D[2-3] */
+ stp d12, d13, [x0, #0xa0] /* jmp_buf->D[4-5] */
+ stp d14, d15, [x0, #0xb0] /* jmp_buf->D[6-7] */
+ mov x0, #0
+ ret
+#endif
diff --git a/mingw-w64-crt/string/memchr.c b/mingw-w64-crt/string/memchr.c
new file mode 100644
index 0000000..e115afc
--- /dev/null
+++ b/mingw-w64-crt/string/memchr.c
@@ -0,0 +1,50 @@
+/*
+ Copyright © 2005-2020 Rich Felker, et al.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define SS (sizeof(size_t))
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+void *memchr(const void *src, int c, size_t n)
+{
+ const unsigned char *s = src;
+ c = (unsigned char)c;
+#ifdef __GNUC__
+ for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--);
+ if (n && *s != c) {
+ typedef size_t __attribute__((__may_alias__)) word;
+ const word *w;
+ size_t k = ONES * c;
+ for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS);
+ s = (const void *)w;
+ }
+#endif
+ for (; n && *s != c; s++, n--);
+ return n ? (void *)s : 0;
+}
diff --git a/mingw-w64-crt/string/memcmp.c b/mingw-w64-crt/string/memcmp.c
new file mode 100644
index 0000000..95afa90
--- /dev/null
+++ b/mingw-w64-crt/string/memcmp.c
@@ -0,0 +1,31 @@
+/*
+ Copyright © 2005-2020 Rich Felker, et al.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <string.h>
+
+int memcmp(const void *vl, const void *vr, size_t n)
+{
+ const unsigned char *l=vl, *r=vr;
+ for (; n && *l == *r; n--, l++, r++);
+ return n ? *l-*r : 0;
+}
diff --git a/mingw-w64-crt/string/memcpy.c b/mingw-w64-crt/string/memcpy.c
new file mode 100644
index 0000000..106ccaa
--- /dev/null
+++ b/mingw-w64-crt/string/memcpy.c
@@ -0,0 +1,12 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <string.h>
+
+void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
+ memcpy_s(dest, n, src, n);
+ return dest;
+}
diff --git a/mingw-w64-crt/string/memmove.c b/mingw-w64-crt/string/memmove.c
new file mode 100644
index 0000000..7cecc8b
--- /dev/null
+++ b/mingw-w64-crt/string/memmove.c
@@ -0,0 +1,12 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <string.h>
+
+void *memmove(void *dest, const void *src, size_t n) {
+ memmove_s(dest, n, src, n);
+ return dest;
+}
diff --git a/mingw-w64-crt/string/memrchr.c b/mingw-w64-crt/string/memrchr.c
new file mode 100644
index 0000000..83b7b8b
--- /dev/null
+++ b/mingw-w64-crt/string/memrchr.c
@@ -0,0 +1,34 @@
+/*
+ Copyright © 2005-2020 Rich Felker, et al.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <string.h>
+
+void *__memrchr(const void *m, int c, size_t n);
+
+void *__memrchr(const void *m, int c, size_t n)
+{
+ const unsigned char *s = m;
+ c = (unsigned char)c;
+ while (n--) if (s[n]==c) return (void *)(s+n);
+ return 0;
+}
diff --git a/mingw-w64-crt/string/strchr.c b/mingw-w64-crt/string/strchr.c
new file mode 100644
index 0000000..8eecdf5
--- /dev/null
+++ b/mingw-w64-crt/string/strchr.c
@@ -0,0 +1,32 @@
+/*
+ Copyright © 2005-2020 Rich Felker, et al.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <string.h>
+
+char *__strchrnul(const char *s, int c);
+
+char *strchr(const char *s, int c)
+{
+ char *r = __strchrnul(s, c);
+ return *(unsigned char *)r == (unsigned char)c ? r : 0;
+}
diff --git a/mingw-w64-crt/string/strchrnul.c b/mingw-w64-crt/string/strchrnul.c
new file mode 100644
index 0000000..889446a
--- /dev/null
+++ b/mingw-w64-crt/string/strchrnul.c
@@ -0,0 +1,51 @@
+/*
+ Copyright © 2005-2020 Rich Felker, et al.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#define ALIGN (sizeof(size_t))
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+char *__strchrnul(const char *s, int c);
+
+char *__strchrnul(const char *s, int c)
+{
+ c = (unsigned char)c;
+ if (!c) return (char *)s + strlen(s);
+
+#ifdef __GNUC__
+ typedef size_t __attribute__((__may_alias__)) word;
+ const word *w;
+ for (; (uintptr_t)s % ALIGN; s++)
+ if (!*s || *(unsigned char *)s == c) return (char *)s;
+ size_t k = ONES * c;
+ for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++);
+ s = (void *)w;
+#endif
+ for (; *s && *(unsigned char *)s != c; s++);
+ return (char *)s;
+}
diff --git a/mingw-w64-crt/string/strrchr.c b/mingw-w64-crt/string/strrchr.c
new file mode 100644
index 0000000..9015af1
--- /dev/null
+++ b/mingw-w64-crt/string/strrchr.c
@@ -0,0 +1,31 @@
+/*
+ Copyright © 2005-2020 Rich Felker, et al.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <string.h>
+
+void *__memrchr(const void *m, int c, size_t n);
+
+char *strrchr(const char *s, int c)
+{
+ return __memrchr(s, c, strlen(s) + 1);
+}
diff --git a/mingw-w64-crt/string/strstr.c b/mingw-w64-crt/string/strstr.c
new file mode 100644
index 0000000..dbd1997
--- /dev/null
+++ b/mingw-w64-crt/string/strstr.c
@@ -0,0 +1,177 @@
+/*
+ Copyright © 2005-2020 Rich Felker, et al.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <string.h>
+#include <stdint.h>
+
+static char *twobyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+ uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
+ for (h++; *h && hw != nw; hw = hw<<8 | *++h);
+ return *h ? (char *)h-1 : 0;
+}
+
+static char *threebyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+ uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8;
+ uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8;
+ for (h+=2; *h && hw != nw; hw = (hw|*++h)<<8);
+ return *h ? (char *)h-2 : 0;
+}
+
+static char *fourbyte_strstr(const unsigned char *h, const unsigned char *n)
+{
+ uint32_t nw = (uint32_t)n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
+ uint32_t hw = (uint32_t)h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
+ for (h+=3; *h && hw != nw; hw = hw<<8 | *++h);
+ return *h ? (char *)h-3 : 0;
+}
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
+{
+ const unsigned char *z;
+ size_t l, ip, jp, k, p, ms, p0, mem, mem0;
+ size_t byteset[32 / sizeof(size_t)] = { 0 };
+ size_t shift[256];
+
+ /* Computing length of needle and fill shift table */
+ for (l=0; n[l] && h[l]; l++)
+ BITOP(byteset, n[l], |=), shift[n[l]] = l+1;
+ if (n[l]) return 0; /* hit the end of h */
+
+ /* Compute maximal suffix */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] > n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ ms = ip;
+ p0 = p;
+
+ /* And with the opposite comparison */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] < n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ if (ip+1 > ms+1) ms = ip;
+ else p = p0;
+
+ /* Periodic needle? */
+ if (memcmp(n, n+p, ms+1)) {
+ mem0 = 0;
+ p = MAX(ms, l-ms-1) + 1;
+ } else mem0 = l-p;
+ mem = 0;
+
+ /* Initialize incremental end-of-haystack pointer */
+ z = h;
+
+ /* Search loop */
+ for (;;) {
+ /* Update incremental end-of-haystack pointer */
+ if ((size_t)(z-h) < l) {
+ /* Fast estimate for MIN(l,63) */
+ size_t grow = l | 63;
+ const unsigned char *z2 = memchr(z, 0, grow);
+ if (z2) {
+ z = z2;
+ if ((size_t)(z-h) < l) return 0;
+ } else z += grow;
+ }
+
+ /* Check last byte first; advance by shift on mismatch */
+ if (BITOP(byteset, h[l-1], &)) {
+ k = l-shift[h[l-1]];
+ if (k) {
+ if (k < mem) k = mem;
+ h += k;
+ mem = 0;
+ continue;
+ }
+ } else {
+ h += l;
+ mem = 0;
+ continue;
+ }
+
+ /* Compare right half */
+ for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
+ if (n[k]) {
+ h += k-ms;
+ mem = 0;
+ continue;
+ }
+ /* Compare left half */
+ for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
+ if (k <= mem) return (char *)h;
+ h += p;
+ mem = mem0;
+ }
+}
+
+char *strstr(const char *h, const char *n)
+{
+ /* Return immediately on empty needle */
+ if (!n[0]) return (char *)h;
+
+ /* Use faster algorithms for short needles */
+ h = strchr(h, *n);
+ if (!h || !n[1]) return (char *)h;
+ if (!h[1]) return 0;
+ if (!n[2]) return twobyte_strstr((void *)h, (void *)n);
+ if (!h[2]) return 0;
+ if (!n[3]) return threebyte_strstr((void *)h, (void *)n);
+ if (!h[3]) return 0;
+ if (!n[4]) return fourbyte_strstr((void *)h, (void *)n);
+
+ return twoway_strstr((void *)h, (void *)n);
+}
diff --git a/mingw-w64-crt/string/wcschr.c b/mingw-w64-crt/string/wcschr.c
new file mode 100644
index 0000000..5fd1910
--- /dev/null
+++ b/mingw-w64-crt/string/wcschr.c
@@ -0,0 +1,31 @@
+/*
+ Copyright © 2005-2020 Rich Felker, et al.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <wchar.h>
+
+wchar_t *wcschr(const wchar_t *s, wchar_t c)
+{
+ if (!c) return (wchar_t *)s + wcslen(s);
+ for (; *s && *s != c; s++);
+ return *s ? (wchar_t *)s : 0;
+}
diff --git a/mingw-w64-crt/string/wcsrchr.c b/mingw-w64-crt/string/wcsrchr.c
new file mode 100644
index 0000000..17b9ac1
--- /dev/null
+++ b/mingw-w64-crt/string/wcsrchr.c
@@ -0,0 +1,31 @@
+/*
+ Copyright © 2005-2020 Rich Felker, et al.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <wchar.h>
+
+wchar_t *wcsrchr(const wchar_t *s, wchar_t c)
+{
+ const wchar_t *p;
+ for (p=s+wcslen(s); p>=s && *p!=c; p--);
+ return p>=s ? (wchar_t *)p : 0;
+}
diff --git a/mingw-w64-crt/string/wcsstr.c b/mingw-w64-crt/string/wcsstr.c
new file mode 100644
index 0000000..7590c14
--- /dev/null
+++ b/mingw-w64-crt/string/wcsstr.c
@@ -0,0 +1,128 @@
+/*
+ Copyright © 2005-2020 Rich Felker, et al.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <wchar.h>
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+static wchar_t *twoway_wcsstr(const wchar_t *h, const wchar_t *n)
+{
+ const wchar_t *z;
+ size_t l, ip, jp, k, p, ms, p0, mem, mem0;
+
+ /* Computing length of needle */
+ for (l=0; n[l] && h[l]; l++);
+ if (n[l]) return 0; /* hit the end of h */
+
+ /* Compute maximal suffix */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] > n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ ms = ip;
+ p0 = p;
+
+ /* And with the opposite comparison */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] < n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ if (ip+1 > ms+1) ms = ip;
+ else p = p0;
+
+ /* Periodic needle? */
+ if (wmemcmp(n, n+p, ms+1)) {
+ mem0 = 0;
+ p = MAX(ms, l-ms-1) + 1;
+ } else mem0 = l-p;
+ mem = 0;
+
+ /* Initialize incremental end-of-haystack pointer */
+ z = h;
+
+ /* Search loop */
+ for (;;) {
+ /* Update incremental end-of-haystack pointer */
+ if ((size_t)(z-h) < l) {
+ /* Fast estimate for MIN(l,63) */
+ size_t grow = l | 63;
+ const wchar_t *z2 = wmemchr(z, 0, grow);
+ if (z2) {
+ z = z2;
+ if ((size_t)(z-h) < l) return 0;
+ } else z += grow;
+ }
+
+ /* Compare right half */
+ for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
+ if (n[k]) {
+ h += k-ms;
+ mem = 0;
+ continue;
+ }
+ /* Compare left half */
+ for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
+ if (k <= mem) return (wchar_t *)h;
+ h += p;
+ mem = mem0;
+ }
+}
+
+wchar_t *wcsstr(const wchar_t *restrict h, const wchar_t *restrict n)
+{
+ /* Return immediately on empty needle or haystack */
+ if (!n[0]) return (wchar_t *)h;
+ if (!h[0]) return 0;
+
+ /* Use faster algorithms for short needles */
+ h = wcschr(h, *n);
+ if (!h || !n[1]) return (wchar_t *)h;
+ if (!h[1]) return 0;
+
+ return twoway_wcsstr(h, n);
+}