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 three 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 like memcpy, memmove, strchr, strstr, wcschr, wcsstr
  These are copied from musl. These can be performance sensitive. Musl
  does have some basic assembly implementations for some architectures that
  could be imported later. (I haven't measured to see how musl's
  implementations perform compared to msvcrt.dll/ucrtbase.dll's
  implementations, or other ones like the one in glibc.)

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 |  52 +++++++
 mingw-w64-crt/lib-common/ucrtapp.mri     |  19 +++
 mingw-w64-crt/misc/longjmp.S             |  96 ++++++++++++
 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            | 146 +++++++++++++++++++
 mingw-w64-crt/string/memmove.c           |  65 +++++++++
 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, 1134 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 9a9384bf1..7cc3c92e8 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
@@ -1732,10 +1755,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
@@ -2068,6 +2093,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..fa15d07ca
--- /dev/null
+++ b/mingw-w64-crt/crt/__C_specific_handler.c
@@ -0,0 +1,52 @@
+/*
+    Copyright (c) 2020 mingw-w64 project
+
+    Contributing authors: Martin Storsjo
+
+    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 <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..3d22954ee
--- /dev/null
+++ b/mingw-w64-crt/misc/longjmp.S
@@ -0,0 +1,96 @@
+/**
+ * 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..dd3e50d60
--- /dev/null
+++ b/mingw-w64-crt/string/memcpy.c
@@ -0,0 +1,146 @@
+/*
+    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>
+
+void *memcpy(void *restrict dest, const void *restrict src, size_t n)
+{
+       unsigned char *d = dest;
+       const unsigned char *s = src;
+
+#ifdef __GNUC__
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define LS >>
+#define RS <<
+#else
+#define LS <<
+#define RS >>
+#endif
+
+       typedef uint32_t __attribute__((__may_alias__)) u32;
+       uint32_t w, x;
+
+       for (; (uintptr_t)s % 4 && n; n--) *d++ = *s++;
+
+       if ((uintptr_t)d % 4 == 0) {
+               for (; n>=16; s+=16, d+=16, n-=16) {
+                       *(u32 *)(d+0) = *(u32 *)(s+0);
+                       *(u32 *)(d+4) = *(u32 *)(s+4);
+                       *(u32 *)(d+8) = *(u32 *)(s+8);
+                       *(u32 *)(d+12) = *(u32 *)(s+12);
+               }
+               if (n&8) {
+                       *(u32 *)(d+0) = *(u32 *)(s+0);
+                       *(u32 *)(d+4) = *(u32 *)(s+4);
+                       d += 8; s += 8;
+               }
+               if (n&4) {
+                       *(u32 *)(d+0) = *(u32 *)(s+0);
+                       d += 4; s += 4;
+               }
+               if (n&2) {
+                       *d++ = *s++; *d++ = *s++;
+               }
+               if (n&1) {
+                       *d = *s;
+               }
+               return dest;
+       }
+
+       if (n >= 32) switch ((uintptr_t)d % 4) {
+       case 1:
+               w = *(u32 *)s;
+               *d++ = *s++;
+               *d++ = *s++;
+               *d++ = *s++;
+               n -= 3;
+               for (; n>=17; s+=16, d+=16, n-=16) {
+                       x = *(u32 *)(s+1);
+                       *(u32 *)(d+0) = (w LS 24) | (x RS 8);
+                       w = *(u32 *)(s+5);
+                       *(u32 *)(d+4) = (x LS 24) | (w RS 8);
+                       x = *(u32 *)(s+9);
+                       *(u32 *)(d+8) = (w LS 24) | (x RS 8);
+                       w = *(u32 *)(s+13);
+                       *(u32 *)(d+12) = (x LS 24) | (w RS 8);
+               }
+               break;
+       case 2:
+               w = *(u32 *)s;
+               *d++ = *s++;
+               *d++ = *s++;
+               n -= 2;
+               for (; n>=18; s+=16, d+=16, n-=16) {
+                       x = *(u32 *)(s+2);
+                       *(u32 *)(d+0) = (w LS 16) | (x RS 16);
+                       w = *(u32 *)(s+6);
+                       *(u32 *)(d+4) = (x LS 16) | (w RS 16);
+                       x = *(u32 *)(s+10);
+                       *(u32 *)(d+8) = (w LS 16) | (x RS 16);
+                       w = *(u32 *)(s+14);
+                       *(u32 *)(d+12) = (x LS 16) | (w RS 16);
+               }
+               break;
+       case 3:
+               w = *(u32 *)s;
+               *d++ = *s++;
+               n -= 1;
+               for (; n>=19; s+=16, d+=16, n-=16) {
+                       x = *(u32 *)(s+3);
+                       *(u32 *)(d+0) = (w LS 8) | (x RS 24);
+                       w = *(u32 *)(s+7);
+                       *(u32 *)(d+4) = (x LS 8) | (w RS 24);
+                       x = *(u32 *)(s+11);
+                       *(u32 *)(d+8) = (w LS 8) | (x RS 24);
+                       w = *(u32 *)(s+15);
+                       *(u32 *)(d+12) = (x LS 8) | (w RS 24);
+               }
+               break;
+       }
+       if (n&16) {
+               *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+               *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+               *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+               *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+       }
+       if (n&8) {
+               *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+               *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+       }
+       if (n&4) {
+               *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
+       }
+       if (n&2) {
+               *d++ = *s++; *d++ = *s++;
+       }
+       if (n&1) {
+               *d = *s;
+       }
+       return dest;
+#endif
+
+       for (; n; n--) *d++ = *s++;
+       return dest;
+}
diff --git a/mingw-w64-crt/string/memmove.c b/mingw-w64-crt/string/memmove.c
new file mode 100644
index 000000000..4dcf67e14
--- /dev/null
+++ b/mingw-w64-crt/string/memmove.c
@@ -0,0 +1,65 @@
+/*
+    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>
+
+#ifdef __GNUC__
+typedef __attribute__((__may_alias__)) size_t WT;
+#define WS (sizeof(WT))
+#endif
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+       char *d = dest;
+       const char *s = src;
+
+       if (d==s) return d;
+       if ((uintptr_t)s-(uintptr_t)d-n <= -2*n) return memcpy(d, s, n);
+
+       if (d<s) {
+#ifdef __GNUC__
+               if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
+                       while ((uintptr_t)d % WS) {
+                               if (!n--) return dest;
+                               *d++ = *s++;
+                       }
+                       for (; n>=WS; n-=WS, d+=WS, s+=WS) *(WT *)d = *(WT *)s;
+               }
+#endif
+               for (; n; n--) *d++ = *s++;
+       } else {
+#ifdef __GNUC__
+               if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
+                       while ((uintptr_t)(d+n) % WS) {
+                               if (!n--) return dest;
+                               d[n] = s[n];
+                       }
+                       while (n>=WS) n-=WS, *(WT *)(d+n) = *(WT *)(s+n);
+               }
+#endif
+               while (n) n--, d[n] = s[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