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