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ö <[email protected]>
---
 mingw-w64-crt/Makefile.am                |  53 ++++++-
 mingw-w64-crt/crt/__C_specific_handler.c |  34 +++++
 mingw-w64-crt/lib-common/ucrtapp.mri     |  19 +++
 mingw-w64-crt/misc/longjmp.S             |  97 +++++++++++++
 mingw-w64-crt/misc/setjmp.S              | 115 +++++++++++++++
 mingw-w64-crt/string/memchr.c            |  50 +++++++
 mingw-w64-crt/string/memcmp.c            |  31 ++++
 mingw-w64-crt/string/memcpy.c            |  12 ++
 mingw-w64-crt/string/memmove.c           |  12 ++
 mingw-w64-crt/string/memrchr.c           |  34 +++++
 mingw-w64-crt/string/strchr.c            |  32 ++++
 mingw-w64-crt/string/strchrnul.c         |  51 +++++++
 mingw-w64-crt/string/strrchr.c           |  31 ++++
 mingw-w64-crt/string/strstr.c            | 177 +++++++++++++++++++++++
 mingw-w64-crt/string/wcschr.c            |  31 ++++
 mingw-w64-crt/string/wcsrchr.c           |  31 ++++
 mingw-w64-crt/string/wcsstr.c            | 128 ++++++++++++++++
 17 files changed, 930 insertions(+), 8 deletions(-)
 create mode 100644 mingw-w64-crt/crt/__C_specific_handler.c
 create mode 100644 mingw-w64-crt/lib-common/ucrtapp.mri
 create mode 100644 mingw-w64-crt/misc/longjmp.S
 create mode 100644 mingw-w64-crt/misc/setjmp.S
 create mode 100644 mingw-w64-crt/string/memchr.c
 create mode 100644 mingw-w64-crt/string/memcmp.c
 create mode 100644 mingw-w64-crt/string/memcpy.c
 create mode 100644 mingw-w64-crt/string/memmove.c
 create mode 100644 mingw-w64-crt/string/memrchr.c
 create mode 100644 mingw-w64-crt/string/strchr.c
 create mode 100644 mingw-w64-crt/string/strchrnul.c
 create mode 100644 mingw-w64-crt/string/strrchr.c
 create mode 100644 mingw-w64-crt/string/strstr.c
 create mode 100644 mingw-w64-crt/string/wcschr.c
 create mode 100644 mingw-w64-crt/string/wcsrchr.c
 create mode 100644 mingw-w64-crt/string/wcsstr.c

diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index c30e22cce..b104da3a1 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -241,6 +241,23 @@ src_ucrtbase=\
   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_AR = $(DTDEF32) lib32/ucrtbase.def && 
$(AR) $(ARFLAGS)
 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_AR = $(DTDEF64) lib64/ucrtbase.def 
&& $(AR) $(ARFLAGS)
 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_AR = $(DTDEFARM32) 
libarm32/ucrtbase.def && $(AR) $(ARFLA
 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_AR = $(DTDEFARM64) 
libarm64/ucrtbase.def && $(AR) $(ARFLA
 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 @@ endif
        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 000000000..07f8927d7
--- /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 000000000..c9c0fb039
--- /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 000000000..a1318dc99
--- /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 000000000..b2058e9e2
--- /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 000000000..e115afc80
--- /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 000000000..95afa9078
--- /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 000000000..106ccaa1a
--- /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 000000000..7cecc8b5c
--- /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 000000000..83b7b8b39
--- /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 000000000..8eecdf561
--- /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 000000000..889446ac5
--- /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 000000000..9015af1df
--- /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 000000000..dbd1997d3
--- /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 000000000..5fd1910ad
--- /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 000000000..17b9ac14e
--- /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 000000000..7590c147e
--- /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);
+}
-- 
2.17.1



_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to