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);
+}