+2017-01-28 Keith Marshall <keithmarshall@users.sourceforge.net>
+
+ Implement wcsnlen() API per feature request [#2332].
+
+ * mingwex/strnlen.s: Rename it as...
+ * mingwex/strnlen.sx: ...this; use C preprocessor logic to adapt...
+ (__mingw_strnlen): ...this existing function implementation for use...
+ [_UNICODE] (__mingw_wcsnlen): ...as this.
+
+ * include/wchar.h [_POSIX_C_SOURCE >= 200809L] (wcsnlen): Declare...
+ [__MSVCRT_VERSION__>=__MSVCR80_DLL]: ...using MS DLL implementation...
+ [!__MSVCRT_VERSION__>=__MSVCR80_DLL] (__mingw_wcsnlen): ...otherwise,
+ declare this, with inline __JMPSTUB__ implementation, providing...
+ (wcsnlen): ...this.
+
+ * Makefile.in (wcsnlen.$OBJEXT): New build rule.
+ (libmingwex.a): Add wcsnlen.$OBJEXT as new prerequisite.
+ (libmoldname.a, libmoldnamed.a): Add __JMPSTUB__ wrappers.
+ (libmoldname70.a, libmoldname70d.a): Likewise.
+ (libmoldname71.a, libmoldname71d.a): Likewise.
+
+ for all other MSVC non-free associated oldname import libraries.
+ (vpath): Add $srcdir/mingwex for %.sx; hence mapping for...
+ (jmpstub.sx): ...this becomes redundant; delete it.
+
2017-01-26 Jason Hood <jadoxa@yahoo.com.au>
Honour GLOB_CASEMATCH for globbing sets; cf. issue [#2327].
#
$(foreach name,moldname $(addprefix moldname,70 71),lib$(name).a) \
$(foreach name,moldname $(addprefix moldname,70 71),lib$(name)d.a): \
- strnlen.jmpstub.$(OBJEXT)
+ strnlen.jmpstub.$(OBJEXT) wcsnlen.jmpstub.$(OBJEXT)
coldname.def: %.def: ${mingwrt_srcdir}/moldname.def.in
$(CC) -C -E -P -D__FILENAME__=$@ -D__CRTDLL__ -xc-header $< > $@
libmingwex.a: $(addsuffix .$(OBJEXT), dirent wdirent dlfcn)
vpath %.s ${mingwrt_srcdir}/mingwex
+vpath %.sx ${mingwrt_srcdir}/mingwex
libmingwex.a: $(addsuffix .$(OBJEXT), fwide mbrtowc mbsinit strnlen wcrtomb \
- wcstof wcstold wctob wmemchr wmemcmp wmemcpy wmemmove wmemset)
+ wcsnlen wcstof wcstold wctob wctrans wctype wmemchr wmemcmp wmemcpy wmemmove \
+ wmemset)
-libmingwex.a: $(addsuffix .$(OBJEXT), wctrans wctype)
+# The wcsnlen() function, enumerated above, is an adaptation of strnlen();
+# we need a specific rule to compile it, from shared source.
+#
+wcsnlen.$(OBJEXT): strnlen.sx
+ $(COMPILE.sx) -D_UNICODE $^ -o $@
# For the math sources, we support the convention that a single
# quux_generic.c source file will produce three objects: quux.o,
# entry points as stubs in libmingwex.a, via the following rules:
#
sinclude Makefile.stub
-vpath jmpstub.sx ${mingwrt_srcdir}/mingwex
libstub_refnames = grep -lr '__$1.*FUNCTION *=' ${mingwrt_srcdir}
jmpstub_prerequisites := $(shell $(call libstub_refnames,JMPSTUB)/include)
libimpl_prerequisites := $(shell $(call libstub_refnames,LIBIMPL)/include)
#endif /* !_NO_OLDNAMES */
#endif /* !__STRICT_ANSI__ */
+#if _POSIX_C_SOURCE >= 200809L
+#if __MSVCRT_VERSION__ >= __MSVCR80_DLL
+/* MSVCR80.DLL adds a (mostly) POSIX.1-2008 conforming wcsnlen(); (it's
+ * also available in MSVCRT.DLL from _WIN32_WINNT_VISTA onwards, but we
+ * pretend otherwise, since recent GCC will try to use the function when
+ * it can be found in libmsvcrt.a, so breaking it for use on WinXP and
+ * earlier).
+ */
+#ifndef __STRICT_ANSI__ /* N.B.: this is not an ISO-C function */
+_CRTIMP __cdecl __MINGW_NOTHROW char *wcsnlen (const wchar_t *, size_t);
+#endif
+
+#else /* MSVCRT.DLL || pre-MSVCR80.DLL */
+/* Emulation, to support recent POSIX.1; we prefer this for ALL versions
+ * of MSVCRT.DLL, (even those which already provide wcsnlen()); to avoid
+ * the GCC breakage noted above. (Note that we implement wcsnlen() with
+ * the alternative external name, __mingw_wcsnlen() in libmingwex.a, to
+ * avoid possible link time collision with MSVCR80.DLL's implementation,
+ * then map this to wcsnlen() via a __CRT_ALIAS, with stubs designated
+ * for linking from within the appropriate oldname libraries.
+ */
+extern size_t __mingw_wcsnlen (const wchar_t *, size_t);
+
+__JMPSTUB__(( LIB=coldname; FUNCTION=wcsnlen ))
+__CRT_ALIAS size_t wcsnlen (const wchar_t *__text, size_t __maxlen)
+{ return __mingw_wcsnlen (__text, __maxlen); }
+
+#endif /* MSVCRT.DLL || pre-MSVCR80.DLL */
+#endif /* _POSIX_C_SOURCE >= 200809L */
+
/* This completes the set of declarations which are to be duplicated by
* inclusion of <string.h>; revert the declarative condition, to make it
* specific to <wchar.h> alone.
/*
- * strnlen.s
+ * strnlen.sx
*
* Implementation of POSIX.1-2008 conforming strnlen(), and a wrapper
* extending it to conform with ISO-C11 TR-24731-1 strnlen_s().
* $Id$
*
* Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2016, MinGW.org Project
+ * Copyright (C) 2016, 2017, MinGW.org Project
*
*
* Permission is hereby granted, free of charge, to any person obtaining a
* sharing of common code between two distinct entry points, with subtly
* differing behaviours, while avoiding the overhead of an extra function
* call to invoke such shared code; this also allows the code to exploit
- * the CUP's string scanning instructions, (which GCC does not), and so
+ * the CPU's string scanning instructions, (which GCC does not), and so
* achieves a more compact, (and likely more efficient), implementation.
*
*/
+#if defined UNICODE || defined _UNICODE
+/* The algorithm defined herein is effectively the same as that required
+ * as a substitute for wcsnlen()/wcsnlen_s(); map entry point names to the
+ * appropriate alternatives for scanning wchar_t *, (rather than char *),
+ * strings, (i.e. Microsoft's so-called UNICODE strings).
+ */
+# define ___mingw_strnlen ___mingw_wcsnlen
+# define ___mingw_strnlen_s ___mingw_wcsnlen_s
+
+/* The fundamental change required to scan whcar_t * strings, rather than
+ * char * strings, is that we must use the scasw instruction in place of
+ * the scasb instruction; map it accordingly.
+ */
+# define scasb scasw
+#endif
+
.text
.align 4
.globl ___mingw_strnlen
decl %eax /* NUL found and counted; discount it */
.L3:
sub %edx, %eax /* compute effective count to return */
-.L4:
- popl %edi /* restore saved register ... */
+
+#if defined UNICODE || defined _UNICODE
+/* By the time we get to here, the EAX register contains the effective
+ * length of the scanned string in bytes; this is the correct value to be
+ * returned, in the case of char * strings, but it is twice the correct
+ * length for wchar_t * strings, (possibly with one odd residual byte,
+ * left over from a partially discounted NUL wchar_t); we may adjust this,
+ * for the wchar_t * case, by a simple logical right shift, effectively
+ * dividing the even extent of the (unsigned) count by two, extracting
+ * the full wchar_t count, leaving any odd byte residual as remainder
+ * in the carry flag, where we may simply (and safely) ignore it.
+ */
+ shrl %eax /* convert byte count to wchar_t count */
+#endif
+
+.L4: popl %edi /* restore saved register ... */
ret /* and we're done */
.align 4