This is _really_ nice. On Thu, 4 Jun 2020, at 08:33, Martin Storsjö wrote: > 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 >
-- Jean-Baptiste Kempf - President +33 672 704 734 _______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
