* gnulib-local/lib/localename-table.h.diff: New file.
* gnulib-local/lib/localename.c.diff: New file.
* gnulib-local/lib/tsearch.c.diff: New file.
* gnulib-local/modules/gettext-runtime-intl-misc: New file, based on
gettext-runtime/intl/Makefile.am.
* gnulib-local/modules/tsearch.diff: New file.
* gnulib-local/Makefile.am (EXTRA_DIST): Add them.
* autogen.sh (GNULIB_MODULES_LIBINTL, GNULIB_SETLOCALE_DEPENDENCIES): New
variables.
Invoke gnulib-tool for the gettext-runtime/intl/ directory.
Update 'aclocal' invocation for the gettext-runtime/intl/ directory.
* gettext-runtime/intl/configure.ac (enable_relocatable): Set to yes always.
Invoke gl_EARLY and gl_INIT. Don't invoke gl_USE_SYSTEM_EXTENSIONS,
AM_PROG_CC_C_O, gl_COMMON, gl_RELOCATABLE_LIBRARY explicitly.
Define IN_LIBINTL through config.h.
Rename __libc* macros and symbols through config.h.
Invoke AC_CONFIG_FILES for gnulib-lib/Makefile.
* gettext-runtime/m4/intl.m4 (AM_INTL_SUBDIR): Don't rename __libc* macros and
symbols here.
(gt_INTL_SUBDIR_CORE): Don't test for tsearch.
* gettext-runtime/intl/arg-nonnull.h: Remove file.
* gettext-runtime/intl/attribute.h: Remove file.
* gettext-runtime/intl/filename.h: Remove file.
* gettext-runtime/intl/flexmember.h: Remove file.
* gettext-runtime/intl/localcharset.h: Remove file.
* gettext-runtime/intl/localcharset.c: Remove file.
* gettext-runtime/intl/localename.c: Remove file.
* gettext-runtime/intl/localename-table.in.h: Remove file.
* gettext-runtime/intl/localename-table.c: Remove file.
* gettext-runtime/intl/lock.h: Remove file.
* gettext-runtime/intl/lock.c: Remove file.
* gettext-runtime/intl/printf-args.h: Remove file.
* gettext-runtime/intl/printf-args.c: Remove file.
* gettext-runtime/intl/printf-parse.h: Remove file.
* gettext-runtime/intl/printf-parse.c: Remove file.
* gettext-runtime/intl/relocatable.h: Remove file.
* gettext-runtime/intl/relocatable.c: Remove file.
* gettext-runtime/intl/setlocale-lock.c: Remove file.
* gettext-runtime/intl/setlocale_null.h: Remove file.
* gettext-runtime/intl/setlocale_null.c: Remove file.
* gettext-runtime/intl/thread-optim.h: Remove file.
* gettext-runtime/intl/threadlib.c: Remove file.
* gettext-runtime/intl/tsearch.h: Remove file.
* gettext-runtime/intl/tsearch.c: Remove file.
* gettext-runtime/intl/vasnprintf.c: Remove file.
* gettext-runtime/intl/verify.h: Remove file.
* gettext-runtime/intl/windows-initguard.h: Remove file.
* gettext-runtime/intl/windows-mutex.h: Remove file.
* gettext-runtime/intl/windows-mutex.c: Remove file.
* gettext-runtime/intl/windows-once.h: Remove file.
* gettext-runtime/intl/windows-once.c: Remove file.
* gettext-runtime/intl/windows-recmutex.h: Remove file.
* gettext-runtime/intl/windows-recmutex.c: Remove file.
* gettext-runtime/intl/windows-rwlock.h: Remove file.
* gettext-runtime/intl/windows-rwlock.c: Remove file.
* gettext-runtime/intl/xsize.h: Remove file.
* gettext-runtime/intl/xsize.c: Remove file.
* gettext-runtime/intl/Makefile.am (ACLOCAL_AMFLAGS): Reference gnulib-m4 in
this directory.
(SUBDIRS): Add gnulib-lib.
(AM_CPPFLAGS): Add -I statements for the gnulib-lib directory. Don't define
BUILDING_DLL, IN_LIBINTL here. Don't parametrize the 'relocatable-lib-lgpl'
module here.
(EXTRA_DIST, LIBINTLSOURCES): Remove the said files.
(localename-table.h): Remove rule.
(*.lo): Remove rules and dependencies for the said files.
(libintl_la_LIBADD, libintl_la_DEPENDENCIES, libgnuintl_la_LIBADD,
libgnuintl_la_DEPENDENCIES): Add gnulib-lib/libgnu.la.
(OTHER_LDFLAGS): Don't export _libintl_* symbols.
(EXTRA_DIST): Add gnulib-m4/gnulib-cache.m4.
* gettext-runtime/intl/gettextP.h: Include glthread/lock.h, not lock.h.
(gl_locale_name_canonicalize, gl_locale_name_from_win32_LANGID,
gl_locale_name_from_win32_LCID, gl_locale_name_thread_unsafe,
gl_locale_name_thread, gl_locale_name_posix, gl_locale_name_environ,
gl_locale_name_default, gl_locale_name): Remove macros.
(_nl_locale_name_posix, _nl_locale_name_environ, _nl_locale_name_default):
Remove declarations.
* gettext-runtime/intl/plural-exp.h (FREE_EXPRESSION, PLURAL_PARSE,
GERMANIC_PLURAL, EXTRACT_PLURAL_EXPRESSION): Prefix these libintl-private
symbols with _libintl_, not libintl_.
* gettext-runtime/intl/bindtextdom.c: Include glthread/lock.h, not lock.h.
* gettext-runtime/intl/finddomain.c: Likewise.
* gettext-runtime/intl/loadmsgcat.c: Likewise.
* gettext-runtime/intl/localealias.c: Likewise.
* gettext-runtime/intl/log.c: Likewise.
* gettext-runtime/intl/textdomain.c: Likewise.
* gettext-runtime/intl/dcigettext.c: Include localename.h. Include
glthread/lock.h, not lock.h.
Include <search.h> always; don't include tsearch.c.
* gettext-runtime/intl/printf.c: Don't define libintl_vasprintf here. Instead,
use _libintl_vasprintf from gnulib-lib/vasnprintf.c. Define _libintl_vasnwprintf
instead of libintl_vasnwprintf.
* gettext-runtime/intl/setlocale.c: Include <errno.h>, localename.h.
(gl_locale_name_canonicalize): New declaration.
* Makefile.am (distcheck-hook): Remove the file comparisons for files in
gettext-runtime/intl/.
/gettext-runtime/gnulib-lib/
/gettext-runtime/gnulib-m4/
/gettext-runtime/doc/relocatable.texi
+/gettext-runtime/intl/gnulib-lib/
+/gettext-runtime/intl/gnulib-m4/
+/gettext-runtime/intl/doc/relocatable.texi
/gettext-runtime/libasprintf/gnulib-lib/
/gettext-runtime/libasprintf/gnulib-m4/
/gettext-runtime/man/x-to-1.in
cmp -s $(srcdir)/gettext-runtime/m4/size_max.m4 $(srcdir)/gettext-tools/gnulib-m4/size_max.m4
cmp -s $(srcdir)/gettext-runtime/m4/stdint_h.m4 $(srcdir)/gettext-tools/gnulib-m4/stdint_h.m4
cmp -s $(srcdir)/gettext-runtime/m4/xsize.m4 $(srcdir)/gettext-tools/gnulib-m4/xsize.m4
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/arg-nonnull.h | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/arg-nonnull.h | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/attribute.h | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/attribute.h | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/filename.h | md5sum`" = "`sed 1,17d $(srcdir)/gettext-tools/gnulib-lib/filename.h | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/flexmember.h | md5sum`" = "`sed 1,19d $(srcdir)/gettext-tools/gnulib-lib/flexmember.h | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/localcharset.h | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/localcharset.h | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/localcharset.c | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/localcharset.c | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/localename.c | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/localename.c | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/localename-table.in.h | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/localename-table.h | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/localename-table.c | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/localename-table.c | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/lock.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/glthread/lock.h | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/lock.c | md5sum`" = "`sed -e 1,15d -e 's,glthread/,,g' $(srcdir)/gettext-tools/gnulib-lib/glthread/lock.c | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/setlocale-lock.c | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/setlocale-lock.c | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/setlocale_null.h | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/setlocale_null.h | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/setlocale_null.c | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/setlocale_null.c | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/thread-optim.h | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/thread-optim.h | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/threadlib.c | md5sum`" = "`sed -e 1,15d $(srcdir)/gettext-tools/gnulib-lib/glthread/threadlib.c | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/verify.h | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/verify.h | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-initguard.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-initguard.h | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-mutex.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-mutex.h | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-mutex.c | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-mutex.c | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-once.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-once.h | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-once.c | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-once.c | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-recmutex.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-recmutex.h | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-recmutex.c | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-recmutex.c | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-rwlock.h | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-rwlock.h | md5sum`"
- test "`sed 1,15d $(srcdir)/gettext-runtime/intl/windows-rwlock.c | md5sum`" = "`sed 1,15d $(srcdir)/gettext-tools/gnulib-lib/windows-rwlock.c | md5sum`"
- test "`sed 1,18d $(srcdir)/gettext-runtime/intl/relocatable.h | md5sum`" = "`sed 1,18d $(srcdir)/gettext-tools/gnulib-lib/relocatable.h | md5sum`"
- test "`sed 1,18d $(srcdir)/gettext-runtime/intl/relocatable.c | md5sum`" = "`sed 1,18d $(srcdir)/gettext-tools/gnulib-lib/relocatable.c | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/vasnprintf.c | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/vasnprintf.c | md5sum`"
- test "`sed 1,16d $(srcdir)/gettext-runtime/intl/xsize.h | md5sum`" = "`sed 1,16d $(srcdir)/gettext-tools/gnulib-lib/xsize.h | md5sum`"
cmp -s $(srcdir)/gettext-runtime/man/help2man $(srcdir)/gettext-tools/man/help2man
cmp -s $(srcdir)/gettext-runtime/man/x-to-1.in $(srcdir)/gettext-tools/man/x-to-1.in
cmp -s $(srcdir)/libtextstyle/m4/libtextstyle.m4 $(srcdir)/gettext-tools/gnulib-m4/libtextstyle.m4
$GNULIB_TOOL --dir=gettext-runtime --lib=libgrt --source-base=gnulib-lib --m4-base=gnulib-m4 --no-libtool --local-dir=gnulib-local --local-symlink \
--import $GNULIB_MODULES_RUNTIME_FOR_SRC $GNULIB_MODULES_RUNTIME_OTHER || exit $?
# In gettext-runtime/intl:
- $GNULIB_TOOL --copy-file m4/bison.m4 gettext-runtime/gnulib-m4/bison.m4 || exit $?
+ GNULIB_MODULES_LIBINTL='
+ gettext-runtime-intl-misc
+ attribute
+ bison
+ filename
+ havelib
+ localcharset
+ lock
+ relocatable-lib-lgpl
+ tsearch
+ vasnprintf
+ '
+ GNULIB_SETLOCALE_DEPENDENCIES=`$GNULIB_TOOL --extract-dependencies setlocale | sed -e 's/ .*//'`
+ $GNULIB_TOOL --dir=gettext-runtime/intl --source-base=gnulib-lib --m4-base=gnulib-m4 --lgpl=2 --libtool --local-dir=gnulib-local --local-symlink \
+ --import $GNULIB_MODULES_LIBINTL $GNULIB_SETLOCALE_DEPENDENCIES || exit $?
# In gettext-runtime/libasprintf:
GNULIB_MODULES_LIBASPRINTF='
alloca
echo "$0: generating configure in gettext-runtime/intl..."
cd gettext-runtime/intl
-aclocal -I ../../m4 -I ../m4 -I ../gnulib-m4 \
+aclocal -I ../../m4 -I ../m4 -I gnulib-m4 \
&& autoconf \
&& autoheader && touch config.h.in \
&& touch ChangeLog \
## Process this file with automake to produce Makefile.in.
AUTOMAKE_OPTIONS = 1.10 gnu no-dependencies
-ACLOCAL_AMFLAGS = -I ../../m4 -I ../m4 -I ../gnulib-m4
+ACLOCAL_AMFLAGS = -I ../../m4 -I ../m4 -I gnulib-m4
-SUBDIRS = .
+SUBDIRS = gnulib-lib
EXTRA_DIST =
BUILT_SOURCES =
# -DBUILDING_LIBINTL: Change expansion of LIBINTL_DLL_EXPORTED macro.
# -DBUILDING_DLL: Change expansion of RELOCATABLE_DLL_EXPORTED macro.
AM_CPPFLAGS = \
+ -Ignulib-lib -I$(srcdir)/gnulib-lib \
-DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \
- -DLIBDIR=\"$(libdir)\" -DBUILDING_LIBINTL -DBUILDING_DLL -DIN_LIBINTL
+ -DLIBDIR=\"$(libdir)\" -DBUILDING_LIBINTL
if WOE32
# On mingw, disable the declarations of *printf functions as aliases to the
AM_CPPFLAGS += -D__USE_MINGW_ANSI_STDIO=0
endif
-# Parametrization of the 'relocatable-lib-lgpl' module.
-AM_CPPFLAGS += \
- -DENABLE_RELOCATABLE=1 -DIN_LIBRARY -DINSTALLDIR=\"$(libdir)\" -DNO_XMALLOC \
- -Dset_relocation_prefix=libintl_set_relocation_prefix \
- -Drelocate=libintl_relocate \
- -Drelocate2=libintl_relocate2 \
- -DDEPENDS_ON_LIBICONV=1
-
BISON = @INTLBISON@
BISONFLAGS = --name-prefix=__gettext
# Just to shut up Automake "error: Yacc source seen but 'YACC' is undefined".
loadinfo.h \
plural-exp.h \
eval-plural.h \
- localcharset.h \
- lock.h windows-mutex.h windows-rwlock.h windows-recmutex.h windows-once.h windows-initguard.h \
- relocatable.h \
- arg-nonnull.h \
- attribute.h \
- filename.h \
- flexmember.h \
- localename-table.in.h \
- setlocale_null.h \
- thread-optim.h \
- tsearch.h tsearch.c \
- verify.h \
- xsize.h \
- printf-args.h printf-args.c \
- printf-parse.h wprintf-parse.h printf-parse.c \
- vasnprintf.h vasnwprintf.h vasnprintf.c \
+ wprintf-parse.h \
+ vasnprintf.h vasnwprintf.h \
intl-exports.c os2compat.h os2compat.c \
libgnuintl.in.h
ngettext.c \
plural.y \
plural-exp.c \
- localcharset.c \
- threadlib.c \
- lock.c \
- relocatable.c \
langprefs.c \
- localename.c \
- localename-table.c \
log.c \
printf.c \
setlocale.c \
- setlocale-lock.c \
- setlocale_null.c \
version.c \
- xsize.c \
osdep.c \
intl-compat.c
-if WINDOWS_NATIVE
-LIBINTLSOURCES += \
- windows-mutex.c \
- windows-rwlock.c \
- windows-recmutex.c \
- windows-once.c
-endif
# We must not install the libintl.h/libintl.la files if we are on a
# system which has the GNU gettext() function in its C library or in a
< $(srcdir)/libgnuintl.in.h > libintl.h
MOSTLYCLEANFILES += libintl.h
-localename-table.h: $(srcdir)/localename-table.in.h $(srcdir)/export.h
- sed -e 's/extern \([^"]\)/extern LIBINTL_DLL_EXPORTED \1/' \
- -e 's/extern,/extern LIBINTL_DLL_EXPORTED,/' \
- -e "/#if HAVE_WORKING_USELOCALE/r $(srcdir)/export.h" \
- < $(srcdir)/localename-table.in.h \
- | sed -e 's,@''HAVE_VISIBILITY''@,@HAVE_VISIBILITY@,g' \
- > localename-table.h
-MOSTLYCLEANFILES += localename-table.h
-
# The Automake generated .y.c rule is broken: When executed in a VPATH build,
# - The .c file gets generated in the build directory. But since it requires
# special tools to rebuild it, we need to distribute it in the tarballs,
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/plural.c
plural-exp.lo: $(srcdir)/plural-exp.c
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/plural-exp.c
-localcharset.lo: $(srcdir)/localcharset.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/localcharset.c
-threadlib.lo: $(srcdir)/threadlib.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/threadlib.c
-lock.lo: $(srcdir)/lock.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/lock.c
-relocatable.lo: $(srcdir)/relocatable.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/relocatable.c
langprefs.lo: $(srcdir)/langprefs.c
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/langprefs.c
-localename.lo: $(srcdir)/localename.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/localename.c
-localename-table.lo: $(srcdir)/localename-table.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/localename-table.c
log.lo: $(srcdir)/log.c
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/log.c
printf.lo: $(srcdir)/printf.c
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/printf.c
setlocale.lo: $(srcdir)/setlocale.c
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/setlocale.c
-setlocale-lock.lo: $(srcdir)/setlocale-lock.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/setlocale-lock.c
-setlocale_null.lo: $(srcdir)/setlocale_null.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/setlocale_null.c
version.lo: $(srcdir)/version.c
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/version.c
-xsize.lo: $(srcdir)/xsize.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/xsize.c
osdep.lo: $(srcdir)/osdep.c
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/osdep.c
intl-compat.lo: $(srcdir)/intl-compat.c
$(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/intl-compat.c
-windows-mutex.lo: $(srcdir)/windows-mutex.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/windows-mutex.c
-windows-rwlock.lo: $(srcdir)/windows-rwlock.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/windows-rwlock.c
-windows-recmutex.lo: $(srcdir)/windows-recmutex.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/windows-recmutex.c
-windows-once.lo: $(srcdir)/windows-once.c
- $(AM_V_CC)$(LTCOMPILE) -c -o $@ $(srcdir)/windows-once.c
# Dependencies.
PLURAL_DEPS += libintl.h
endif
-bindtextdom.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-dcgettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-dgettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-gettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-finddomain.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
+bindtextdom.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
+dcgettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
+dgettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
+gettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
+finddomain.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
hash-string.lo: ../config.h $(srcdir)/hash-string.h
-loadmsgcat.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h $(srcdir)/hash-string.h $(srcdir)/plural-exp.h
-localealias.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h $(srcdir)/relocatable.h
-textdomain.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-l10nflist.lo: ../config.h $(srcdir)/loadinfo.h $(srcdir)/filename.h
+loadmsgcat.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/hash-string.h $(srcdir)/plural-exp.h
+localealias.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
+textdomain.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
+l10nflist.lo: ../config.h $(srcdir)/loadinfo.h
explodename.lo: ../config.h $(srcdir)/loadinfo.h
-dcigettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h $(srcdir)/localcharset.h $(srcdir)/plural-exp.h $(srcdir)/hash-string.h $(srcdir)/tsearch.h $(srcdir)/tsearch.c $(srcdir)/eval-plural.h $(srcdir)/filename.h
-dcngettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-dngettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-ngettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
+dcigettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/plural-exp.h $(srcdir)/hash-string.h $(srcdir)/eval-plural.h
+dcngettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
+dngettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
+ngettext.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
plural.lo: ../config.h $(srcdir)/plural-exp.h $(PLURAL_DEPS)
plural-exp.lo: ../config.h $(srcdir)/plural-exp.h
-localcharset.lo: ../config.h $(srcdir)/localcharset.h
-threadlib.lo: ../config.h
-lock.lo: ../config.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-relocatable.lo: ../config.h $(srcdir)/relocatable.h
langprefs.lo: ../config.h
-localename.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h $(srcdir)/flexmember.h $(srcdir)/setlocale_null.h $(srcdir)/arg-nonnull.h localename-table.h
-localename-table.lo: ../config.h localename-table.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-log.lo: ../config.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-printf.lo: ../config.h $(srcdir)/printf-args.c $(srcdir)/printf-args.h $(srcdir)/printf-parse.c $(srcdir)/printf-parse.h $(srcdir)/wprintf-parse.h $(srcdir)/xsize.h $(srcdir)/vasnprintf.c $(srcdir)/vasnprintf.h $(srcdir)/vasnwprintf.h $(srcdir)/verify.h
-setlocale.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-setlocale-lock.lo: ../config.h $(srcdir)/windows-initguard.h
-setlocale_null.lo: ../config.h $(srcdir)/setlocale_null.h $(srcdir)/arg-nonnull.h
+log.lo: ../config.h
+printf.lo: ../config.h $(srcdir)/wprintf-parse.h $(srcdir)/vasnprintf.h $(srcdir)/vasnwprintf.h
+setlocale.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
version.lo: ../config.h libgnuintl.h
-xsize.lo: ../config.h $(srcdir)/xsize.h
osdep.lo: ../config.h $(srcdir)/intl-exports.c $(srcdir)/os2compat.c
-intl-compat.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h $(srcdir)/lock.h $(srcdir)/windows-mutex.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-once.h $(srcdir)/windows-initguard.h
-windows-mutex.lo: ../config.h $(srcdir)/windows-mutex.h $(srcdir)/windows-initguard.h
-windows-rwlock.lo: ../config.h $(srcdir)/windows-rwlock.h $(srcdir)/windows-initguard.h
-windows-recmutex.lo: ../config.h $(srcdir)/windows-recmutex.h $(srcdir)/windows-initguard.h
-windows-once.lo: ../config.h $(srcdir)/windows-once.h
+intl-compat.lo: ../config.h $(srcdir)/gettextP.h libgnuintl.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
# Version information according to Woe32 conventions.
EXTRA_DIST += libintl.rc
else
WOE32_LIBADD =
endif
-libintl_la_LIBADD = $(WOE32_LIBADD)
-libintl_la_DEPENDENCIES = $(WOE32_LIBADD)
-libgnuintl_la_LIBADD = $(WOE32_LIBADD)
-libgnuintl_la_DEPENDENCIES = $(WOE32_LIBADD)
+
+# What object files to include in libintl.la and libgnuintl.la.
+libintl_la_LIBADD = gnulib-lib/libgnu.la $(WOE32_LIBADD)
+libintl_la_DEPENDENCIES = gnulib-lib/libgnu.la $(WOE32_LIBADD)
+libgnuintl_la_LIBADD = gnulib-lib/libgnu.la $(WOE32_LIBADD)
+libgnuintl_la_DEPENDENCIES = gnulib-lib/libgnu.la $(WOE32_LIBADD)
# langprefs.c (_nl_language_preferences_win32_95) uses functions from
# advapi32.dll.
LTV_AGE=2
# How to build libintl.la and libgnuintl.la.
-# Limit the exported symbols: Don't export glwthread* (from gnulib modules).
+# Limit the exported symbols: Don't export _libintl_* (from gnulib modules).
OTHER_LDFLAGS = \
- @LTLIBICONV@ @INTL_MACOSX_LIBS@ $(INTL_WINDOWS_LIBS) @LTLIBTHREAD@ \
+ @LTLIBICONV@ @INTL_MACOSX_LIBS@ $(INTL_WINDOWS_LIBS) @LIB_SETLOCALE_NULL@ @LTLIBTHREAD@ \
-no-undefined \
- -export-symbols-regex '^([^g]|g[^l]|gl[^w]|glw[^t]|glwt[^h]|glwth[^r]|glwthr[^e]|glwthre[^a]|glwthrea[^d]).*' \
+ -export-symbols-regex '^([^_]|_[^l]|_l[^i]|_li[^b]|_lib[^i]|_libi[^n]|_libin[^t]|_libint[^l]|_libintl[^_]).*' \
-version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \
-rpath $(libdir)
libintl_la_LDFLAGS = $(AM_LDFLAGS) $(OTHER_LDFLAGS)
endif
+# Allow users to use "gnulib-tool --update".
+EXTRA_DIST += gnulib-m4/gnulib-cache.m4
+
+
# Clean up after Solaris cc.
clean-local:
rm -rf SunWS_cache
+++ /dev/null
-/* A C macro for declaring that specific arguments must not be NULL.
- Copyright (C) 2009-2020 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools
- that the values passed as arguments n, ..., m must be non-NULL pointers.
- n = 1 stands for the first argument, n = 2 for the second argument etc. */
-#ifndef _GL_ARG_NONNULL
-# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || defined __clang__
-# define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params))
-# else
-# define _GL_ARG_NONNULL(params)
-# endif
-#endif
+++ /dev/null
-/* ATTRIBUTE_* macros for using attributes in GCC and similar compilers
-
- Copyright 2020 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Paul Eggert. */
-
-/* Provide public ATTRIBUTE_* names for the private _GL_ATTRIBUTE_*
- macros used within Gnulib. */
-
-/* These attributes can be placed in two ways:
- - At the start of a declaration (i.e. even before storage-class
- specifiers!); then they apply to all entities that are declared
- by the declaration.
- - Immediately after the name of an entity being declared by the
- declaration; then they apply to that entity only. */
-
-#ifndef _GL_ATTRIBUTE_H
-#define _GL_ATTRIBUTE_H
-
-
-/* This file defines two types of attributes:
- * C2X standard attributes. These have macro names that do not begin with
- 'ATTRIBUTE_'.
- * Selected GCC attributes; see:
- https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
- https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
- https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html
- These names begin with 'ATTRIBUTE_' to avoid name clashes. */
-
-
-/* =============== Attributes for specific kinds of functions =============== */
-
-/* Attributes for functions that should not be used. */
-
-/* Warn if the entity is used. */
-/* Applies to:
- - function, variable,
- - struct, union, struct/union member,
- - enumeration, enumeration item,
- - typedef,
- in C++ also: namespace, class, template specialization. */
-#define DEPRECATED _GL_ATTRIBUTE_DEPRECATED
-
-/* If a function call is not optimized way, warn with MSG. */
-/* Applies to: functions. */
-#define ATTRIBUTE_WARNING(msg) _GL_ATTRIBUTE_WARNING (msg)
-
-/* If a function call is not optimized way, report an error with MSG. */
-/* Applies to: functions. */
-#define ATTRIBUTE_ERROR(msg) _GL_ATTRIBUTE_ERROR (msg)
-
-
-/* Attributes for memory-allocating functions. */
-
-/* The function returns a pointer to freshly allocated memory. */
-/* Applies to: functions. */
-#define ATTRIBUTE_MALLOC _GL_ATTRIBUTE_MALLOC
-
-/* ATTRIBUTE_ALLOC_SIZE ((N)) - The Nth argument of the function
- is the size of the returned memory block.
- ATTRIBUTE_ALLOC_SIZE ((M, N)) - Multiply the Mth and Nth arguments
- to determine the size of the returned memory block. */
-/* Applies to: function, pointer to function, function types. */
-#define ATTRIBUTE_ALLOC_SIZE(args) _GL_ATTRIBUTE_ALLOC_SIZE (args)
-
-
-/* Attributes for variadic functions. */
-
-/* The variadic function expects a trailing NULL argument.
- ATTRIBUTE_SENTINEL () - The last argument is NULL (requires C99).
- ATTRIBUTE_SENTINEL ((N)) - The (N+1)st argument from the end is NULL. */
-/* Applies to: functions. */
-#define ATTRIBUTE_SENTINEL(pos) _GL_ATTRIBUTE_SENTINEL (pos)
-
-
-/* ================== Attributes for compiler diagnostics ================== */
-
-/* Attributes that help the compiler diagnose programmer mistakes.
- Some of them may also help for some compiler optimizations. */
-
-/* ATTRIBUTE_FORMAT ((ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK)) -
- The STRING-INDEXth function argument is a format string of style
- ARCHETYPE, which is one of:
- printf, gnu_printf
- scanf, gnu_scanf,
- strftime, gnu_strftime,
- strfmon,
- or the same thing prefixed and suffixed with '__'.
- If FIRST-TO-CHECK is not 0, arguments starting at FIRST-TO_CHECK
- are suitable for the format string. */
-/* Applies to: functions. */
-#define ATTRIBUTE_FORMAT(spec) _GL_ATTRIBUTE_FORMAT (spec)
-
-/* ATTRIBUTE_NONNULL ((N1, N2,...)) - Arguments N1, N2,... must not be NULL.
- ATTRIBUTE_NONNULL () - All pointer arguments must not be null. */
-/* Applies to: functions. */
-#define ATTRIBUTE_NONNULL(args) _GL_ATTRIBUTE_NONNULL (args)
-
-/* The function's return value is a non-NULL pointer. */
-/* Applies to: functions. */
-#define ATTRIBUTE_RETURNS_NONNULL _GL_ATTRIBUTE_RETURNS_NONNULL
-
-/* Warn if the caller does not use the return value,
- unless the caller uses something like ignore_value. */
-/* Applies to: function, enumeration, class. */
-#define NODISCARD _GL_ATTRIBUTE_NODISCARD
-
-
-/* Attributes that disable false alarms when the compiler diagnoses
- programmer "mistakes". */
-
-/* Do not warn if the entity is not used. */
-/* Applies to:
- - function, variable,
- - struct, union, struct/union member,
- - enumeration, enumeration item,
- - typedef,
- in C++ also: class. */
-#define MAYBE_UNUSED _GL_ATTRIBUTE_MAYBE_UNUSED
-
-/* The contents of a character array is not meant to be NUL-terminated. */
-/* Applies to: struct/union members and variables that are arrays of element
- type '[[un]signed] char'. */
-#define ATTRIBUTE_NONSTRING _GL_ATTRIBUTE_NONSTRING
-
-/* Do not warn if control flow falls through to the immediately
- following 'case' or 'default' label. */
-/* Applies to: Empty statement (;), inside a 'switch' statement. */
-#define FALLTHROUGH _GL_ATTRIBUTE_FALLTHROUGH
-
-
-/* ================== Attributes for debugging information ================== */
-
-/* Attributes regarding debugging information emitted by the compiler. */
-
-/* Omit the function from stack traces when debugging. */
-/* Applies to: function. */
-#define ATTRIBUTE_ARTIFICIAL _GL_ATTRIBUTE_ARTIFICIAL
-
-/* Make the entity visible to debuggers etc., even with '-fwhole-program'. */
-/* Applies to: functions, variables. */
-#define ATTRIBUTE_EXTERNALLY_VISIBLE _GL_ATTRIBUTE_EXTERNALLY_VISIBLE
-
-
-/* ========== Attributes that mainly direct compiler optimizations ========== */
-
-/* The function does not throw exceptions. */
-/* Applies to: functions. */
-#define ATTRIBUTE_NOTHROW _GL_ATTRIBUTE_NOTHROW
-
-/* Do not inline the function. */
-/* Applies to: functions. */
-#define ATTRIBUTE_NOINLINE _GL_ATTRIBUTE_NOINLINE
-
-/* Always inline the function, and report an error if the compiler
- cannot inline. */
-/* Applies to: function. */
-#define ATTRIBUTE_ALWAYS_INLINE _GL_ATTRIBUTE_ALWAYS_INLINE
-
-/* It is OK for a compiler to omit duplicate calls with the same arguments.
- This attribute is safe for a function that neither depends on
- nor affects observable state, and always returns exactly once -
- e.g., does not loop forever, and does not call longjmp.
- (This attribute is stricter than ATTRIBUTE_PURE.) */
-/* Applies to: functions. */
-#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
-
-/* It is OK for a compiler to omit duplicate calls with the same
- arguments if observable state is not changed between calls.
- This attribute is safe for a function that does not affect
- observable state, and always returns exactly once.
- (This attribute is looser than ATTRIBUTE_CONST.) */
-/* Applies to: functions. */
-#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE
-
-/* The function is rarely executed. */
-/* Applies to: functions. */
-#define ATTRIBUTE_COLD _GL_ATTRIBUTE_COLD
-
-/* If called from some other compilation unit, the function executes
- code from that unit only by return or by exception handling,
- letting the compiler optimize that unit more aggressively. */
-/* Applies to: functions. */
-#define ATTRIBUTE_LEAF _GL_ATTRIBUTE_LEAF
-
-/* For struct members: The member has the smallest possible alignment.
- For struct, union, class: All members have the smallest possible alignment,
- minimizing the memory required. */
-/* Applies to: struct members, struct, union,
- in C++ also: class. */
-#define ATTRIBUTE_PACKED _GL_ATTRIBUTE_PACKED
-
-
-/* ================ Attributes that make invalid code valid ================ */
-
-/* Attributes that prevent fatal compiler optimizations for code that is not
- fully ISO C compliant. */
-
-/* Pointers to the type may point to the same storage as pointers to
- other types, thus disabling strict aliasing optimization. */
-/* Applies to: types. */
-#define ATTRIBUTE_MAY_ALIAS _GL_ATTRIBUTE_MAY_ALIAS
-
-
-#endif /* _GL_ATTRIBUTE_H */
/* Implementation of the bindtextdomain(3) function
- Copyright (C) 1995-2020 Free Software Foundation, Inc.
+ Copyright (C) 1995-2021 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
# define gl_rwlock_wrlock __libc_rwlock_wrlock
# define gl_rwlock_unlock __libc_rwlock_unlock
#else
-# include "lock.h"
+# include "glthread/lock.h"
#endif
/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
dnl Set preferences for the gnulib module 'threadlib'.
gl_AVOID_WINPTHREAD
-dnl Make sure we see all GNU and Solaris extensions.
-gl_USE_SYSTEM_EXTENSIONS
-AM_PROG_CC_C_O
+dnl Set preferences for the gnulib module 'relocatable-lib-lgpl':
+dnl Enable relocatability unconditionally.
+enable_relocatable=yes
+
+dnl Early checks, assembled by gnulib.
+gl_EARLY
dnl Check for build configuration.
AM_CONDITIONAL([PRELOADABLE_LIBINTL],
[test $USE_INCLUDED_LIBINTL = no && test $GLIBC2 = yes && test "$enable_shared" = yes])
-dnl Get common Gnulib macros.
-gl_COMMON
-dnl Get definitions for relocatable.c.
-gl_RELOCATABLE_LIBRARY
+dnl Checks for header files, functions and declarations.
+gl_INIT
dnl Compilation on mingw and Cygwin needs special Makefile rules, because
dnl 1. when we install a shared library, we must arrange to export
dnl Put some default definitions into config.h.
AH_BOTTOM([
+/* Tweak gnulib code according to the needs of this library. */
+#define IN_LIBINTL 1
+
/* On Windows, variables that may be in a DLL must be marked specially. */
#if (defined _MSC_VER && defined _DLL) && !defined IN_RELOCWRAPPER
# define DLL_VARIABLE __declspec (dllimport)
#endif
])
+dnl Rename some macros and functions used for locking.
+AH_VERBATIM([0locking], [
+#define __libc_lock_t gl_lock_t
+#define __libc_lock_define gl_lock_define
+#define __libc_lock_define_initialized gl_lock_define_initialized
+#define __libc_lock_init gl_lock_init
+#define __libc_lock_lock gl_lock_lock
+#define __libc_lock_unlock gl_lock_unlock
+#define __libc_lock_recursive_t gl_recursive_lock_t
+#define __libc_lock_define_recursive gl_recursive_lock_define
+#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized
+#define __libc_lock_init_recursive gl_recursive_lock_init
+#define __libc_lock_lock_recursive gl_recursive_lock_lock
+#define __libc_lock_unlock_recursive gl_recursive_lock_unlock
+])
+
+dnl Hide undesired symbols from the global namespace, by prefixing them with
+dnl "_libintl_" or "_nl_".
+AH_VERBATIM([0noexport], [
+#define asnprintf _libintl_asnprintf
+#define rpl_asnprintf _libintl_asnprintf
+/* Symbols defined by gnulib module 'float'. */
+#define gl_LDBL_MAX _libintl_LDBL_MAX
+/* Symbols defined by gnulib module 'localename'. */
+#define gl_locale_name_canonicalize _nl_locale_name_canonicalize
+#define gl_locale_name_from_win32_LANGID _nl_locale_name_from_win32_LANGID
+#define gl_locale_name_from_win32_LCID _nl_locale_name_from_win32_LCID
+#define gl_locale_name_thread_unsafe _nl_locale_name_thread_unsafe
+#define gl_locale_name_thread _nl_locale_name_thread
+#define gl_locale_name_posix _nl_locale_name_posix
+#define gl_locale_name_environ _nl_locale_name_environ
+#define gl_locale_name_default _nl_locale_name_default
+#define gl_locale_name _nl_locale_name
+/* Symbols defined by gnulib module 'lock'. */
+#define glthread_lock_init _libintl_lock_init
+#define glthread_lock_lock _libintl_lock_lock
+#define glthread_lock_unlock _libintl_lock_unlock
+#define glthread_lock_destroy _libintl_lock_destroy
+#define glthread_rwlock_init _libintl_rwlock_init
+#define glthread_rwlock_rdlock _libintl_rwlock_rdlock
+#define glthread_rwlock_wrlock _libintl_rwlock_wrlock
+#define glthread_rwlock_unlock _libintl_rwlock_unlock
+#define glthread_rwlock_destroy _libintl_rwlock_destroy
+#define glthread_recursive_lock_init _libintl_recursive_lock_init
+#define glthread_recursive_lock_lock _libintl_recursive_lock_lock
+#define glthread_recursive_lock_unlock _libintl_recursive_lock_unlock
+#define glthread_recursive_lock_destroy _libintl_recursive_lock_destroy
+#define glthread_rwlock_init_for_glibc _libintl_rwlock_init_for_glibc
+#define glthread_rwlock_init_multithreaded _libintl_rwlock_init_multithreaded
+#define glthread_rwlock_rdlock_multithreaded _libintl_rwlock_rdlock_multithreaded
+#define glthread_rwlock_wrlock_multithreaded _libintl_rwlock_wrlock_multithreaded
+#define glthread_rwlock_unlock_multithreaded _libintl_rwlock_unlock_multithreaded
+#define glthread_rwlock_destroy_multithreaded _libintl_rwlock_destroy_multithreaded
+#define glthread_recursive_lock_init_multithreaded _libintl_recursive_lock_init_multithreaded
+#define glthread_recursive_lock_lock_multithreaded _libintl_recursive_lock_lock_multithreaded
+#define glthread_recursive_lock_unlock_multithreaded _libintl_recursive_lock_unlock_multithreaded
+#define glthread_recursive_lock_destroy_multithreaded _libintl_recursive_lock_destroy_multithreaded
+#define glthread_once_singlethreaded _libintl_once_singlethreaded
+#define glthread_once_multithreaded _libintl_once_multithreaded
+/* Symbols defined by gnulib module 'relocatable-lib-lgpl'. */
+#define relocate _libintl_relocate
+#define relocate2 _libintl_relocate2
+/* Symbols defined by gnulib module 'setlocale-null'. */
+#define setlocale_null _libintl_setlocale_null
+#define setlocale_null_r _libintl_setlocale_null_r
+/* Symbols defined by gnulib module 'threadlib'. */
+#define glthread_in_use _libintl_glthread_in_use
+/* Symbols defined by gnulib module 'vasnprintf'. */
+#define printf_fetchargs _libintl_printf_fetchargs
+#define printf_parse _libintl_printf_parse
+#define vasnprintf _libintl_vasnprintf
+/* Symbols defined by gnulib module 'windows-mutex'. */
+#define glwthread_mutex_init _libintl_glwthread_mutex_init
+#define glwthread_mutex_lock _libintl_glwthread_mutex_lock
+#define glwthread_mutex_trylock _libintl_glwthread_mutex_trylock
+#define glwthread_mutex_unlock _libintl_glwthread_mutex_unlock
+#define glwthread_mutex_destroy _libintl_glwthread_mutex_destroy
+/* Symbols defined by gnulib module 'windows-once'. */
+#define glwthread_once _libintl_glwthread_once
+/* Symbols defined by gnulib module 'windows-recmutex'. */
+#define glwthread_recmutex_init _libintl_glwthread_recmutex_init
+#define glwthread_recmutex_lock _libintl_glwthread_recmutex_lock
+#define glwthread_recmutex_trylock _libintl_glwthread_recmutex_trylock
+#define glwthread_recmutex_unlock _libintl_glwthread_recmutex_unlock
+#define glwthread_recmutex_destroy _libintl_glwthread_recmutex_destroy
+/* Symbols defined by gnulib module 'windows-rwlock'. */
+#define glwthread_rwlock_init _libintl_glwthread_rwlock_init
+#define glwthread_rwlock_rdlock _libintl_glwthread_rwlock_rdlock
+#define glwthread_rwlock_wrlock _libintl_glwthread_rwlock_wrlock
+#define glwthread_rwlock_tryrdlock _libintl_glwthread_rwlock_tryrdlock
+#define glwthread_rwlock_trywrlock _libintl_glwthread_rwlock_trywrlock
+#define glwthread_rwlock_unlock _libintl_glwthread_rwlock_unlock
+#define glwthread_rwlock_destroy _libintl_glwthread_rwlock_destroy
+/* Symbols defined by gnulib module 'xsize'. */
+#define xmax _libintl_xmax
+#define xsum _libintl_xsum
+#define xsum3 _libintl_xsum3
+#define xsum4 _libintl_xsum4
+])
+dnl Symbols defined by gnulib module 'memchr'.
+if test $REPLACE_MEMCHR = 1; then
+ AC_DEFINE([memchr], [_libintl_memchr], [Hidden symbol.])
+ AC_DEFINE([rpl_memchr], [_libintl_memchr], [Hidden symbol.])
+fi
+dnl Symbols defined by gnulib module 'tsearch'.
+if test $HAVE_TSEARCH = 0 || test $HAVE_TWALK = 0 || test $REPLACE_TSEARCH = 1; then
+ AC_DEFINE([tsearch], [_libintl_tsearch], [Hidden symbol.])
+ AC_DEFINE([rpl_tsearch], [_libintl_tsearch], [Hidden symbol.])
+ AC_DEFINE([tfind], [_libintl_tfind], [Hidden symbol.])
+ AC_DEFINE([rpl_tfind], [_libintl_tfind], [Hidden symbol.])
+ AC_DEFINE([tdelete], [_libintl_tdelete], [Hidden symbol.])
+ AC_DEFINE([rpl_tdelete], [_libintl_tdelete], [Hidden symbol.])
+ AC_DEFINE([twalk], [_libintl_twalk], [Hidden symbol.])
+ AC_DEFINE([rpl_twalk], [_libintl_twalk], [Hidden symbol.])
+fi
+
AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([gnulib-lib/Makefile])
AC_OUTPUT
/* Implementation of the internal dcigettext function.
- Copyright (C) 1995-2020 Free Software Foundation, Inc.
+ Copyright (C) 1995-2021 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
#if !defined _LIBC
# include "localcharset.h"
+# include "localename.h"
#endif
#include "gettextP.h"
# define gl_rwlock_wrlock __libc_rwlock_wrlock
# define gl_rwlock_unlock __libc_rwlock_unlock
#else
-# include "lock.h"
+# include "glthread/lock.h"
#endif
/* Alignment of types. */
# endif
#endif
-/* Use a replacement if the system does not provide the `tsearch' function
- family. */
-#if defined HAVE_TSEARCH || defined _LIBC
-# include <search.h>
-#else
-# define tsearch libintl_tsearch
-# define tfind libintl_tfind
-# define tdelete libintl_tdelete
-# define twalk libintl_twalk
-# include "tsearch.h"
-#endif
-
+#include <search.h>
#ifdef _LIBC
# define tsearch __tsearch
#endif
}
#endif
-#if !_LIBC && !HAVE_TSEARCH
-# include "tsearch.c"
-#endif
-
#ifdef _LIBC
/* If we want to free all resources we have to do some work at
+++ /dev/null
-/* Basic filename support macros.
- Copyright (C) 2001-2004, 2007-2020 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* From Paul Eggert and Jim Meyering. */
-
-#ifndef _FILENAME_H
-#define _FILENAME_H
-
-#include <string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Filename support.
- ISSLASH(C) tests whether C is a directory separator
- character.
- HAS_DEVICE(Filename) tests whether Filename contains a device
- specification.
- FILE_SYSTEM_PREFIX_LEN(Filename) length of the device specification
- at the beginning of Filename,
- index of the part consisting of
- alternating components and slashes.
- FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
- 1 when a non-empty device specification
- can be followed by an empty or relative
- part,
- 0 when a non-empty device specification
- must be followed by a slash,
- 0 when device specification don't exist.
- IS_ABSOLUTE_FILE_NAME(Filename)
- tests whether Filename is independent of
- any notion of "current directory".
- IS_RELATIVE_FILE_NAME(Filename)
- tests whether Filename may be concatenated
- to a directory filename.
- Note: On native Windows, OS/2, DOS, "c:" is neither an absolute nor a
- relative file name!
- IS_FILE_NAME_WITH_DIR(Filename) tests whether Filename contains a device
- or directory specification.
- */
-#if defined _WIN32 || defined __CYGWIN__ \
- || defined __EMX__ || defined __MSDOS__ || defined __DJGPP__
- /* Native Windows, Cygwin, OS/2, DOS */
-# define ISSLASH(C) ((C) == '/' || (C) == '\\')
- /* Internal macro: Tests whether a character is a drive letter. */
-# define _IS_DRIVE_LETTER(C) \
- (((C) >= 'A' && (C) <= 'Z') || ((C) >= 'a' && (C) <= 'z'))
- /* Help the compiler optimizing it. This assumes ASCII. */
-# undef _IS_DRIVE_LETTER
-# define _IS_DRIVE_LETTER(C) \
- (((unsigned int) (C) | ('a' - 'A')) - 'a' <= 'z' - 'a')
-# define HAS_DEVICE(Filename) \
- (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':')
-# define FILE_SYSTEM_PREFIX_LEN(Filename) (HAS_DEVICE (Filename) ? 2 : 0)
-# ifdef __CYGWIN__
-# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
-# else
- /* On native Windows, OS/2, DOS, the system has the notion of a
- "current directory" on each drive. */
-# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
-# endif
-# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
-# define IS_ABSOLUTE_FILE_NAME(Filename) \
- ISSLASH ((Filename)[FILE_SYSTEM_PREFIX_LEN (Filename)])
-# else
-# define IS_ABSOLUTE_FILE_NAME(Filename) \
- (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename))
-# endif
-# define IS_RELATIVE_FILE_NAME(Filename) \
- (! (ISSLASH ((Filename)[0]) || HAS_DEVICE (Filename)))
-# define IS_FILE_NAME_WITH_DIR(Filename) \
- (strchr ((Filename), '/') != NULL || strchr ((Filename), '\\') != NULL \
- || HAS_DEVICE (Filename))
-#else
- /* Unix */
-# define ISSLASH(C) ((C) == '/')
-# define HAS_DEVICE(Filename) ((void) (Filename), 0)
-# define FILE_SYSTEM_PREFIX_LEN(Filename) ((void) (Filename), 0)
-# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
-# define IS_ABSOLUTE_FILE_NAME(Filename) ISSLASH ((Filename)[0])
-# define IS_RELATIVE_FILE_NAME(Filename) (! ISSLASH ((Filename)[0]))
-# define IS_FILE_NAME_WITH_DIR(Filename) (strchr ((Filename), '/') != NULL)
-#endif
-
-/* Deprecated macros. For backward compatibility with old users of the
- 'filename' module. */
-#define IS_ABSOLUTE_PATH IS_ABSOLUTE_FILE_NAME
-#define IS_PATH_WITH_DIR IS_FILE_NAME_WITH_DIR
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _FILENAME_H */
/* Handle list of needed message catalogs
- Copyright (C) 1995-2020 Free Software Foundation, Inc.
+ Copyright (C) 1995-2021 Free Software Foundation, Inc.
Written by Ulrich Drepper <drepper@gnu.org>, 1995.
This program is free software: you can redistribute it and/or modify
# define gl_rwlock_wrlock __libc_rwlock_wrlock
# define gl_rwlock_unlock __libc_rwlock_unlock
#else
-# include "lock.h"
+# include "glthread/lock.h"
#endif
/* @@ end of prolog @@ */
+++ /dev/null
-/* Sizes of structs with flexible array members.
-
- Copyright 2016-2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
-
- Written by Paul Eggert. */
-
-#include <stddef.h>
-
-/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below.
- On older platforms without _Alignof, use a pessimistic bound that is
- safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1.
- On newer platforms, use _Alignof to get a tighter bound. */
-
-#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
-# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1))
-#else
-# define FLEXALIGNOF(type) _Alignof (type)
-#endif
-
-/* Yield a properly aligned upper bound on the size of a struct of
- type TYPE with a flexible array member named MEMBER that is
- followed by N bytes of other data. The result is suitable as an
- argument to malloc. For example:
-
- struct s { int n; char d[FLEXIBLE_ARRAY_MEMBER]; };
- struct s *p = malloc (FLEXSIZEOF (struct s, d, n * sizeof (char)));
-
- FLEXSIZEOF (TYPE, MEMBER, N) is not simply (sizeof (TYPE) + N),
- since FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms. Nor is
- it simply (offsetof (TYPE, MEMBER) + N), as that might yield a size
- that causes malloc to yield a pointer that is not properly aligned
- for TYPE; for example, if sizeof (int) == alignof (int) == 4,
- malloc (offsetof (struct s, d) + 3 * sizeof (char)) is equivalent
- to malloc (7) and might yield a pointer that is not a multiple of 4
- (which means the pointer is not properly aligned for struct s),
- whereas malloc (FLEXSIZEOF (struct s, d, 3 * sizeof (char))) is
- equivalent to malloc (8) and must yield a pointer that is a
- multiple of 4.
-
- Yield a value less than N if and only if arithmetic overflow occurs. */
-
-#define FLEXSIZEOF(type, member, n) \
- ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \
- & ~ (FLEXALIGNOF (type) - 1))
/* Header describing internals of libintl library.
- Copyright (C) 1995-2020 Free Software Foundation, Inc.
+ Copyright (C) 1995-2021 Free Software Foundation, Inc.
Written by Ulrich Drepper <drepper@cygnus.com>, 1995.
This program is free software: you can redistribute it and/or modify
# include <bits/libc-lock.h>
# define gl_rwlock_define __libc_rwlock_define
#else
-# include "lock.h"
+# include "glthread/lock.h"
#endif
#ifdef _LIBC
#ifndef _LIBC
extern const char *_nl_language_preferences_default (void);
-# define gl_locale_name_canonicalize _nl_locale_name_canonicalize
extern void _nl_locale_name_canonicalize (char *name);
-# define gl_locale_name_from_win32_LANGID _nl_locale_name_from_win32_LANGID
/* extern const char *_nl_locale_name_from_win32_LANGID (LANGID langid); */
-# define gl_locale_name_from_win32_LCID _nl_locale_name_from_win32_LCID
/* extern const char *_nl_locale_name_from_win32_LCID (LCID lcid); */
-# define gl_locale_name_thread_unsafe _nl_locale_name_thread_unsafe
extern const char *_nl_locale_name_thread_unsafe (int category,
const char *categoryname);
-# define gl_locale_name_thread _nl_locale_name_thread
-/* extern const char *_nl_locale_name_thread (int category,
- const char *categoryname); */
-# define gl_locale_name_posix _nl_locale_name_posix
-extern const char *_nl_locale_name_posix (int category,
- const char *categoryname);
-# define gl_locale_name_environ _nl_locale_name_environ
-extern const char *_nl_locale_name_environ (int category,
- const char *categoryname);
-# define gl_locale_name_default _nl_locale_name_default
-extern const char *_nl_locale_name_default (void);
-# define gl_locale_name _nl_locale_name
-/* extern const char *_nl_locale_name (int category,
- const char *categoryname); */
#endif
struct loaded_l10nfile *_nl_find_domain (const char *__dirname,
/* Load needed message catalogs.
- Copyright (C) 1995-2020 Free Software Foundation, Inc.
+ Copyright (C) 1995-2021 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
#ifdef _LIBC
# include <bits/libc-lock.h>
#else
-# include "lock.h"
+# include "glthread/lock.h"
#endif
/* Provide fallback values for macros that ought to be defined in <inttypes.h>.
+++ /dev/null
-/* Determine a canonical name for the current locale's character encoding.
-
- Copyright (C) 2000-2006, 2008-2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>. */
-
-#include <config.h>
-
-/* Specification. */
-#include "localcharset.h"
-
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#if defined __APPLE__ && defined __MACH__ && HAVE_LANGINFO_CODESET
-# define DARWIN7 /* Darwin 7 or newer, i.e. Mac OS X 10.3 or newer */
-#endif
-
-#if defined _WIN32 && !defined __CYGWIN__
-# define WINDOWS_NATIVE
-# include <locale.h>
-#endif
-
-#if defined __EMX__
-/* Assume EMX program runs on OS/2, even if compiled under DOS. */
-# ifndef OS2
-# define OS2
-# endif
-#endif
-
-#if !defined WINDOWS_NATIVE
-# if HAVE_LANGINFO_CODESET
-# include <langinfo.h>
-# else
-# if 0 /* see comment regarding use of setlocale(), below */
-# include <locale.h>
-# endif
-# endif
-# ifdef __CYGWIN__
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-# endif
-#elif defined WINDOWS_NATIVE
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
- /* For the use of setlocale() below, the Gnulib override in setlocale.c is
- not needed; see the platform lists in setlocale_null.m4. */
-# undef setlocale
-#endif
-#if defined OS2
-# define INCL_DOS
-# include <os2.h>
-#endif
-
-/* For MB_CUR_MAX_L */
-#if defined DARWIN7
-# include <xlocale.h>
-#endif
-
-
-#if HAVE_LANGINFO_CODESET || defined WINDOWS_NATIVE || defined OS2
-
-/* On these platforms, we use a mapping from non-canonical encoding name
- to GNU canonical encoding name. */
-
-/* With glibc-2.1 or newer, we don't need any canonicalization,
- because glibc has iconv and both glibc and libiconv support all
- GNU canonical names directly. */
-# if !((defined __GNU_LIBRARY__ && __GLIBC__ >= 2) || defined __UCLIBC__)
-
-struct table_entry
-{
- const char alias[11+1];
- const char canonical[11+1];
-};
-
-/* Table of platform-dependent mappings, sorted in ascending order. */
-static const struct table_entry alias_table[] =
- {
-# if defined __FreeBSD__ /* FreeBSD */
- /*{ "ARMSCII-8", "ARMSCII-8" },*/
- { "Big5", "BIG5" },
- { "C", "ASCII" },
- /*{ "CP1131", "CP1131" },*/
- /*{ "CP1251", "CP1251" },*/
- /*{ "CP866", "CP866" },*/
- /*{ "GB18030", "GB18030" },*/
- /*{ "GB2312", "GB2312" },*/
- /*{ "GBK", "GBK" },*/
- /*{ "ISCII-DEV", "?" },*/
- { "ISO8859-1", "ISO-8859-1" },
- { "ISO8859-13", "ISO-8859-13" },
- { "ISO8859-15", "ISO-8859-15" },
- { "ISO8859-2", "ISO-8859-2" },
- { "ISO8859-5", "ISO-8859-5" },
- { "ISO8859-7", "ISO-8859-7" },
- { "ISO8859-9", "ISO-8859-9" },
- /*{ "KOI8-R", "KOI8-R" },*/
- /*{ "KOI8-U", "KOI8-U" },*/
- { "SJIS", "SHIFT_JIS" },
- { "US-ASCII", "ASCII" },
- { "eucCN", "GB2312" },
- { "eucJP", "EUC-JP" },
- { "eucKR", "EUC-KR" }
-# define alias_table_defined
-# endif
-# if defined __NetBSD__ /* NetBSD */
- { "646", "ASCII" },
- /*{ "ARMSCII-8", "ARMSCII-8" },*/
- /*{ "BIG5", "BIG5" },*/
- { "Big5-HKSCS", "BIG5-HKSCS" },
- /*{ "CP1251", "CP1251" },*/
- /*{ "CP866", "CP866" },*/
- /*{ "GB18030", "GB18030" },*/
- /*{ "GB2312", "GB2312" },*/
- { "ISO8859-1", "ISO-8859-1" },
- { "ISO8859-13", "ISO-8859-13" },
- { "ISO8859-15", "ISO-8859-15" },
- { "ISO8859-2", "ISO-8859-2" },
- { "ISO8859-4", "ISO-8859-4" },
- { "ISO8859-5", "ISO-8859-5" },
- { "ISO8859-7", "ISO-8859-7" },
- /*{ "KOI8-R", "KOI8-R" },*/
- /*{ "KOI8-U", "KOI8-U" },*/
- /*{ "PT154", "PT154" },*/
- { "SJIS", "SHIFT_JIS" },
- { "eucCN", "GB2312" },
- { "eucJP", "EUC-JP" },
- { "eucKR", "EUC-KR" },
- { "eucTW", "EUC-TW" }
-# define alias_table_defined
-# endif
-# if defined __OpenBSD__ /* OpenBSD */
- { "646", "ASCII" },
- { "ISO8859-1", "ISO-8859-1" },
- { "ISO8859-13", "ISO-8859-13" },
- { "ISO8859-15", "ISO-8859-15" },
- { "ISO8859-2", "ISO-8859-2" },
- { "ISO8859-4", "ISO-8859-4" },
- { "ISO8859-5", "ISO-8859-5" },
- { "ISO8859-7", "ISO-8859-7" },
- { "US-ASCII", "ASCII" }
-# define alias_table_defined
-# endif
-# if defined __APPLE__ && defined __MACH__ /* Mac OS X */
- /* Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is
- useless:
- - It returns the empty string when LANG is set to a locale of the
- form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8
- LC_CTYPE file.
- - The environment variables LANG, LC_CTYPE, LC_ALL are not set by
- the system; nl_langinfo(CODESET) returns "US-ASCII" in this case.
- - The documentation says:
- "... all code that calls BSD system routines should ensure
- that the const *char parameters of these routines are in UTF-8
- encoding. All BSD system functions expect their string
- parameters to be in UTF-8 encoding and nothing else."
- It also says
- "An additional caveat is that string parameters for files,
- paths, and other file-system entities must be in canonical
- UTF-8. In a canonical UTF-8 Unicode string, all decomposable
- characters are decomposed ..."
- but this is not true: You can pass non-decomposed UTF-8 strings
- to file system functions, and it is the OS which will convert
- them to decomposed UTF-8 before accessing the file system.
- - The Apple Terminal application displays UTF-8 by default.
- - However, other applications are free to use different encodings:
- - xterm uses ISO-8859-1 by default.
- - TextEdit uses MacRoman by default.
- We prefer UTF-8 over decomposed UTF-8-MAC because one should
- minimize the use of decomposed Unicode. Unfortunately, through the
- Darwin file system, decomposed UTF-8 strings are leaked into user
- space nevertheless.
- Then there are also the locales with encodings other than US-ASCII
- and UTF-8. These locales can be occasionally useful to users (e.g.
- when grepping through ISO-8859-1 encoded text files), when all their
- file names are in US-ASCII.
- */
- { "ARMSCII-8", "ARMSCII-8" },
- { "Big5", "BIG5" },
- { "Big5HKSCS", "BIG5-HKSCS" },
- { "CP1131", "CP1131" },
- { "CP1251", "CP1251" },
- { "CP866", "CP866" },
- { "CP949", "CP949" },
- { "GB18030", "GB18030" },
- { "GB2312", "GB2312" },
- { "GBK", "GBK" },
- /*{ "ISCII-DEV", "?" },*/
- { "ISO8859-1", "ISO-8859-1" },
- { "ISO8859-13", "ISO-8859-13" },
- { "ISO8859-15", "ISO-8859-15" },
- { "ISO8859-2", "ISO-8859-2" },
- { "ISO8859-4", "ISO-8859-4" },
- { "ISO8859-5", "ISO-8859-5" },
- { "ISO8859-7", "ISO-8859-7" },
- { "ISO8859-9", "ISO-8859-9" },
- { "KOI8-R", "KOI8-R" },
- { "KOI8-U", "KOI8-U" },
- { "PT154", "PT154" },
- { "SJIS", "SHIFT_JIS" },
- { "eucCN", "GB2312" },
- { "eucJP", "EUC-JP" },
- { "eucKR", "EUC-KR" }
-# define alias_table_defined
-# endif
-# if defined _AIX /* AIX */
- /*{ "GBK", "GBK" },*/
- { "IBM-1046", "CP1046" },
- { "IBM-1124", "CP1124" },
- { "IBM-1129", "CP1129" },
- { "IBM-1252", "CP1252" },
- { "IBM-850", "CP850" },
- { "IBM-856", "CP856" },
- { "IBM-921", "ISO-8859-13" },
- { "IBM-922", "CP922" },
- { "IBM-932", "CP932" },
- { "IBM-943", "CP943" },
- { "IBM-eucCN", "GB2312" },
- { "IBM-eucJP", "EUC-JP" },
- { "IBM-eucKR", "EUC-KR" },
- { "IBM-eucTW", "EUC-TW" },
- { "ISO8859-1", "ISO-8859-1" },
- { "ISO8859-15", "ISO-8859-15" },
- { "ISO8859-2", "ISO-8859-2" },
- { "ISO8859-5", "ISO-8859-5" },
- { "ISO8859-6", "ISO-8859-6" },
- { "ISO8859-7", "ISO-8859-7" },
- { "ISO8859-8", "ISO-8859-8" },
- { "ISO8859-9", "ISO-8859-9" },
- { "TIS-620", "TIS-620" },
- /*{ "UTF-8", "UTF-8" },*/
- { "big5", "BIG5" }
-# define alias_table_defined
-# endif
-# if defined __hpux /* HP-UX */
- { "SJIS", "SHIFT_JIS" },
- { "arabic8", "HP-ARABIC8" },
- { "big5", "BIG5" },
- { "cp1251", "CP1251" },
- { "eucJP", "EUC-JP" },
- { "eucKR", "EUC-KR" },
- { "eucTW", "EUC-TW" },
- { "gb18030", "GB18030" },
- { "greek8", "HP-GREEK8" },
- { "hebrew8", "HP-HEBREW8" },
- { "hkbig5", "BIG5-HKSCS" },
- { "hp15CN", "GB2312" },
- { "iso88591", "ISO-8859-1" },
- { "iso885913", "ISO-8859-13" },
- { "iso885915", "ISO-8859-15" },
- { "iso88592", "ISO-8859-2" },
- { "iso88594", "ISO-8859-4" },
- { "iso88595", "ISO-8859-5" },
- { "iso88596", "ISO-8859-6" },
- { "iso88597", "ISO-8859-7" },
- { "iso88598", "ISO-8859-8" },
- { "iso88599", "ISO-8859-9" },
- { "kana8", "HP-KANA8" },
- { "koi8r", "KOI8-R" },
- { "roman8", "HP-ROMAN8" },
- { "tis620", "TIS-620" },
- { "turkish8", "HP-TURKISH8" },
- { "utf8", "UTF-8" }
-# define alias_table_defined
-# endif
-# if defined __sgi /* IRIX */
- { "ISO8859-1", "ISO-8859-1" },
- { "ISO8859-15", "ISO-8859-15" },
- { "ISO8859-2", "ISO-8859-2" },
- { "ISO8859-5", "ISO-8859-5" },
- { "ISO8859-7", "ISO-8859-7" },
- { "ISO8859-9", "ISO-8859-9" },
- { "eucCN", "GB2312" },
- { "eucJP", "EUC-JP" },
- { "eucKR", "EUC-KR" },
- { "eucTW", "EUC-TW" }
-# define alias_table_defined
-# endif
-# if defined __osf__ /* OSF/1 */
- /*{ "GBK", "GBK" },*/
- { "ISO8859-1", "ISO-8859-1" },
- { "ISO8859-15", "ISO-8859-15" },
- { "ISO8859-2", "ISO-8859-2" },
- { "ISO8859-4", "ISO-8859-4" },
- { "ISO8859-5", "ISO-8859-5" },
- { "ISO8859-7", "ISO-8859-7" },
- { "ISO8859-8", "ISO-8859-8" },
- { "ISO8859-9", "ISO-8859-9" },
- { "KSC5601", "CP949" },
- { "SJIS", "SHIFT_JIS" },
- { "TACTIS", "TIS-620" },
- /*{ "UTF-8", "UTF-8" },*/
- { "big5", "BIG5" },
- { "cp850", "CP850" },
- { "dechanyu", "DEC-HANYU" },
- { "dechanzi", "GB2312" },
- { "deckanji", "DEC-KANJI" },
- { "deckorean", "EUC-KR" },
- { "eucJP", "EUC-JP" },
- { "eucKR", "EUC-KR" },
- { "eucTW", "EUC-TW" },
- { "sdeckanji", "EUC-JP" }
-# define alias_table_defined
-# endif
-# if defined __sun /* Solaris */
- { "5601", "EUC-KR" },
- { "646", "ASCII" },
- /*{ "BIG5", "BIG5" },*/
- { "Big5-HKSCS", "BIG5-HKSCS" },
- { "GB18030", "GB18030" },
- /*{ "GBK", "GBK" },*/
- { "ISO8859-1", "ISO-8859-1" },
- { "ISO8859-11", "TIS-620" },
- { "ISO8859-13", "ISO-8859-13" },
- { "ISO8859-15", "ISO-8859-15" },
- { "ISO8859-2", "ISO-8859-2" },
- { "ISO8859-3", "ISO-8859-3" },
- { "ISO8859-4", "ISO-8859-4" },
- { "ISO8859-5", "ISO-8859-5" },
- { "ISO8859-6", "ISO-8859-6" },
- { "ISO8859-7", "ISO-8859-7" },
- { "ISO8859-8", "ISO-8859-8" },
- { "ISO8859-9", "ISO-8859-9" },
- { "PCK", "SHIFT_JIS" },
- { "TIS620.2533", "TIS-620" },
- /*{ "UTF-8", "UTF-8" },*/
- { "ansi-1251", "CP1251" },
- { "cns11643", "EUC-TW" },
- { "eucJP", "EUC-JP" },
- { "gb2312", "GB2312" },
- { "koi8-r", "KOI8-R" }
-# define alias_table_defined
-# endif
-# if defined __minix /* Minix */
- { "646", "ASCII" }
-# define alias_table_defined
-# endif
-# if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Windows */
- { "CP1361", "JOHAB" },
- { "CP20127", "ASCII" },
- { "CP20866", "KOI8-R" },
- { "CP20936", "GB2312" },
- { "CP21866", "KOI8-RU" },
- { "CP28591", "ISO-8859-1" },
- { "CP28592", "ISO-8859-2" },
- { "CP28593", "ISO-8859-3" },
- { "CP28594", "ISO-8859-4" },
- { "CP28595", "ISO-8859-5" },
- { "CP28596", "ISO-8859-6" },
- { "CP28597", "ISO-8859-7" },
- { "CP28598", "ISO-8859-8" },
- { "CP28599", "ISO-8859-9" },
- { "CP28605", "ISO-8859-15" },
- { "CP38598", "ISO-8859-8" },
- { "CP51932", "EUC-JP" },
- { "CP51936", "GB2312" },
- { "CP51949", "EUC-KR" },
- { "CP51950", "EUC-TW" },
- { "CP54936", "GB18030" },
- { "CP65001", "UTF-8" },
- { "CP936", "GBK" }
-# define alias_table_defined
-# endif
-# if defined OS2 /* OS/2 */
- /* The list of encodings is taken from "List of OS/2 Codepages"
- by Alex Taylor:
- <http://altsan.org/os2/toolkits/uls/index.html#codepages>.
- See also "__convcp() of kLIBC":
- <https://github.com/bitwiseworks/libc/blob/master/src/emx/src/lib/locale/__convcp.c>. */
- { "CP1004", "CP1252" },
- /*{ "CP1041", "CP943" },*/
- /*{ "CP1088", "CP949" },*/
- { "CP1089", "ISO-8859-6" },
- /*{ "CP1114", "CP950" },*/
- /*{ "CP1115", "GB2312" },*/
- { "CP1208", "UTF-8" },
- /*{ "CP1380", "GB2312" },*/
- { "CP1381", "GB2312" },
- { "CP1383", "GB2312" },
- { "CP1386", "GBK" },
- /*{ "CP301", "CP943" },*/
- { "CP3372", "EUC-JP" },
- { "CP4946", "CP850" },
- /*{ "CP5048", "JIS_X0208-1990" },*/
- /*{ "CP5049", "JIS_X0212-1990" },*/
- /*{ "CP5067", "KS_C_5601-1987" },*/
- { "CP813", "ISO-8859-7" },
- { "CP819", "ISO-8859-1" },
- { "CP878", "KOI8-R" },
- /*{ "CP897", "CP943" },*/
- { "CP912", "ISO-8859-2" },
- { "CP913", "ISO-8859-3" },
- { "CP914", "ISO-8859-4" },
- { "CP915", "ISO-8859-5" },
- { "CP916", "ISO-8859-8" },
- { "CP920", "ISO-8859-9" },
- { "CP921", "ISO-8859-13" },
- { "CP923", "ISO-8859-15" },
- /*{ "CP941", "CP943" },*/
- /*{ "CP947", "CP950" },*/
- /*{ "CP951", "CP949" },*/
- /*{ "CP952", "JIS_X0208-1990" },*/
- /*{ "CP953", "JIS_X0212-1990" },*/
- { "CP954", "EUC-JP" },
- { "CP964", "EUC-TW" },
- { "CP970", "EUC-KR" },
- /*{ "CP971", "KS_C_5601-1987" },*/
- { "IBM-1004", "CP1252" },
- /*{ "IBM-1006", "?" },*/
- /*{ "IBM-1008", "?" },*/
- /*{ "IBM-1041", "CP943" },*/
- /*{ "IBM-1051", "?" },*/
- /*{ "IBM-1088", "CP949" },*/
- { "IBM-1089", "ISO-8859-6" },
- /*{ "IBM-1098", "?" },*/
- /*{ "IBM-1114", "CP950" },*/
- /*{ "IBM-1115", "GB2312" },*/
- /*{ "IBM-1116", "?" },*/
- /*{ "IBM-1117", "?" },*/
- /*{ "IBM-1118", "?" },*/
- /*{ "IBM-1119", "?" },*/
- { "IBM-1124", "CP1124" },
- { "IBM-1125", "CP1125" },
- { "IBM-1131", "CP1131" },
- { "IBM-1208", "UTF-8" },
- { "IBM-1250", "CP1250" },
- { "IBM-1251", "CP1251" },
- { "IBM-1252", "CP1252" },
- { "IBM-1253", "CP1253" },
- { "IBM-1254", "CP1254" },
- { "IBM-1255", "CP1255" },
- { "IBM-1256", "CP1256" },
- { "IBM-1257", "CP1257" },
- /*{ "IBM-1275", "?" },*/
- /*{ "IBM-1276", "?" },*/
- /*{ "IBM-1277", "?" },*/
- /*{ "IBM-1280", "?" },*/
- /*{ "IBM-1281", "?" },*/
- /*{ "IBM-1282", "?" },*/
- /*{ "IBM-1283", "?" },*/
- /*{ "IBM-1380", "GB2312" },*/
- { "IBM-1381", "GB2312" },
- { "IBM-1383", "GB2312" },
- { "IBM-1386", "GBK" },
- /*{ "IBM-301", "CP943" },*/
- { "IBM-3372", "EUC-JP" },
- { "IBM-367", "ASCII" },
- { "IBM-437", "CP437" },
- { "IBM-4946", "CP850" },
- /*{ "IBM-5048", "JIS_X0208-1990" },*/
- /*{ "IBM-5049", "JIS_X0212-1990" },*/
- /*{ "IBM-5067", "KS_C_5601-1987" },*/
- { "IBM-813", "ISO-8859-7" },
- { "IBM-819", "ISO-8859-1" },
- { "IBM-850", "CP850" },
- /*{ "IBM-851", "?" },*/
- { "IBM-852", "CP852" },
- { "IBM-855", "CP855" },
- { "IBM-856", "CP856" },
- { "IBM-857", "CP857" },
- /*{ "IBM-859", "?" },*/
- { "IBM-860", "CP860" },
- { "IBM-861", "CP861" },
- { "IBM-862", "CP862" },
- { "IBM-863", "CP863" },
- { "IBM-864", "CP864" },
- { "IBM-865", "CP865" },
- { "IBM-866", "CP866" },
- /*{ "IBM-868", "?" },*/
- { "IBM-869", "CP869" },
- { "IBM-874", "CP874" },
- { "IBM-878", "KOI8-R" },
- /*{ "IBM-895", "?" },*/
- /*{ "IBM-897", "CP943" },*/
- /*{ "IBM-907", "?" },*/
- /*{ "IBM-909", "?" },*/
- { "IBM-912", "ISO-8859-2" },
- { "IBM-913", "ISO-8859-3" },
- { "IBM-914", "ISO-8859-4" },
- { "IBM-915", "ISO-8859-5" },
- { "IBM-916", "ISO-8859-8" },
- { "IBM-920", "ISO-8859-9" },
- { "IBM-921", "ISO-8859-13" },
- { "IBM-922", "CP922" },
- { "IBM-923", "ISO-8859-15" },
- { "IBM-932", "CP932" },
- /*{ "IBM-941", "CP943" },*/
- /*{ "IBM-942", "?" },*/
- { "IBM-943", "CP943" },
- /*{ "IBM-947", "CP950" },*/
- { "IBM-949", "CP949" },
- { "IBM-950", "CP950" },
- /*{ "IBM-951", "CP949" },*/
- /*{ "IBM-952", "JIS_X0208-1990" },*/
- /*{ "IBM-953", "JIS_X0212-1990" },*/
- { "IBM-954", "EUC-JP" },
- /*{ "IBM-955", "?" },*/
- { "IBM-964", "EUC-TW" },
- { "IBM-970", "EUC-KR" },
- /*{ "IBM-971", "KS_C_5601-1987" },*/
- { "IBM-eucCN", "GB2312" },
- { "IBM-eucJP", "EUC-JP" },
- { "IBM-eucKR", "EUC-KR" },
- { "IBM-eucTW", "EUC-TW" },
- { "IBM33722", "EUC-JP" },
- { "ISO8859-1", "ISO-8859-1" },
- { "ISO8859-2", "ISO-8859-2" },
- { "ISO8859-3", "ISO-8859-3" },
- { "ISO8859-4", "ISO-8859-4" },
- { "ISO8859-5", "ISO-8859-5" },
- { "ISO8859-6", "ISO-8859-6" },
- { "ISO8859-7", "ISO-8859-7" },
- { "ISO8859-8", "ISO-8859-8" },
- { "ISO8859-9", "ISO-8859-9" },
- /*{ "JISX0201-1976", "JISX0201-1976" },*/
- /*{ "JISX0208-1978", "?" },*/
- /*{ "JISX0208-1983", "JIS_X0208-1983" },*/
- /*{ "JISX0208-1990", "JIS_X0208-1990" },*/
- /*{ "JISX0212-1990", "JIS_X0212-1990" },*/
- /*{ "KSC5601-1987", "KS_C_5601-1987" },*/
- { "SJIS-1", "CP943" },
- { "SJIS-2", "CP943" },
- { "eucJP", "EUC-JP" },
- { "eucKR", "EUC-KR" },
- { "eucTW-1993", "EUC-TW" }
-# define alias_table_defined
-# endif
-# if defined VMS /* OpenVMS */
- /* The list of encodings is taken from the OpenVMS 7.3-1 documentation
- "Compaq C Run-Time Library Reference Manual for OpenVMS systems"
- section 10.7 "Handling Different Character Sets". */
- { "DECHANYU", "DEC-HANYU" },
- { "DECHANZI", "GB2312" },
- { "DECKANJI", "DEC-KANJI" },
- { "DECKOREAN", "EUC-KR" },
- { "ISO8859-1", "ISO-8859-1" },
- { "ISO8859-2", "ISO-8859-2" },
- { "ISO8859-5", "ISO-8859-5" },
- { "ISO8859-7", "ISO-8859-7" },
- { "ISO8859-8", "ISO-8859-8" },
- { "ISO8859-9", "ISO-8859-9" },
- { "SDECKANJI", "EUC-JP" },
- { "SJIS", "SHIFT_JIS" },
- { "eucJP", "EUC-JP" },
- { "eucTW", "EUC-TW" }
-# define alias_table_defined
-# endif
-# ifndef alias_table_defined
- /* Just a dummy entry, to avoid a C syntax error. */
- { "", "" }
-# endif
- };
-
-# endif
-
-#else
-
-/* On these platforms, we use a mapping from locale name to GNU canonical
- encoding name. */
-
-struct table_entry
-{
- const char locale[17+1];
- const char canonical[11+1];
-};
-
-/* Table of platform-dependent mappings, sorted in ascending order. */
-static const struct table_entry locale_table[] =
- {
-# if defined __FreeBSD__ /* FreeBSD 4.2 */
- { "cs_CZ.ISO_8859-2", "ISO-8859-2" },
- { "da_DK.DIS_8859-15", "ISO-8859-15" },
- { "da_DK.ISO_8859-1", "ISO-8859-1" },
- { "de_AT.DIS_8859-15", "ISO-8859-15" },
- { "de_AT.ISO_8859-1", "ISO-8859-1" },
- { "de_CH.DIS_8859-15", "ISO-8859-15" },
- { "de_CH.ISO_8859-1", "ISO-8859-1" },
- { "de_DE.DIS_8859-15", "ISO-8859-15" },
- { "de_DE.ISO_8859-1", "ISO-8859-1" },
- { "en_AU.DIS_8859-15", "ISO-8859-15" },
- { "en_AU.ISO_8859-1", "ISO-8859-1" },
- { "en_CA.DIS_8859-15", "ISO-8859-15" },
- { "en_CA.ISO_8859-1", "ISO-8859-1" },
- { "en_GB.DIS_8859-15", "ISO-8859-15" },
- { "en_GB.ISO_8859-1", "ISO-8859-1" },
- { "en_US.DIS_8859-15", "ISO-8859-15" },
- { "en_US.ISO_8859-1", "ISO-8859-1" },
- { "es_ES.DIS_8859-15", "ISO-8859-15" },
- { "es_ES.ISO_8859-1", "ISO-8859-1" },
- { "fi_FI.DIS_8859-15", "ISO-8859-15" },
- { "fi_FI.ISO_8859-1", "ISO-8859-1" },
- { "fr_BE.DIS_8859-15", "ISO-8859-15" },
- { "fr_BE.ISO_8859-1", "ISO-8859-1" },
- { "fr_CA.DIS_8859-15", "ISO-8859-15" },
- { "fr_CA.ISO_8859-1", "ISO-8859-1" },
- { "fr_CH.DIS_8859-15", "ISO-8859-15" },
- { "fr_CH.ISO_8859-1", "ISO-8859-1" },
- { "fr_FR.DIS_8859-15", "ISO-8859-15" },
- { "fr_FR.ISO_8859-1", "ISO-8859-1" },
- { "hr_HR.ISO_8859-2", "ISO-8859-2" },
- { "hu_HU.ISO_8859-2", "ISO-8859-2" },
- { "is_IS.DIS_8859-15", "ISO-8859-15" },
- { "is_IS.ISO_8859-1", "ISO-8859-1" },
- { "it_CH.DIS_8859-15", "ISO-8859-15" },
- { "it_CH.ISO_8859-1", "ISO-8859-1" },
- { "it_IT.DIS_8859-15", "ISO-8859-15" },
- { "it_IT.ISO_8859-1", "ISO-8859-1" },
- { "ja_JP.EUC", "EUC-JP" },
- { "ja_JP.SJIS", "SHIFT_JIS" },
- { "ja_JP.Shift_JIS", "SHIFT_JIS" },
- { "ko_KR.EUC", "EUC-KR" },
- { "la_LN.ASCII", "ASCII" },
- { "la_LN.DIS_8859-15", "ISO-8859-15" },
- { "la_LN.ISO_8859-1", "ISO-8859-1" },
- { "la_LN.ISO_8859-2", "ISO-8859-2" },
- { "la_LN.ISO_8859-4", "ISO-8859-4" },
- { "lt_LN.ASCII", "ASCII" },
- { "lt_LN.DIS_8859-15", "ISO-8859-15" },
- { "lt_LN.ISO_8859-1", "ISO-8859-1" },
- { "lt_LN.ISO_8859-2", "ISO-8859-2" },
- { "lt_LT.ISO_8859-4", "ISO-8859-4" },
- { "nl_BE.DIS_8859-15", "ISO-8859-15" },
- { "nl_BE.ISO_8859-1", "ISO-8859-1" },
- { "nl_NL.DIS_8859-15", "ISO-8859-15" },
- { "nl_NL.ISO_8859-1", "ISO-8859-1" },
- { "no_NO.DIS_8859-15", "ISO-8859-15" },
- { "no_NO.ISO_8859-1", "ISO-8859-1" },
- { "pl_PL.ISO_8859-2", "ISO-8859-2" },
- { "pt_PT.DIS_8859-15", "ISO-8859-15" },
- { "pt_PT.ISO_8859-1", "ISO-8859-1" },
- { "ru_RU.CP866", "CP866" },
- { "ru_RU.ISO_8859-5", "ISO-8859-5" },
- { "ru_RU.KOI8-R", "KOI8-R" },
- { "ru_SU.CP866", "CP866" },
- { "ru_SU.ISO_8859-5", "ISO-8859-5" },
- { "ru_SU.KOI8-R", "KOI8-R" },
- { "sl_SI.ISO_8859-2", "ISO-8859-2" },
- { "sv_SE.DIS_8859-15", "ISO-8859-15" },
- { "sv_SE.ISO_8859-1", "ISO-8859-1" },
- { "uk_UA.KOI8-U", "KOI8-U" },
- { "zh_CN.EUC", "GB2312" },
- { "zh_TW.BIG5", "BIG5" },
- { "zh_TW.Big5", "BIG5" }
-# define locale_table_defined
-# endif
-# if defined __DJGPP__ /* DOS / DJGPP 2.03 */
- /* The encodings given here may not all be correct.
- If you find that the encoding given for your language and
- country is not the one your DOS machine actually uses, just
- correct it in this file, and send a mail to
- Juan Manuel Guerrero <juan.guerrero@gmx.de>
- and <bug-gnulib@gnu.org>. */
- { "C", "ASCII" },
- { "ar", "CP864" },
- { "ar_AE", "CP864" },
- { "ar_DZ", "CP864" },
- { "ar_EG", "CP864" },
- { "ar_IQ", "CP864" },
- { "ar_IR", "CP864" },
- { "ar_JO", "CP864" },
- { "ar_KW", "CP864" },
- { "ar_MA", "CP864" },
- { "ar_OM", "CP864" },
- { "ar_QA", "CP864" },
- { "ar_SA", "CP864" },
- { "ar_SY", "CP864" },
- { "be", "CP866" },
- { "be_BE", "CP866" },
- { "bg", "CP866" }, /* not CP855 ?? */
- { "bg_BG", "CP866" }, /* not CP855 ?? */
- { "ca", "CP850" },
- { "ca_ES", "CP850" },
- { "cs", "CP852" },
- { "cs_CZ", "CP852" },
- { "da", "CP865" }, /* not CP850 ?? */
- { "da_DK", "CP865" }, /* not CP850 ?? */
- { "de", "CP850" },
- { "de_AT", "CP850" },
- { "de_CH", "CP850" },
- { "de_DE", "CP850" },
- { "el", "CP869" },
- { "el_GR", "CP869" },
- { "en", "CP850" },
- { "en_AU", "CP850" }, /* not CP437 ?? */
- { "en_CA", "CP850" },
- { "en_GB", "CP850" },
- { "en_NZ", "CP437" },
- { "en_US", "CP437" },
- { "en_ZA", "CP850" }, /* not CP437 ?? */
- { "eo", "CP850" },
- { "eo_EO", "CP850" },
- { "es", "CP850" },
- { "es_AR", "CP850" },
- { "es_BO", "CP850" },
- { "es_CL", "CP850" },
- { "es_CO", "CP850" },
- { "es_CR", "CP850" },
- { "es_CU", "CP850" },
- { "es_DO", "CP850" },
- { "es_EC", "CP850" },
- { "es_ES", "CP850" },
- { "es_GT", "CP850" },
- { "es_HN", "CP850" },
- { "es_MX", "CP850" },
- { "es_NI", "CP850" },
- { "es_PA", "CP850" },
- { "es_PE", "CP850" },
- { "es_PY", "CP850" },
- { "es_SV", "CP850" },
- { "es_UY", "CP850" },
- { "es_VE", "CP850" },
- { "et", "CP850" },
- { "et_EE", "CP850" },
- { "eu", "CP850" },
- { "eu_ES", "CP850" },
- { "fi", "CP850" },
- { "fi_FI", "CP850" },
- { "fr", "CP850" },
- { "fr_BE", "CP850" },
- { "fr_CA", "CP850" },
- { "fr_CH", "CP850" },
- { "fr_FR", "CP850" },
- { "ga", "CP850" },
- { "ga_IE", "CP850" },
- { "gd", "CP850" },
- { "gd_GB", "CP850" },
- { "gl", "CP850" },
- { "gl_ES", "CP850" },
- { "he", "CP862" },
- { "he_IL", "CP862" },
- { "hr", "CP852" },
- { "hr_HR", "CP852" },
- { "hu", "CP852" },
- { "hu_HU", "CP852" },
- { "id", "CP850" }, /* not CP437 ?? */
- { "id_ID", "CP850" }, /* not CP437 ?? */
- { "is", "CP861" }, /* not CP850 ?? */
- { "is_IS", "CP861" }, /* not CP850 ?? */
- { "it", "CP850" },
- { "it_CH", "CP850" },
- { "it_IT", "CP850" },
- { "ja", "CP932" },
- { "ja_JP", "CP932" },
- { "kr", "CP949" }, /* not CP934 ?? */
- { "kr_KR", "CP949" }, /* not CP934 ?? */
- { "lt", "CP775" },
- { "lt_LT", "CP775" },
- { "lv", "CP775" },
- { "lv_LV", "CP775" },
- { "mk", "CP866" }, /* not CP855 ?? */
- { "mk_MK", "CP866" }, /* not CP855 ?? */
- { "mt", "CP850" },
- { "mt_MT", "CP850" },
- { "nb", "CP865" }, /* not CP850 ?? */
- { "nb_NO", "CP865" }, /* not CP850 ?? */
- { "nl", "CP850" },
- { "nl_BE", "CP850" },
- { "nl_NL", "CP850" },
- { "nn", "CP865" }, /* not CP850 ?? */
- { "nn_NO", "CP865" }, /* not CP850 ?? */
- { "no", "CP865" }, /* not CP850 ?? */
- { "no_NO", "CP865" }, /* not CP850 ?? */
- { "pl", "CP852" },
- { "pl_PL", "CP852" },
- { "pt", "CP850" },
- { "pt_BR", "CP850" },
- { "pt_PT", "CP850" },
- { "ro", "CP852" },
- { "ro_RO", "CP852" },
- { "ru", "CP866" },
- { "ru_RU", "CP866" },
- { "sk", "CP852" },
- { "sk_SK", "CP852" },
- { "sl", "CP852" },
- { "sl_SI", "CP852" },
- { "sq", "CP852" },
- { "sq_AL", "CP852" },
- { "sr", "CP852" }, /* CP852 or CP866 or CP855 ?? */
- { "sr_CS", "CP852" }, /* CP852 or CP866 or CP855 ?? */
- { "sr_YU", "CP852" }, /* CP852 or CP866 or CP855 ?? */
- { "sv", "CP850" },
- { "sv_SE", "CP850" },
- { "th", "CP874" },
- { "th_TH", "CP874" },
- { "tr", "CP857" },
- { "tr_TR", "CP857" },
- { "uk", "CP1125" },
- { "uk_UA", "CP1125" },
- { "zh_CN", "GBK" },
- { "zh_TW", "CP950" } /* not CP938 ?? */
-# define locale_table_defined
-# endif
-# ifndef locale_table_defined
- /* Just a dummy entry, to avoid a C syntax error. */
- { "", "" }
-# endif
- };
-
-#endif
-
-
-/* Determine the current locale's character encoding, and canonicalize it
- into one of the canonical names listed below.
- The result must not be freed; it is statically allocated. The result
- becomes invalid when setlocale() is used to change the global locale, or
- when the value of one of the environment variables LC_ALL, LC_CTYPE, LANG
- is changed; threads in multithreaded programs should not do this.
- If the canonical name cannot be determined, the result is a non-canonical
- name. */
-
-#ifdef STATIC
-STATIC
-#endif
-const char *
-locale_charset (void)
-{
- const char *codeset;
-
- /* This function must be multithread-safe. To achieve this without using
- thread-local storage, we use a simple strcpy or memcpy to fill this static
- buffer. Filling it through, for example, strcpy + strcat would not be
- guaranteed to leave the buffer's contents intact if another thread is
- currently accessing it. If necessary, the contents is first assembled in
- a stack-allocated buffer. */
-
-#if HAVE_LANGINFO_CODESET || defined WINDOWS_NATIVE || defined OS2
-
-# if HAVE_LANGINFO_CODESET
-
- /* Most systems support nl_langinfo (CODESET) nowadays. */
- codeset = nl_langinfo (CODESET);
-
-# ifdef __CYGWIN__
- /* Cygwin < 1.7 does not have locales. nl_langinfo (CODESET) always
- returns "US-ASCII". Return the suffix of the locale name from the
- environment variables (if present) or the codepage as a number. */
- if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0)
- {
- const char *locale;
- static char resultbuf[2 + 10 + 1];
-
- locale = getenv ("LC_ALL");
- if (locale == NULL || locale[0] == '\0')
- {
- locale = getenv ("LC_CTYPE");
- if (locale == NULL || locale[0] == '\0')
- locale = getenv ("LANG");
- }
- if (locale != NULL && locale[0] != '\0')
- {
- /* If the locale name contains an encoding after the dot, return
- it. */
- const char *dot = strchr (locale, '.');
-
- if (dot != NULL)
- {
- const char *modifier;
-
- dot++;
- /* Look for the possible @... trailer and remove it, if any. */
- modifier = strchr (dot, '@');
- if (modifier == NULL)
- return dot;
- if (modifier - dot < sizeof (resultbuf))
- {
- /* This way of filling resultbuf is multithread-safe. */
- memcpy (resultbuf, dot, modifier - dot);
- resultbuf [modifier - dot] = '\0';
- return resultbuf;
- }
- }
- }
-
- /* The Windows API has a function returning the locale's codepage as a
- number: GetACP(). This encoding is used by Cygwin, unless the user
- has set the environment variable CYGWIN=codepage:oem (which very few
- people do).
- Output directed to console windows needs to be converted (to
- GetOEMCP() if the console is using a raster font, or to
- GetConsoleOutputCP() if it is using a TrueType font). Cygwin does
- this conversion transparently (see winsup/cygwin/fhandler_console.cc),
- converting to GetConsoleOutputCP(). This leads to correct results,
- except when SetConsoleOutputCP has been called and a raster font is
- in use. */
- {
- char buf[2 + 10 + 1];
-
- sprintf (buf, "CP%u", GetACP ());
- strcpy (resultbuf, buf);
- codeset = resultbuf;
- }
- }
-# endif
-
- if (codeset == NULL)
- /* The canonical name cannot be determined. */
- codeset = "";
-
-# elif defined WINDOWS_NATIVE
-
- char buf[2 + 10 + 1];
- static char resultbuf[2 + 10 + 1];
-
- /* The Windows API has a function returning the locale's codepage as
- a number, but the value doesn't change according to what the
- 'setlocale' call specified. So we use it as a last resort, in
- case the string returned by 'setlocale' doesn't specify the
- codepage. */
- char *current_locale = setlocale (LC_CTYPE, NULL);
- char *pdot = strrchr (current_locale, '.');
-
- if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf))
- sprintf (buf, "CP%s", pdot + 1);
- else
- {
- /* The Windows API has a function returning the locale's codepage as a
- number: GetACP().
- When the output goes to a console window, it needs to be provided in
- GetOEMCP() encoding if the console is using a raster font, or in
- GetConsoleOutputCP() encoding if it is using a TrueType font.
- But in GUI programs and for output sent to files and pipes, GetACP()
- encoding is the best bet. */
- sprintf (buf, "CP%u", GetACP ());
- }
- /* For a locale name such as "French_France.65001", in Windows 10,
- setlocale now returns "French_France.utf8" instead. */
- if (strcmp (buf + 2, "65001") == 0 || strcmp (buf + 2, "utf8") == 0)
- codeset = "UTF-8";
- else
- {
- strcpy (resultbuf, buf);
- codeset = resultbuf;
- }
-
-# elif defined OS2
-
- const char *locale;
- static char resultbuf[2 + 10 + 1];
- ULONG cp[3];
- ULONG cplen;
-
- codeset = NULL;
-
- /* Allow user to override the codeset, as set in the operating system,
- with standard language environment variables. */
- locale = getenv ("LC_ALL");
- if (locale == NULL || locale[0] == '\0')
- {
- locale = getenv ("LC_CTYPE");
- if (locale == NULL || locale[0] == '\0')
- locale = getenv ("LANG");
- }
- if (locale != NULL && locale[0] != '\0')
- {
- /* If the locale name contains an encoding after the dot, return it. */
- const char *dot = strchr (locale, '.');
-
- if (dot != NULL)
- {
- const char *modifier;
-
- dot++;
- /* Look for the possible @... trailer and remove it, if any. */
- modifier = strchr (dot, '@');
- if (modifier == NULL)
- return dot;
- if (modifier - dot < sizeof (resultbuf))
- {
- /* This way of filling resultbuf is multithread-safe. */
- memcpy (resultbuf, dot, modifier - dot);
- resultbuf [modifier - dot] = '\0';
- return resultbuf;
- }
- }
-
- /* For the POSIX locale, don't use the system's codepage. */
- if (strcmp (locale, "C") == 0 || strcmp (locale, "POSIX") == 0)
- codeset = "";
- }
-
- if (codeset == NULL)
- {
- /* OS/2 has a function returning the locale's codepage as a number. */
- if (DosQueryCp (sizeof (cp), cp, &cplen))
- codeset = "";
- else
- {
- char buf[2 + 10 + 1];
-
- sprintf (buf, "CP%u", cp[0]);
- strcpy (resultbuf, buf);
- codeset = resultbuf;
- }
- }
-
-# else
-
-# error "Add code for other platforms here."
-
-# endif
-
- /* Resolve alias. */
- {
-# ifdef alias_table_defined
- /* On some platforms, UTF-8 locales are the most frequently used ones.
- Speed up the common case and slow down the less common cases by
- testing for this case first. */
-# if defined __OpenBSD__ || (defined __APPLE__ && defined __MACH__) || defined __sun || defined __CYGWIN__
- if (strcmp (codeset, "UTF-8") == 0)
- goto done_table_lookup;
- else
-# endif
- {
- const struct table_entry * const table = alias_table;
- size_t const table_size =
- sizeof (alias_table) / sizeof (struct table_entry);
- /* The table is sorted. Perform a binary search. */
- size_t hi = table_size;
- size_t lo = 0;
- while (lo < hi)
- {
- /* Invariant:
- for i < lo, strcmp (table[i].alias, codeset) < 0,
- for i >= hi, strcmp (table[i].alias, codeset) > 0. */
- size_t mid = (hi + lo) >> 1; /* >= lo, < hi */
- int cmp = strcmp (table[mid].alias, codeset);
- if (cmp < 0)
- lo = mid + 1;
- else if (cmp > 0)
- hi = mid;
- else
- {
- /* Found an i with
- strcmp (table[i].alias, codeset) == 0. */
- codeset = table[mid].canonical;
- goto done_table_lookup;
- }
- }
- }
- if (0)
- done_table_lookup: ;
- else
-# endif
- {
- /* Did not find it in the table. */
- /* On Mac OS X, all modern locales use the UTF-8 encoding.
- BeOS and Haiku have a single locale, and it has UTF-8 encoding. */
-# if (defined __APPLE__ && defined __MACH__) || defined __BEOS__ || defined __HAIKU__
- codeset = "UTF-8";
-# else
- /* Don't return an empty string. GNU libc and GNU libiconv interpret
- the empty string as denoting "the locale's character encoding",
- thus GNU libiconv would call this function a second time. */
- if (codeset[0] == '\0')
- codeset = "ASCII";
-# endif
- }
- }
-
-#else
-
- /* On old systems which lack it, use setlocale or getenv. */
- const char *locale = NULL;
-
- /* But most old systems don't have a complete set of locales. Some
- (like DJGPP) have only the C locale. Therefore we don't use setlocale
- here; it would return "C" when it doesn't support the locale name the
- user has set. */
-# if 0
- locale = setlocale (LC_CTYPE, NULL);
-# endif
- if (locale == NULL || locale[0] == '\0')
- {
- locale = getenv ("LC_ALL");
- if (locale == NULL || locale[0] == '\0')
- {
- locale = getenv ("LC_CTYPE");
- if (locale == NULL || locale[0] == '\0')
- locale = getenv ("LANG");
- if (locale == NULL)
- locale = "";
- }
- }
-
- /* Map locale name to canonical encoding name. */
- {
-# ifdef locale_table_defined
- const struct table_entry * const table = locale_table;
- size_t const table_size =
- sizeof (locale_table) / sizeof (struct table_entry);
- /* The table is sorted. Perform a binary search. */
- size_t hi = table_size;
- size_t lo = 0;
- while (lo < hi)
- {
- /* Invariant:
- for i < lo, strcmp (table[i].locale, locale) < 0,
- for i >= hi, strcmp (table[i].locale, locale) > 0. */
- size_t mid = (hi + lo) >> 1; /* >= lo, < hi */
- int cmp = strcmp (table[mid].locale, locale);
- if (cmp < 0)
- lo = mid + 1;
- else if (cmp > 0)
- hi = mid;
- else
- {
- /* Found an i with
- strcmp (table[i].locale, locale) == 0. */
- codeset = table[mid].canonical;
- goto done_table_lookup;
- }
- }
- if (0)
- done_table_lookup: ;
- else
-# endif
- {
- /* Did not find it in the table. */
- /* On Mac OS X, all modern locales use the UTF-8 encoding.
- BeOS and Haiku have a single locale, and it has UTF-8 encoding. */
-# if (defined __APPLE__ && defined __MACH__) || defined __BEOS__ || defined __HAIKU__
- codeset = "UTF-8";
-# else
- /* The canonical name cannot be determined. */
- /* Don't return an empty string. GNU libc and GNU libiconv interpret
- the empty string as denoting "the locale's character encoding",
- thus GNU libiconv would call this function a second time. */
- codeset = "ASCII";
-# endif
- }
- }
-
-#endif
-
-#ifdef DARWIN7
- /* Mac OS X sets MB_CUR_MAX to 1 when LC_ALL=C, and "UTF-8"
- (the default codeset) does not work when MB_CUR_MAX is 1. */
- if (strcmp (codeset, "UTF-8") == 0 && MB_CUR_MAX_L (uselocale (NULL)) <= 1)
- codeset = "ASCII";
-#endif
-
- return codeset;
-}
+++ /dev/null
-/* Determine a canonical name for the current locale's character encoding.
- Copyright (C) 2000-2003, 2018-2019 Free Software Foundation, Inc.
- This file is part of the GNU CHARSET Library.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-#ifndef _LOCALCHARSET_H
-#define _LOCALCHARSET_H
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Determine the current locale's character encoding, and canonicalize it
- into one of the canonical names listed below.
- The result must not be freed; it is statically allocated. The result
- becomes invalid when setlocale() is used to change the global locale, or
- when the value of one of the environment variables LC_ALL, LC_CTYPE, LANG
- is changed; threads in multithreaded programs should not do this.
- If the canonical name cannot be determined, the result is a non-canonical
- name. */
-extern const char * locale_charset (void);
-
-/* About GNU canonical names for character encodings:
-
- Every canonical name must be supported by GNU libiconv. Support by GNU libc
- is also desirable.
-
- The name is case insensitive. Usually an upper case MIME charset name is
- preferred.
-
- The current list of these GNU canonical names is:
-
- name MIME? used by which systems
- (darwin = Mac OS X, windows = native Windows)
-
- ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin minix cygwin
- ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos
- ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos
- ISO-8859-3 Y glibc solaris cygwin
- ISO-8859-4 Y hpux osf solaris freebsd netbsd openbsd darwin
- ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos
- ISO-8859-6 Y glibc aix hpux solaris cygwin
- ISO-8859-7 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos
- ISO-8859-8 Y glibc aix hpux osf solaris cygwin zos
- ISO-8859-9 Y glibc aix hpux irix osf solaris freebsd darwin cygwin zos
- ISO-8859-13 glibc hpux solaris freebsd netbsd openbsd darwin cygwin
- ISO-8859-14 glibc cygwin
- ISO-8859-15 glibc aix irix osf solaris freebsd netbsd openbsd darwin cygwin
- KOI8-R Y glibc hpux solaris freebsd netbsd openbsd darwin
- KOI8-U Y glibc freebsd netbsd openbsd darwin cygwin
- KOI8-T glibc
- CP437 dos
- CP775 dos
- CP850 aix osf dos
- CP852 dos
- CP855 dos
- CP856 aix
- CP857 dos
- CP861 dos
- CP862 dos
- CP864 dos
- CP865 dos
- CP866 freebsd netbsd openbsd darwin dos
- CP869 dos
- CP874 windows dos
- CP922 aix
- CP932 aix cygwin windows dos
- CP943 aix zos
- CP949 osf darwin windows dos
- CP950 windows dos
- CP1046 aix
- CP1124 aix
- CP1125 dos
- CP1129 aix
- CP1131 freebsd darwin
- CP1250 windows
- CP1251 glibc hpux solaris freebsd netbsd openbsd darwin cygwin windows
- CP1252 aix windows
- CP1253 windows
- CP1254 windows
- CP1255 glibc windows
- CP1256 windows
- CP1257 windows
- GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin cygwin zos
- EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin
- EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin zos
- EUC-TW glibc aix hpux irix osf solaris netbsd
- BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin zos
- BIG5-HKSCS glibc hpux solaris netbsd darwin
- GBK glibc aix osf solaris freebsd darwin cygwin windows dos
- GB18030 glibc hpux solaris freebsd netbsd darwin
- SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin
- JOHAB glibc solaris windows
- TIS-620 glibc aix hpux osf solaris cygwin zos
- VISCII Y glibc
- TCVN5712-1 glibc
- ARMSCII-8 glibc freebsd netbsd darwin
- GEORGIAN-PS glibc cygwin
- PT154 glibc netbsd cygwin
- HP-ROMAN8 hpux
- HP-ARABIC8 hpux
- HP-GREEK8 hpux
- HP-HEBREW8 hpux
- HP-TURKISH8 hpux
- HP-KANA8 hpux
- DEC-KANJI osf
- DEC-HANYU osf
- UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin zos
-
- Note: Names which are not marked as being a MIME name should not be used in
- Internet protocols for information interchange (mail, news, etc.).
-
- Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications
- must understand both names and treat them as equivalent.
- */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif /* _LOCALCHARSET_H */
/* Handle aliases for locale names.
- Copyright (C) 1995-2017 Free Software Foundation, Inc.
+ Copyright (C) 1995-2017, 2021 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
#ifdef _LIBC
# include <bits/libc-lock.h>
#else
-# include "lock.h"
+# include "glthread/lock.h"
#endif
#ifndef internal_function
+++ /dev/null
-/* Table that maps a locale object to the names of the locale categories.
- Copyright (C) 2018 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2018. */
-
-#include <config.h>
-
-#if HAVE_WORKING_USELOCALE && HAVE_NAMELESS_LOCALES
-
-/* Specification. */
-#include "localename-table.h"
-
-#include <stdint.h>
-
-/* A hash function for pointers. */
-size_t _GL_ATTRIBUTE_CONST
-locale_hash_function (locale_t x)
-{
- uintptr_t p = (uintptr_t) x;
- size_t h = ((p % 4177) << 12) + ((p % 79) << 6) + (p % 61);
- return h;
-}
-
-struct locale_hash_node * locale_hash_table[LOCALE_HASH_TABLE_SIZE]
- /* = { NULL, ..., NULL } */;
-
-gl_rwlock_define_initialized(, locale_lock)
-
-#else
-
-/* This declaration is solely to ensure that after preprocessing
- this file is never empty. */
-typedef int dummy;
-
-#endif
+++ /dev/null
-/* Table that maps a locale object to the names of the locale categories.
- Copyright (C) 2018 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2018. */
-
-#if HAVE_WORKING_USELOCALE && HAVE_NAMELESS_LOCALES
-
-# include <stddef.h>
-# include <locale.h>
-
-# ifdef IN_LIBINTL
-# include "lock.h"
-# else
-# include "glthread/lock.h"
-# endif
-
-struct locale_categories_names
- {
- /* Locale category -> name (allocated with indefinite extent). */
- const char *category_name[6];
- };
-
-/* A hash table of fixed size. Multiple threads can access it read-only
- simultaneously, but only one thread can insert into it or remove from it
- at the same time.
- This hash table has global scope, so that when an application uses both
- GNU libintl and gnulib, the application sees only one hash table. (When
- linking statically with libintl, the fact that localename-table.c is a
- separate compilation unit resolves the duplicate symbol conflict. When
- linking with libintl as a shared library, we rely on ELF and the symbol
- conflict resolution implemented in the ELF dynamic loader here.)
- Both the libintl overrides and the gnulib overrides of the functions
- newlocale, duplocale, freelocale see the same hash table (and the same lock).
- For this reason, the internal layout of the hash table and the hash function
- MUST NEVER CHANGE. If you need to change the internal layout or the hash
- function, introduce versioning by appending a version suffix to the symbols
- at the linker level. */
-# define locale_hash_function libintl_locale_hash_function
-# define locale_hash_table libintl_locale_hash_table
-# define locale_lock libintl_locale_lock
-
-extern size_t _GL_ATTRIBUTE_CONST locale_hash_function (locale_t x);
-
-/* A node in a hash bucket collision list. */
-struct locale_hash_node
- {
- struct locale_hash_node *next;
- locale_t locale;
- struct locale_categories_names names;
- };
-
-# define LOCALE_HASH_TABLE_SIZE 101
-extern struct locale_hash_node * locale_hash_table[LOCALE_HASH_TABLE_SIZE];
-
-/* This lock protects the locale_hash_table against multiple simultaneous
- accesses (except that multiple simultaneous read accesses are allowed). */
-
-gl_rwlock_define(extern, locale_lock)
-
-#endif
+++ /dev/null
-/* Determine name of the currently selected locale.
- Copyright (C) 1995-2021 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */
-/* Native Windows code written by Tor Lillqvist <tml@iki.fi>. */
-/* Mac OS X code written by Bruno Haible <bruno@clisp.org>. */
-
-#include <config.h>
-
-/* Specification. */
-#ifdef IN_LIBINTL
-# include "gettextP.h"
-#else
-# include "localename.h"
-#endif
-
-#include <limits.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <locale.h>
-#include <string.h>
-
-#include "flexmember.h"
-#include "setlocale_null.h"
-#include "thread-optim.h"
-
-#if HAVE_GOOD_USELOCALE
-/* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */
-# if defined __APPLE__ && defined __MACH__
-# include <xlocale.h>
-# endif
-# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGINFO_H) || defined __CYGWIN__
-# include <langinfo.h>
-# endif
-# if !defined IN_LIBINTL
-# include "glthread/lock.h"
-# endif
-# if defined __sun
-# if HAVE_GETLOCALENAME_L
-/* Solaris >= 12. */
-extern char * getlocalename_l(int, locale_t);
-# elif HAVE_SOLARIS114_LOCALES
-# include <sys/localedef.h>
-# endif
-# endif
-# if HAVE_NAMELESS_LOCALES
-# include <errno.h>
-# include "localename-table.h"
-# endif
-#endif
-
-#if HAVE_CFPREFERENCESCOPYAPPVALUE
-# include <CoreFoundation/CFString.h>
-# include <CoreFoundation/CFPreferences.h>
-#endif
-
-#if defined _WIN32 && !defined __CYGWIN__
-# define WINDOWS_NATIVE
-# if !defined IN_LIBINTL
-# include "glthread/lock.h"
-# endif
-#endif
-
-#if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-# include <winnls.h>
-/* List of language codes, sorted by value:
- 0x01 LANG_ARABIC
- 0x02 LANG_BULGARIAN
- 0x03 LANG_CATALAN
- 0x04 LANG_CHINESE
- 0x05 LANG_CZECH
- 0x06 LANG_DANISH
- 0x07 LANG_GERMAN
- 0x08 LANG_GREEK
- 0x09 LANG_ENGLISH
- 0x0a LANG_SPANISH
- 0x0b LANG_FINNISH
- 0x0c LANG_FRENCH
- 0x0d LANG_HEBREW
- 0x0e LANG_HUNGARIAN
- 0x0f LANG_ICELANDIC
- 0x10 LANG_ITALIAN
- 0x11 LANG_JAPANESE
- 0x12 LANG_KOREAN
- 0x13 LANG_DUTCH
- 0x14 LANG_NORWEGIAN
- 0x15 LANG_POLISH
- 0x16 LANG_PORTUGUESE
- 0x17 LANG_ROMANSH
- 0x18 LANG_ROMANIAN
- 0x19 LANG_RUSSIAN
- 0x1a LANG_CROATIAN == LANG_SERBIAN
- 0x1b LANG_SLOVAK
- 0x1c LANG_ALBANIAN
- 0x1d LANG_SWEDISH
- 0x1e LANG_THAI
- 0x1f LANG_TURKISH
- 0x20 LANG_URDU
- 0x21 LANG_INDONESIAN
- 0x22 LANG_UKRAINIAN
- 0x23 LANG_BELARUSIAN
- 0x24 LANG_SLOVENIAN
- 0x25 LANG_ESTONIAN
- 0x26 LANG_LATVIAN
- 0x27 LANG_LITHUANIAN
- 0x28 LANG_TAJIK
- 0x29 LANG_FARSI
- 0x2a LANG_VIETNAMESE
- 0x2b LANG_ARMENIAN
- 0x2c LANG_AZERI
- 0x2d LANG_BASQUE
- 0x2e LANG_SORBIAN
- 0x2f LANG_MACEDONIAN
- 0x30 LANG_SUTU
- 0x31 LANG_TSONGA
- 0x32 LANG_TSWANA
- 0x33 LANG_VENDA
- 0x34 LANG_XHOSA
- 0x35 LANG_ZULU
- 0x36 LANG_AFRIKAANS
- 0x37 LANG_GEORGIAN
- 0x38 LANG_FAEROESE
- 0x39 LANG_HINDI
- 0x3a LANG_MALTESE
- 0x3b LANG_SAMI
- 0x3c LANG_GAELIC
- 0x3d LANG_YIDDISH
- 0x3e LANG_MALAY
- 0x3f LANG_KAZAK
- 0x40 LANG_KYRGYZ
- 0x41 LANG_SWAHILI
- 0x42 LANG_TURKMEN
- 0x43 LANG_UZBEK
- 0x44 LANG_TATAR
- 0x45 LANG_BENGALI
- 0x46 LANG_PUNJABI
- 0x47 LANG_GUJARATI
- 0x48 LANG_ORIYA
- 0x49 LANG_TAMIL
- 0x4a LANG_TELUGU
- 0x4b LANG_KANNADA
- 0x4c LANG_MALAYALAM
- 0x4d LANG_ASSAMESE
- 0x4e LANG_MARATHI
- 0x4f LANG_SANSKRIT
- 0x50 LANG_MONGOLIAN
- 0x51 LANG_TIBETAN
- 0x52 LANG_WELSH
- 0x53 LANG_CAMBODIAN
- 0x54 LANG_LAO
- 0x55 LANG_BURMESE
- 0x56 LANG_GALICIAN
- 0x57 LANG_KONKANI
- 0x58 LANG_MANIPURI
- 0x59 LANG_SINDHI
- 0x5a LANG_SYRIAC
- 0x5b LANG_SINHALESE
- 0x5c LANG_CHEROKEE
- 0x5d LANG_INUKTITUT
- 0x5e LANG_AMHARIC
- 0x5f LANG_TAMAZIGHT
- 0x60 LANG_KASHMIRI
- 0x61 LANG_NEPALI
- 0x62 LANG_FRISIAN
- 0x63 LANG_PASHTO
- 0x64 LANG_TAGALOG
- 0x65 LANG_DIVEHI
- 0x66 LANG_EDO
- 0x67 LANG_FULFULDE
- 0x68 LANG_HAUSA
- 0x69 LANG_IBIBIO
- 0x6a LANG_YORUBA
- 0x6d LANG_BASHKIR
- 0x6e LANG_LUXEMBOURGISH
- 0x6f LANG_GREENLANDIC
- 0x70 LANG_IGBO
- 0x71 LANG_KANURI
- 0x72 LANG_OROMO
- 0x73 LANG_TIGRINYA
- 0x74 LANG_GUARANI
- 0x75 LANG_HAWAIIAN
- 0x76 LANG_LATIN
- 0x77 LANG_SOMALI
- 0x78 LANG_YI
- 0x79 LANG_PAPIAMENTU
- 0x7a LANG_MAPUDUNGUN
- 0x7c LANG_MOHAWK
- 0x7e LANG_BRETON
- 0x82 LANG_OCCITAN
- 0x83 LANG_CORSICAN
- 0x84 LANG_ALSATIAN
- 0x85 LANG_YAKUT
- 0x86 LANG_KICHE
- 0x87 LANG_KINYARWANDA
- 0x88 LANG_WOLOF
- 0x8c LANG_DARI
- 0x91 LANG_SCOTTISH_GAELIC
-*/
-/* Mingw headers don't have latest language and sublanguage codes. */
-# ifndef LANG_AFRIKAANS
-# define LANG_AFRIKAANS 0x36
-# endif
-# ifndef LANG_ALBANIAN
-# define LANG_ALBANIAN 0x1c
-# endif
-# ifndef LANG_ALSATIAN
-# define LANG_ALSATIAN 0x84
-# endif
-# ifndef LANG_AMHARIC
-# define LANG_AMHARIC 0x5e
-# endif
-# ifndef LANG_ARABIC
-# define LANG_ARABIC 0x01
-# endif
-# ifndef LANG_ARMENIAN
-# define LANG_ARMENIAN 0x2b
-# endif
-# ifndef LANG_ASSAMESE
-# define LANG_ASSAMESE 0x4d
-# endif
-# ifndef LANG_AZERI
-# define LANG_AZERI 0x2c
-# endif
-# ifndef LANG_BASHKIR
-# define LANG_BASHKIR 0x6d
-# endif
-# ifndef LANG_BASQUE
-# define LANG_BASQUE 0x2d
-# endif
-# ifndef LANG_BELARUSIAN
-# define LANG_BELARUSIAN 0x23
-# endif
-# ifndef LANG_BENGALI
-# define LANG_BENGALI 0x45
-# endif
-# ifndef LANG_BRETON
-# define LANG_BRETON 0x7e
-# endif
-# ifndef LANG_BURMESE
-# define LANG_BURMESE 0x55
-# endif
-# ifndef LANG_CAMBODIAN
-# define LANG_CAMBODIAN 0x53
-# endif
-# ifndef LANG_CATALAN
-# define LANG_CATALAN 0x03
-# endif
-# ifndef LANG_CHEROKEE
-# define LANG_CHEROKEE 0x5c
-# endif
-# ifndef LANG_CORSICAN
-# define LANG_CORSICAN 0x83
-# endif
-# ifndef LANG_DARI
-# define LANG_DARI 0x8c
-# endif
-# ifndef LANG_DIVEHI
-# define LANG_DIVEHI 0x65
-# endif
-# ifndef LANG_EDO
-# define LANG_EDO 0x66
-# endif
-# ifndef LANG_ESTONIAN
-# define LANG_ESTONIAN 0x25
-# endif
-# ifndef LANG_FAEROESE
-# define LANG_FAEROESE 0x38
-# endif
-# ifndef LANG_FARSI
-# define LANG_FARSI 0x29
-# endif
-# ifndef LANG_FRISIAN
-# define LANG_FRISIAN 0x62
-# endif
-# ifndef LANG_FULFULDE
-# define LANG_FULFULDE 0x67
-# endif
-# ifndef LANG_GAELIC
-# define LANG_GAELIC 0x3c
-# endif
-# ifndef LANG_GALICIAN
-# define LANG_GALICIAN 0x56
-# endif
-# ifndef LANG_GEORGIAN
-# define LANG_GEORGIAN 0x37
-# endif
-# ifndef LANG_GREENLANDIC
-# define LANG_GREENLANDIC 0x6f
-# endif
-# ifndef LANG_GUARANI
-# define LANG_GUARANI 0x74
-# endif
-# ifndef LANG_GUJARATI
-# define LANG_GUJARATI 0x47
-# endif
-# ifndef LANG_HAUSA
-# define LANG_HAUSA 0x68
-# endif
-# ifndef LANG_HAWAIIAN
-# define LANG_HAWAIIAN 0x75
-# endif
-# ifndef LANG_HEBREW
-# define LANG_HEBREW 0x0d
-# endif
-# ifndef LANG_HINDI
-# define LANG_HINDI 0x39
-# endif
-# ifndef LANG_IBIBIO
-# define LANG_IBIBIO 0x69
-# endif
-# ifndef LANG_IGBO
-# define LANG_IGBO 0x70
-# endif
-# ifndef LANG_INDONESIAN
-# define LANG_INDONESIAN 0x21
-# endif
-# ifndef LANG_INUKTITUT
-# define LANG_INUKTITUT 0x5d
-# endif
-# ifndef LANG_KANNADA
-# define LANG_KANNADA 0x4b
-# endif
-# ifndef LANG_KANURI
-# define LANG_KANURI 0x71
-# endif
-# ifndef LANG_KASHMIRI
-# define LANG_KASHMIRI 0x60
-# endif
-# ifndef LANG_KAZAK
-# define LANG_KAZAK 0x3f
-# endif
-# ifndef LANG_KICHE
-# define LANG_KICHE 0x86
-# endif
-# ifndef LANG_KINYARWANDA
-# define LANG_KINYARWANDA 0x87
-# endif
-# ifndef LANG_KONKANI
-# define LANG_KONKANI 0x57
-# endif
-# ifndef LANG_KYRGYZ
-# define LANG_KYRGYZ 0x40
-# endif
-# ifndef LANG_LAO
-# define LANG_LAO 0x54
-# endif
-# ifndef LANG_LATIN
-# define LANG_LATIN 0x76
-# endif
-# ifndef LANG_LATVIAN
-# define LANG_LATVIAN 0x26
-# endif
-# ifndef LANG_LITHUANIAN
-# define LANG_LITHUANIAN 0x27
-# endif
-# ifndef LANG_LUXEMBOURGISH
-# define LANG_LUXEMBOURGISH 0x6e
-# endif
-# ifndef LANG_MACEDONIAN
-# define LANG_MACEDONIAN 0x2f
-# endif
-# ifndef LANG_MALAY
-# define LANG_MALAY 0x3e
-# endif
-# ifndef LANG_MALAYALAM
-# define LANG_MALAYALAM 0x4c
-# endif
-# ifndef LANG_MALTESE
-# define LANG_MALTESE 0x3a
-# endif
-# ifndef LANG_MANIPURI
-# define LANG_MANIPURI 0x58
-# endif
-# ifndef LANG_MAORI
-# define LANG_MAORI 0x81
-# endif
-# ifndef LANG_MAPUDUNGUN
-# define LANG_MAPUDUNGUN 0x7a
-# endif
-# ifndef LANG_MARATHI
-# define LANG_MARATHI 0x4e
-# endif
-# ifndef LANG_MOHAWK
-# define LANG_MOHAWK 0x7c
-# endif
-# ifndef LANG_MONGOLIAN
-# define LANG_MONGOLIAN 0x50
-# endif
-# ifndef LANG_NEPALI
-# define LANG_NEPALI 0x61
-# endif
-# ifndef LANG_OCCITAN
-# define LANG_OCCITAN 0x82
-# endif
-# ifndef LANG_ORIYA
-# define LANG_ORIYA 0x48
-# endif
-# ifndef LANG_OROMO
-# define LANG_OROMO 0x72
-# endif
-# ifndef LANG_PAPIAMENTU
-# define LANG_PAPIAMENTU 0x79
-# endif
-# ifndef LANG_PASHTO
-# define LANG_PASHTO 0x63
-# endif
-# ifndef LANG_PUNJABI
-# define LANG_PUNJABI 0x46
-# endif
-# ifndef LANG_QUECHUA
-# define LANG_QUECHUA 0x6b
-# endif
-# ifndef LANG_ROMANSH
-# define LANG_ROMANSH 0x17
-# endif
-# ifndef LANG_SAMI
-# define LANG_SAMI 0x3b
-# endif
-# ifndef LANG_SANSKRIT
-# define LANG_SANSKRIT 0x4f
-# endif
-# ifndef LANG_SCOTTISH_GAELIC
-# define LANG_SCOTTISH_GAELIC 0x91
-# endif
-# ifndef LANG_SERBIAN
-# define LANG_SERBIAN 0x1a
-# endif
-# ifndef LANG_SINDHI
-# define LANG_SINDHI 0x59
-# endif
-# ifndef LANG_SINHALESE
-# define LANG_SINHALESE 0x5b
-# endif
-# ifndef LANG_SLOVAK
-# define LANG_SLOVAK 0x1b
-# endif
-# ifndef LANG_SOMALI
-# define LANG_SOMALI 0x77
-# endif
-# ifndef LANG_SORBIAN
-# define LANG_SORBIAN 0x2e
-# endif
-# ifndef LANG_SOTHO
-# define LANG_SOTHO 0x6c
-# endif
-# ifndef LANG_SUTU
-# define LANG_SUTU 0x30
-# endif
-# ifndef LANG_SWAHILI
-# define LANG_SWAHILI 0x41
-# endif
-# ifndef LANG_SYRIAC
-# define LANG_SYRIAC 0x5a
-# endif
-# ifndef LANG_TAGALOG
-# define LANG_TAGALOG 0x64
-# endif
-# ifndef LANG_TAJIK
-# define LANG_TAJIK 0x28
-# endif
-# ifndef LANG_TAMAZIGHT
-# define LANG_TAMAZIGHT 0x5f
-# endif
-# ifndef LANG_TAMIL
-# define LANG_TAMIL 0x49
-# endif
-# ifndef LANG_TATAR
-# define LANG_TATAR 0x44
-# endif
-# ifndef LANG_TELUGU
-# define LANG_TELUGU 0x4a
-# endif
-# ifndef LANG_THAI
-# define LANG_THAI 0x1e
-# endif
-# ifndef LANG_TIBETAN
-# define LANG_TIBETAN 0x51
-# endif
-# ifndef LANG_TIGRINYA
-# define LANG_TIGRINYA 0x73
-# endif
-# ifndef LANG_TSONGA
-# define LANG_TSONGA 0x31
-# endif
-# ifndef LANG_TSWANA
-# define LANG_TSWANA 0x32
-# endif
-# ifndef LANG_TURKMEN
-# define LANG_TURKMEN 0x42
-# endif
-# ifndef LANG_UIGHUR
-# define LANG_UIGHUR 0x80
-# endif
-# ifndef LANG_UKRAINIAN
-# define LANG_UKRAINIAN 0x22
-# endif
-# ifndef LANG_URDU
-# define LANG_URDU 0x20
-# endif
-# ifndef LANG_UZBEK
-# define LANG_UZBEK 0x43
-# endif
-# ifndef LANG_VENDA
-# define LANG_VENDA 0x33
-# endif
-# ifndef LANG_VIETNAMESE
-# define LANG_VIETNAMESE 0x2a
-# endif
-# ifndef LANG_WELSH
-# define LANG_WELSH 0x52
-# endif
-# ifndef LANG_WOLOF
-# define LANG_WOLOF 0x88
-# endif
-# ifndef LANG_XHOSA
-# define LANG_XHOSA 0x34
-# endif
-# ifndef LANG_YAKUT
-# define LANG_YAKUT 0x85
-# endif
-# ifndef LANG_YI
-# define LANG_YI 0x78
-# endif
-# ifndef LANG_YIDDISH
-# define LANG_YIDDISH 0x3d
-# endif
-# ifndef LANG_YORUBA
-# define LANG_YORUBA 0x6a
-# endif
-# ifndef LANG_ZULU
-# define LANG_ZULU 0x35
-# endif
-# ifndef SUBLANG_AFRIKAANS_SOUTH_AFRICA
-# define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01
-# endif
-# ifndef SUBLANG_ALBANIAN_ALBANIA
-# define SUBLANG_ALBANIAN_ALBANIA 0x01
-# endif
-# ifndef SUBLANG_ALSATIAN_FRANCE
-# define SUBLANG_ALSATIAN_FRANCE 0x01
-# endif
-# ifndef SUBLANG_AMHARIC_ETHIOPIA
-# define SUBLANG_AMHARIC_ETHIOPIA 0x01
-# endif
-# ifndef SUBLANG_ARABIC_SAUDI_ARABIA
-# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
-# endif
-# ifndef SUBLANG_ARABIC_IRAQ
-# define SUBLANG_ARABIC_IRAQ 0x02
-# endif
-# ifndef SUBLANG_ARABIC_EGYPT
-# define SUBLANG_ARABIC_EGYPT 0x03
-# endif
-# ifndef SUBLANG_ARABIC_LIBYA
-# define SUBLANG_ARABIC_LIBYA 0x04
-# endif
-# ifndef SUBLANG_ARABIC_ALGERIA
-# define SUBLANG_ARABIC_ALGERIA 0x05
-# endif
-# ifndef SUBLANG_ARABIC_MOROCCO
-# define SUBLANG_ARABIC_MOROCCO 0x06
-# endif
-# ifndef SUBLANG_ARABIC_TUNISIA
-# define SUBLANG_ARABIC_TUNISIA 0x07
-# endif
-# ifndef SUBLANG_ARABIC_OMAN
-# define SUBLANG_ARABIC_OMAN 0x08
-# endif
-# ifndef SUBLANG_ARABIC_YEMEN
-# define SUBLANG_ARABIC_YEMEN 0x09
-# endif
-# ifndef SUBLANG_ARABIC_SYRIA
-# define SUBLANG_ARABIC_SYRIA 0x0a
-# endif
-# ifndef SUBLANG_ARABIC_JORDAN
-# define SUBLANG_ARABIC_JORDAN 0x0b
-# endif
-# ifndef SUBLANG_ARABIC_LEBANON
-# define SUBLANG_ARABIC_LEBANON 0x0c
-# endif
-# ifndef SUBLANG_ARABIC_KUWAIT
-# define SUBLANG_ARABIC_KUWAIT 0x0d
-# endif
-# ifndef SUBLANG_ARABIC_UAE
-# define SUBLANG_ARABIC_UAE 0x0e
-# endif
-# ifndef SUBLANG_ARABIC_BAHRAIN
-# define SUBLANG_ARABIC_BAHRAIN 0x0f
-# endif
-# ifndef SUBLANG_ARABIC_QATAR
-# define SUBLANG_ARABIC_QATAR 0x10
-# endif
-# ifndef SUBLANG_ARMENIAN_ARMENIA
-# define SUBLANG_ARMENIAN_ARMENIA 0x01
-# endif
-# ifndef SUBLANG_ASSAMESE_INDIA
-# define SUBLANG_ASSAMESE_INDIA 0x01
-# endif
-# ifndef SUBLANG_AZERI_LATIN
-# define SUBLANG_AZERI_LATIN 0x01
-# endif
-# ifndef SUBLANG_AZERI_CYRILLIC
-# define SUBLANG_AZERI_CYRILLIC 0x02
-# endif
-# ifndef SUBLANG_BASHKIR_RUSSIA
-# define SUBLANG_BASHKIR_RUSSIA 0x01
-# endif
-# ifndef SUBLANG_BASQUE_BASQUE
-# define SUBLANG_BASQUE_BASQUE 0x01
-# endif
-# ifndef SUBLANG_BELARUSIAN_BELARUS
-# define SUBLANG_BELARUSIAN_BELARUS 0x01
-# endif
-# ifndef SUBLANG_BENGALI_INDIA
-# define SUBLANG_BENGALI_INDIA 0x01
-# endif
-# ifndef SUBLANG_BENGALI_BANGLADESH
-# define SUBLANG_BENGALI_BANGLADESH 0x02
-# endif
-# ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
-# define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05
-# endif
-# ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
-# define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08
-# endif
-# ifndef SUBLANG_BRETON_FRANCE
-# define SUBLANG_BRETON_FRANCE 0x01
-# endif
-# ifndef SUBLANG_BULGARIAN_BULGARIA
-# define SUBLANG_BULGARIAN_BULGARIA 0x01
-# endif
-# ifndef SUBLANG_CAMBODIAN_CAMBODIA
-# define SUBLANG_CAMBODIAN_CAMBODIA 0x01
-# endif
-# ifndef SUBLANG_CATALAN_SPAIN
-# define SUBLANG_CATALAN_SPAIN 0x01
-# endif
-# ifndef SUBLANG_CORSICAN_FRANCE
-# define SUBLANG_CORSICAN_FRANCE 0x01
-# endif
-# ifndef SUBLANG_CROATIAN_CROATIA
-# define SUBLANG_CROATIAN_CROATIA 0x01
-# endif
-# ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
-# define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04
-# endif
-# ifndef SUBLANG_CHINESE_MACAU
-# define SUBLANG_CHINESE_MACAU 0x05
-# endif
-# ifndef SUBLANG_CZECH_CZECH_REPUBLIC
-# define SUBLANG_CZECH_CZECH_REPUBLIC 0x01
-# endif
-# ifndef SUBLANG_DANISH_DENMARK
-# define SUBLANG_DANISH_DENMARK 0x01
-# endif
-# ifndef SUBLANG_DARI_AFGHANISTAN
-# define SUBLANG_DARI_AFGHANISTAN 0x01
-# endif
-# ifndef SUBLANG_DIVEHI_MALDIVES
-# define SUBLANG_DIVEHI_MALDIVES 0x01
-# endif
-# ifndef SUBLANG_DUTCH_SURINAM
-# define SUBLANG_DUTCH_SURINAM 0x03
-# endif
-# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
-# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
-# endif
-# ifndef SUBLANG_ENGLISH_JAMAICA
-# define SUBLANG_ENGLISH_JAMAICA 0x08
-# endif
-# ifndef SUBLANG_ENGLISH_CARIBBEAN
-# define SUBLANG_ENGLISH_CARIBBEAN 0x09
-# endif
-# ifndef SUBLANG_ENGLISH_BELIZE
-# define SUBLANG_ENGLISH_BELIZE 0x0a
-# endif
-# ifndef SUBLANG_ENGLISH_TRINIDAD
-# define SUBLANG_ENGLISH_TRINIDAD 0x0b
-# endif
-# ifndef SUBLANG_ENGLISH_ZIMBABWE
-# define SUBLANG_ENGLISH_ZIMBABWE 0x0c
-# endif
-# ifndef SUBLANG_ENGLISH_PHILIPPINES
-# define SUBLANG_ENGLISH_PHILIPPINES 0x0d
-# endif
-# ifndef SUBLANG_ENGLISH_INDONESIA
-# define SUBLANG_ENGLISH_INDONESIA 0x0e
-# endif
-# ifndef SUBLANG_ENGLISH_HONGKONG
-# define SUBLANG_ENGLISH_HONGKONG 0x0f
-# endif
-# ifndef SUBLANG_ENGLISH_INDIA
-# define SUBLANG_ENGLISH_INDIA 0x10
-# endif
-# ifndef SUBLANG_ENGLISH_MALAYSIA
-# define SUBLANG_ENGLISH_MALAYSIA 0x11
-# endif
-# ifndef SUBLANG_ENGLISH_SINGAPORE
-# define SUBLANG_ENGLISH_SINGAPORE 0x12
-# endif
-# ifndef SUBLANG_ESTONIAN_ESTONIA
-# define SUBLANG_ESTONIAN_ESTONIA 0x01
-# endif
-# ifndef SUBLANG_FAEROESE_FAROE_ISLANDS
-# define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01
-# endif
-# ifndef SUBLANG_FARSI_IRAN
-# define SUBLANG_FARSI_IRAN 0x01
-# endif
-# ifndef SUBLANG_FINNISH_FINLAND
-# define SUBLANG_FINNISH_FINLAND 0x01
-# endif
-# ifndef SUBLANG_FRENCH_LUXEMBOURG
-# define SUBLANG_FRENCH_LUXEMBOURG 0x05
-# endif
-# ifndef SUBLANG_FRENCH_MONACO
-# define SUBLANG_FRENCH_MONACO 0x06
-# endif
-# ifndef SUBLANG_FRENCH_WESTINDIES
-# define SUBLANG_FRENCH_WESTINDIES 0x07
-# endif
-# ifndef SUBLANG_FRENCH_REUNION
-# define SUBLANG_FRENCH_REUNION 0x08
-# endif
-# ifndef SUBLANG_FRENCH_CONGO
-# define SUBLANG_FRENCH_CONGO 0x09
-# endif
-# ifndef SUBLANG_FRENCH_SENEGAL
-# define SUBLANG_FRENCH_SENEGAL 0x0a
-# endif
-# ifndef SUBLANG_FRENCH_CAMEROON
-# define SUBLANG_FRENCH_CAMEROON 0x0b
-# endif
-# ifndef SUBLANG_FRENCH_COTEDIVOIRE
-# define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
-# endif
-# ifndef SUBLANG_FRENCH_MALI
-# define SUBLANG_FRENCH_MALI 0x0d
-# endif
-# ifndef SUBLANG_FRENCH_MOROCCO
-# define SUBLANG_FRENCH_MOROCCO 0x0e
-# endif
-# ifndef SUBLANG_FRENCH_HAITI
-# define SUBLANG_FRENCH_HAITI 0x0f
-# endif
-# ifndef SUBLANG_FRISIAN_NETHERLANDS
-# define SUBLANG_FRISIAN_NETHERLANDS 0x01
-# endif
-# ifndef SUBLANG_GALICIAN_SPAIN
-# define SUBLANG_GALICIAN_SPAIN 0x01
-# endif
-# ifndef SUBLANG_GEORGIAN_GEORGIA
-# define SUBLANG_GEORGIAN_GEORGIA 0x01
-# endif
-# ifndef SUBLANG_GERMAN_LUXEMBOURG
-# define SUBLANG_GERMAN_LUXEMBOURG 0x04
-# endif
-# ifndef SUBLANG_GERMAN_LIECHTENSTEIN
-# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
-# endif
-# ifndef SUBLANG_GREEK_GREECE
-# define SUBLANG_GREEK_GREECE 0x01
-# endif
-# ifndef SUBLANG_GREENLANDIC_GREENLAND
-# define SUBLANG_GREENLANDIC_GREENLAND 0x01
-# endif
-# ifndef SUBLANG_GUJARATI_INDIA
-# define SUBLANG_GUJARATI_INDIA 0x01
-# endif
-# ifndef SUBLANG_HAUSA_NIGERIA_LATIN
-# define SUBLANG_HAUSA_NIGERIA_LATIN 0x01
-# endif
-# ifndef SUBLANG_HEBREW_ISRAEL
-# define SUBLANG_HEBREW_ISRAEL 0x01
-# endif
-# ifndef SUBLANG_HINDI_INDIA
-# define SUBLANG_HINDI_INDIA 0x01
-# endif
-# ifndef SUBLANG_HUNGARIAN_HUNGARY
-# define SUBLANG_HUNGARIAN_HUNGARY 0x01
-# endif
-# ifndef SUBLANG_ICELANDIC_ICELAND
-# define SUBLANG_ICELANDIC_ICELAND 0x01
-# endif
-# ifndef SUBLANG_IGBO_NIGERIA
-# define SUBLANG_IGBO_NIGERIA 0x01
-# endif
-# ifndef SUBLANG_INDONESIAN_INDONESIA
-# define SUBLANG_INDONESIAN_INDONESIA 0x01
-# endif
-# ifndef SUBLANG_INUKTITUT_CANADA
-# define SUBLANG_INUKTITUT_CANADA 0x01
-# endif
-# undef SUBLANG_INUKTITUT_CANADA_LATIN
-# define SUBLANG_INUKTITUT_CANADA_LATIN 0x02
-# undef SUBLANG_IRISH_IRELAND
-# define SUBLANG_IRISH_IRELAND 0x02
-# ifndef SUBLANG_JAPANESE_JAPAN
-# define SUBLANG_JAPANESE_JAPAN 0x01
-# endif
-# ifndef SUBLANG_KANNADA_INDIA
-# define SUBLANG_KANNADA_INDIA 0x01
-# endif
-# ifndef SUBLANG_KASHMIRI_INDIA
-# define SUBLANG_KASHMIRI_INDIA 0x02
-# endif
-# ifndef SUBLANG_KAZAK_KAZAKHSTAN
-# define SUBLANG_KAZAK_KAZAKHSTAN 0x01
-# endif
-# ifndef SUBLANG_KICHE_GUATEMALA
-# define SUBLANG_KICHE_GUATEMALA 0x01
-# endif
-# ifndef SUBLANG_KINYARWANDA_RWANDA
-# define SUBLANG_KINYARWANDA_RWANDA 0x01
-# endif
-# ifndef SUBLANG_KONKANI_INDIA
-# define SUBLANG_KONKANI_INDIA 0x01
-# endif
-# ifndef SUBLANG_KYRGYZ_KYRGYZSTAN
-# define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01
-# endif
-# ifndef SUBLANG_LAO_LAOS
-# define SUBLANG_LAO_LAOS 0x01
-# endif
-# ifndef SUBLANG_LATVIAN_LATVIA
-# define SUBLANG_LATVIAN_LATVIA 0x01
-# endif
-# ifndef SUBLANG_LITHUANIAN_LITHUANIA
-# define SUBLANG_LITHUANIAN_LITHUANIA 0x01
-# endif
-# undef SUBLANG_LOWER_SORBIAN_GERMANY
-# define SUBLANG_LOWER_SORBIAN_GERMANY 0x02
-# ifndef SUBLANG_LUXEMBOURGISH_LUXEMBOURG
-# define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01
-# endif
-# ifndef SUBLANG_MACEDONIAN_MACEDONIA
-# define SUBLANG_MACEDONIAN_MACEDONIA 0x01
-# endif
-# ifndef SUBLANG_MALAY_MALAYSIA
-# define SUBLANG_MALAY_MALAYSIA 0x01
-# endif
-# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
-# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
-# endif
-# ifndef SUBLANG_MALAYALAM_INDIA
-# define SUBLANG_MALAYALAM_INDIA 0x01
-# endif
-# ifndef SUBLANG_MALTESE_MALTA
-# define SUBLANG_MALTESE_MALTA 0x01
-# endif
-# ifndef SUBLANG_MAORI_NEW_ZEALAND
-# define SUBLANG_MAORI_NEW_ZEALAND 0x01
-# endif
-# ifndef SUBLANG_MAPUDUNGUN_CHILE
-# define SUBLANG_MAPUDUNGUN_CHILE 0x01
-# endif
-# ifndef SUBLANG_MARATHI_INDIA
-# define SUBLANG_MARATHI_INDIA 0x01
-# endif
-# ifndef SUBLANG_MOHAWK_CANADA
-# define SUBLANG_MOHAWK_CANADA 0x01
-# endif
-# ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
-# define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01
-# endif
-# ifndef SUBLANG_MONGOLIAN_PRC
-# define SUBLANG_MONGOLIAN_PRC 0x02
-# endif
-# ifndef SUBLANG_NEPALI_NEPAL
-# define SUBLANG_NEPALI_NEPAL 0x01
-# endif
-# ifndef SUBLANG_NEPALI_INDIA
-# define SUBLANG_NEPALI_INDIA 0x02
-# endif
-# ifndef SUBLANG_OCCITAN_FRANCE
-# define SUBLANG_OCCITAN_FRANCE 0x01
-# endif
-# ifndef SUBLANG_ORIYA_INDIA
-# define SUBLANG_ORIYA_INDIA 0x01
-# endif
-# ifndef SUBLANG_PASHTO_AFGHANISTAN
-# define SUBLANG_PASHTO_AFGHANISTAN 0x01
-# endif
-# ifndef SUBLANG_POLISH_POLAND
-# define SUBLANG_POLISH_POLAND 0x01
-# endif
-# ifndef SUBLANG_PUNJABI_INDIA
-# define SUBLANG_PUNJABI_INDIA 0x01
-# endif
-# ifndef SUBLANG_PUNJABI_PAKISTAN
-# define SUBLANG_PUNJABI_PAKISTAN 0x02
-# endif
-# ifndef SUBLANG_QUECHUA_BOLIVIA
-# define SUBLANG_QUECHUA_BOLIVIA 0x01
-# endif
-# ifndef SUBLANG_QUECHUA_ECUADOR
-# define SUBLANG_QUECHUA_ECUADOR 0x02
-# endif
-# ifndef SUBLANG_QUECHUA_PERU
-# define SUBLANG_QUECHUA_PERU 0x03
-# endif
-# ifndef SUBLANG_ROMANIAN_ROMANIA
-# define SUBLANG_ROMANIAN_ROMANIA 0x01
-# endif
-# ifndef SUBLANG_ROMANIAN_MOLDOVA
-# define SUBLANG_ROMANIAN_MOLDOVA 0x02
-# endif
-# ifndef SUBLANG_ROMANSH_SWITZERLAND
-# define SUBLANG_ROMANSH_SWITZERLAND 0x01
-# endif
-# ifndef SUBLANG_RUSSIAN_RUSSIA
-# define SUBLANG_RUSSIAN_RUSSIA 0x01
-# endif
-# ifndef SUBLANG_RUSSIAN_MOLDAVIA
-# define SUBLANG_RUSSIAN_MOLDAVIA 0x02
-# endif
-# ifndef SUBLANG_SAMI_NORTHERN_NORWAY
-# define SUBLANG_SAMI_NORTHERN_NORWAY 0x01
-# endif
-# ifndef SUBLANG_SAMI_NORTHERN_SWEDEN
-# define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02
-# endif
-# ifndef SUBLANG_SAMI_NORTHERN_FINLAND
-# define SUBLANG_SAMI_NORTHERN_FINLAND 0x03
-# endif
-# ifndef SUBLANG_SAMI_LULE_NORWAY
-# define SUBLANG_SAMI_LULE_NORWAY 0x04
-# endif
-# ifndef SUBLANG_SAMI_LULE_SWEDEN
-# define SUBLANG_SAMI_LULE_SWEDEN 0x05
-# endif
-# ifndef SUBLANG_SAMI_SOUTHERN_NORWAY
-# define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06
-# endif
-# ifndef SUBLANG_SAMI_SOUTHERN_SWEDEN
-# define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07
-# endif
-# undef SUBLANG_SAMI_SKOLT_FINLAND
-# define SUBLANG_SAMI_SKOLT_FINLAND 0x08
-# undef SUBLANG_SAMI_INARI_FINLAND
-# define SUBLANG_SAMI_INARI_FINLAND 0x09
-# ifndef SUBLANG_SANSKRIT_INDIA
-# define SUBLANG_SANSKRIT_INDIA 0x01
-# endif
-# ifndef SUBLANG_SERBIAN_LATIN
-# define SUBLANG_SERBIAN_LATIN 0x02
-# endif
-# ifndef SUBLANG_SERBIAN_CYRILLIC
-# define SUBLANG_SERBIAN_CYRILLIC 0x03
-# endif
-# ifndef SUBLANG_SINDHI_INDIA
-# define SUBLANG_SINDHI_INDIA 0x01
-# endif
-# undef SUBLANG_SINDHI_PAKISTAN
-# define SUBLANG_SINDHI_PAKISTAN 0x02
-# ifndef SUBLANG_SINDHI_AFGHANISTAN
-# define SUBLANG_SINDHI_AFGHANISTAN 0x02
-# endif
-# ifndef SUBLANG_SINHALESE_SRI_LANKA
-# define SUBLANG_SINHALESE_SRI_LANKA 0x01
-# endif
-# ifndef SUBLANG_SLOVAK_SLOVAKIA
-# define SUBLANG_SLOVAK_SLOVAKIA 0x01
-# endif
-# ifndef SUBLANG_SLOVENIAN_SLOVENIA
-# define SUBLANG_SLOVENIAN_SLOVENIA 0x01
-# endif
-# ifndef SUBLANG_SOTHO_SOUTH_AFRICA
-# define SUBLANG_SOTHO_SOUTH_AFRICA 0x01
-# endif
-# ifndef SUBLANG_SPANISH_GUATEMALA
-# define SUBLANG_SPANISH_GUATEMALA 0x04
-# endif
-# ifndef SUBLANG_SPANISH_COSTA_RICA
-# define SUBLANG_SPANISH_COSTA_RICA 0x05
-# endif
-# ifndef SUBLANG_SPANISH_PANAMA
-# define SUBLANG_SPANISH_PANAMA 0x06
-# endif
-# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
-# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
-# endif
-# ifndef SUBLANG_SPANISH_VENEZUELA
-# define SUBLANG_SPANISH_VENEZUELA 0x08
-# endif
-# ifndef SUBLANG_SPANISH_COLOMBIA
-# define SUBLANG_SPANISH_COLOMBIA 0x09
-# endif
-# ifndef SUBLANG_SPANISH_PERU
-# define SUBLANG_SPANISH_PERU 0x0a
-# endif
-# ifndef SUBLANG_SPANISH_ARGENTINA
-# define SUBLANG_SPANISH_ARGENTINA 0x0b
-# endif
-# ifndef SUBLANG_SPANISH_ECUADOR
-# define SUBLANG_SPANISH_ECUADOR 0x0c
-# endif
-# ifndef SUBLANG_SPANISH_CHILE
-# define SUBLANG_SPANISH_CHILE 0x0d
-# endif
-# ifndef SUBLANG_SPANISH_URUGUAY
-# define SUBLANG_SPANISH_URUGUAY 0x0e
-# endif
-# ifndef SUBLANG_SPANISH_PARAGUAY
-# define SUBLANG_SPANISH_PARAGUAY 0x0f
-# endif
-# ifndef SUBLANG_SPANISH_BOLIVIA
-# define SUBLANG_SPANISH_BOLIVIA 0x10
-# endif
-# ifndef SUBLANG_SPANISH_EL_SALVADOR
-# define SUBLANG_SPANISH_EL_SALVADOR 0x11
-# endif
-# ifndef SUBLANG_SPANISH_HONDURAS
-# define SUBLANG_SPANISH_HONDURAS 0x12
-# endif
-# ifndef SUBLANG_SPANISH_NICARAGUA
-# define SUBLANG_SPANISH_NICARAGUA 0x13
-# endif
-# ifndef SUBLANG_SPANISH_PUERTO_RICO
-# define SUBLANG_SPANISH_PUERTO_RICO 0x14
-# endif
-# ifndef SUBLANG_SPANISH_US
-# define SUBLANG_SPANISH_US 0x15
-# endif
-# ifndef SUBLANG_SWAHILI_KENYA
-# define SUBLANG_SWAHILI_KENYA 0x01
-# endif
-# ifndef SUBLANG_SWEDISH_SWEDEN
-# define SUBLANG_SWEDISH_SWEDEN 0x01
-# endif
-# ifndef SUBLANG_SWEDISH_FINLAND
-# define SUBLANG_SWEDISH_FINLAND 0x02
-# endif
-# ifndef SUBLANG_SYRIAC_SYRIA
-# define SUBLANG_SYRIAC_SYRIA 0x01
-# endif
-# ifndef SUBLANG_TAGALOG_PHILIPPINES
-# define SUBLANG_TAGALOG_PHILIPPINES 0x01
-# endif
-# ifndef SUBLANG_TAJIK_TAJIKISTAN
-# define SUBLANG_TAJIK_TAJIKISTAN 0x01
-# endif
-# ifndef SUBLANG_TAMAZIGHT_ARABIC
-# define SUBLANG_TAMAZIGHT_ARABIC 0x01
-# endif
-# ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN
-# define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02
-# endif
-# ifndef SUBLANG_TAMIL_INDIA
-# define SUBLANG_TAMIL_INDIA 0x01
-# endif
-# ifndef SUBLANG_TATAR_RUSSIA
-# define SUBLANG_TATAR_RUSSIA 0x01
-# endif
-# ifndef SUBLANG_TELUGU_INDIA
-# define SUBLANG_TELUGU_INDIA 0x01
-# endif
-# ifndef SUBLANG_THAI_THAILAND
-# define SUBLANG_THAI_THAILAND 0x01
-# endif
-# ifndef SUBLANG_TIBETAN_PRC
-# define SUBLANG_TIBETAN_PRC 0x01
-# endif
-# undef SUBLANG_TIBETAN_BHUTAN
-# define SUBLANG_TIBETAN_BHUTAN 0x02
-# ifndef SUBLANG_TIGRINYA_ETHIOPIA
-# define SUBLANG_TIGRINYA_ETHIOPIA 0x01
-# endif
-# ifndef SUBLANG_TIGRINYA_ERITREA
-# define SUBLANG_TIGRINYA_ERITREA 0x02
-# endif
-# ifndef SUBLANG_TSWANA_SOUTH_AFRICA
-# define SUBLANG_TSWANA_SOUTH_AFRICA 0x01
-# endif
-# ifndef SUBLANG_TURKISH_TURKEY
-# define SUBLANG_TURKISH_TURKEY 0x01
-# endif
-# ifndef SUBLANG_TURKMEN_TURKMENISTAN
-# define SUBLANG_TURKMEN_TURKMENISTAN 0x01
-# endif
-# ifndef SUBLANG_UIGHUR_PRC
-# define SUBLANG_UIGHUR_PRC 0x01
-# endif
-# ifndef SUBLANG_UKRAINIAN_UKRAINE
-# define SUBLANG_UKRAINIAN_UKRAINE 0x01
-# endif
-# ifndef SUBLANG_UPPER_SORBIAN_GERMANY
-# define SUBLANG_UPPER_SORBIAN_GERMANY 0x01
-# endif
-# ifndef SUBLANG_URDU_PAKISTAN
-# define SUBLANG_URDU_PAKISTAN 0x01
-# endif
-# ifndef SUBLANG_URDU_INDIA
-# define SUBLANG_URDU_INDIA 0x02
-# endif
-# ifndef SUBLANG_UZBEK_LATIN
-# define SUBLANG_UZBEK_LATIN 0x01
-# endif
-# ifndef SUBLANG_UZBEK_CYRILLIC
-# define SUBLANG_UZBEK_CYRILLIC 0x02
-# endif
-# ifndef SUBLANG_VIETNAMESE_VIETNAM
-# define SUBLANG_VIETNAMESE_VIETNAM 0x01
-# endif
-# ifndef SUBLANG_WELSH_UNITED_KINGDOM
-# define SUBLANG_WELSH_UNITED_KINGDOM 0x01
-# endif
-# ifndef SUBLANG_WOLOF_SENEGAL
-# define SUBLANG_WOLOF_SENEGAL 0x01
-# endif
-# ifndef SUBLANG_XHOSA_SOUTH_AFRICA
-# define SUBLANG_XHOSA_SOUTH_AFRICA 0x01
-# endif
-# ifndef SUBLANG_YAKUT_RUSSIA
-# define SUBLANG_YAKUT_RUSSIA 0x01
-# endif
-# ifndef SUBLANG_YI_PRC
-# define SUBLANG_YI_PRC 0x01
-# endif
-# ifndef SUBLANG_YORUBA_NIGERIA
-# define SUBLANG_YORUBA_NIGERIA 0x01
-# endif
-# ifndef SUBLANG_ZULU_SOUTH_AFRICA
-# define SUBLANG_ZULU_SOUTH_AFRICA 0x01
-# endif
-/* GetLocaleInfoA operations. */
-# ifndef LOCALE_SNAME
-# define LOCALE_SNAME 0x5c
-# endif
-# ifndef LOCALE_NAME_MAX_LENGTH
-# define LOCALE_NAME_MAX_LENGTH 85
-# endif
-/* Don't assume that UNICODE is not defined. */
-# undef GetLocaleInfo
-# define GetLocaleInfo GetLocaleInfoA
-# undef EnumSystemLocales
-# define EnumSystemLocales EnumSystemLocalesA
-#endif
-
-/* We want to use the system's setlocale() function here, not the gnulib
- override. */
-#undef setlocale
-
-
-#if HAVE_CFPREFERENCESCOPYAPPVALUE
-/* Mac OS X 10.4 or newer */
-
-/* Canonicalize a Mac OS X locale name to a Unix locale name.
- NAME is a sufficiently large buffer.
- On input, it contains the Mac OS X locale name.
- On output, it contains the Unix locale name. */
-# if !defined IN_LIBINTL
-static
-# endif
-void
-gl_locale_name_canonicalize (char *name)
-{
- /* This conversion is based on a posting by
- Deborah GoldSmith <goldsmit@apple.com> on 2005-03-08,
- https://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */
-
- /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and
- ISO 3166) names. Prior to Mac OS X 10.3, there is no API for doing this.
- Therefore we do it ourselves, using a table based on the results of the
- Mac OS X 10.3.8 function
- CFLocaleCreateCanonicalLocaleIdentifierFromString(). */
- typedef struct { const char legacy[21+1]; const char unixy[5+1]; }
- legacy_entry;
- static const legacy_entry legacy_table[] = {
- { "Afrikaans", "af" },
- { "Albanian", "sq" },
- { "Amharic", "am" },
- { "Arabic", "ar" },
- { "Armenian", "hy" },
- { "Assamese", "as" },
- { "Aymara", "ay" },
- { "Azerbaijani", "az" },
- { "Basque", "eu" },
- { "Belarusian", "be" },
- { "Belorussian", "be" },
- { "Bengali", "bn" },
- { "Brazilian Portugese", "pt_BR" },
- { "Brazilian Portuguese", "pt_BR" },
- { "Breton", "br" },
- { "Bulgarian", "bg" },
- { "Burmese", "my" },
- { "Byelorussian", "be" },
- { "Catalan", "ca" },
- { "Chewa", "ny" },
- { "Chichewa", "ny" },
- { "Chinese", "zh" },
- { "Chinese, Simplified", "zh_CN" },
- { "Chinese, Traditional", "zh_TW" },
- { "Chinese, Tradtional", "zh_TW" },
- { "Croatian", "hr" },
- { "Czech", "cs" },
- { "Danish", "da" },
- { "Dutch", "nl" },
- { "Dzongkha", "dz" },
- { "English", "en" },
- { "Esperanto", "eo" },
- { "Estonian", "et" },
- { "Faroese", "fo" },
- { "Farsi", "fa" },
- { "Finnish", "fi" },
- { "Flemish", "nl_BE" },
- { "French", "fr" },
- { "Galician", "gl" },
- { "Gallegan", "gl" },
- { "Georgian", "ka" },
- { "German", "de" },
- { "Greek", "el" },
- { "Greenlandic", "kl" },
- { "Guarani", "gn" },
- { "Gujarati", "gu" },
- { "Hawaiian", "haw" }, /* Yes, "haw", not "cpe". */
- { "Hebrew", "he" },
- { "Hindi", "hi" },
- { "Hungarian", "hu" },
- { "Icelandic", "is" },
- { "Indonesian", "id" },
- { "Inuktitut", "iu" },
- { "Irish", "ga" },
- { "Italian", "it" },
- { "Japanese", "ja" },
- { "Javanese", "jv" },
- { "Kalaallisut", "kl" },
- { "Kannada", "kn" },
- { "Kashmiri", "ks" },
- { "Kazakh", "kk" },
- { "Khmer", "km" },
- { "Kinyarwanda", "rw" },
- { "Kirghiz", "ky" },
- { "Korean", "ko" },
- { "Kurdish", "ku" },
- { "Latin", "la" },
- { "Latvian", "lv" },
- { "Lithuanian", "lt" },
- { "Macedonian", "mk" },
- { "Malagasy", "mg" },
- { "Malay", "ms" },
- { "Malayalam", "ml" },
- { "Maltese", "mt" },
- { "Manx", "gv" },
- { "Marathi", "mr" },
- { "Moldavian", "mo" },
- { "Mongolian", "mn" },
- { "Nepali", "ne" },
- { "Norwegian", "nb" }, /* Yes, "nb", not the obsolete "no". */
- { "Nyanja", "ny" },
- { "Nynorsk", "nn" },
- { "Oriya", "or" },
- { "Oromo", "om" },
- { "Panjabi", "pa" },
- { "Pashto", "ps" },
- { "Persian", "fa" },
- { "Polish", "pl" },
- { "Portuguese", "pt" },
- { "Portuguese, Brazilian", "pt_BR" },
- { "Punjabi", "pa" },
- { "Pushto", "ps" },
- { "Quechua", "qu" },
- { "Romanian", "ro" },
- { "Ruanda", "rw" },
- { "Rundi", "rn" },
- { "Russian", "ru" },
- { "Sami", "se_NO" }, /* Not just "se". */
- { "Sanskrit", "sa" },
- { "Scottish", "gd" },
- { "Serbian", "sr" },
- { "Simplified Chinese", "zh_CN" },
- { "Sindhi", "sd" },
- { "Sinhalese", "si" },
- { "Slovak", "sk" },
- { "Slovenian", "sl" },
- { "Somali", "so" },
- { "Spanish", "es" },
- { "Sundanese", "su" },
- { "Swahili", "sw" },
- { "Swedish", "sv" },
- { "Tagalog", "tl" },
- { "Tajik", "tg" },
- { "Tajiki", "tg" },
- { "Tamil", "ta" },
- { "Tatar", "tt" },
- { "Telugu", "te" },
- { "Thai", "th" },
- { "Tibetan", "bo" },
- { "Tigrinya", "ti" },
- { "Tongan", "to" },
- { "Traditional Chinese", "zh_TW" },
- { "Turkish", "tr" },
- { "Turkmen", "tk" },
- { "Uighur", "ug" },
- { "Ukrainian", "uk" },
- { "Urdu", "ur" },
- { "Uzbek", "uz" },
- { "Vietnamese", "vi" },
- { "Welsh", "cy" },
- { "Yiddish", "yi" }
- };
-
- /* Convert new-style locale names with language tags (ISO 639 and ISO 15924)
- to Unix (ISO 639 and ISO 3166) names. */
- typedef struct { const char langtag[7+1]; const char unixy[12+1]; }
- langtag_entry;
- static const langtag_entry langtag_table[] = {
- /* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn".
- The default script for az on Unix is Latin. */
- { "az-Latn", "az" },
- /* Mac OS X has "bs-Cyrl", "bs-Latn".
- The default script for bs on Unix is Latin. */
- { "bs-Latn", "bs" },
- /* Mac OS X has "ga-dots". Does not yet exist on Unix. */
- { "ga-dots", "ga" },
- /* Mac OS X has "kk-Cyrl".
- The default script for kk on Unix is Cyrillic. */
- { "kk-Cyrl", "kk" },
- /* Mac OS X has "mn-Cyrl", "mn-Mong".
- The default script for mn on Unix is Cyrillic. */
- { "mn-Cyrl", "mn" },
- /* Mac OS X has "ms-Arab", "ms-Latn".
- The default script for ms on Unix is Latin. */
- { "ms-Latn", "ms" },
- /* Mac OS X has "pa-Arab", "pa-Guru".
- Country codes are used to distinguish these on Unix. */
- { "pa-Arab", "pa_PK" },
- { "pa-Guru", "pa_IN" },
- /* Mac OS X has "shi-Latn", "shi-Tfng". Does not yet exist on Unix. */
- /* Mac OS X has "sr-Cyrl", "sr-Latn".
- The default script for sr on Unix is Cyrillic. */
- { "sr-Cyrl", "sr" },
- /* Mac OS X has "tg-Cyrl".
- The default script for tg on Unix is Cyrillic. */
- { "tg-Cyrl", "tg" },
- /* Mac OS X has "tk-Cyrl".
- The default script for tk on Unix is Cyrillic. */
- { "tk-Cyrl", "tk" },
- /* Mac OS X has "tt-Cyrl".
- The default script for tt on Unix is Cyrillic. */
- { "tt-Cyrl", "tt" },
- /* Mac OS X has "uz-Arab", "uz-Cyrl", "uz-Latn".
- The default script for uz on Unix is Latin. */
- { "uz-Latn", "uz" },
- /* Mac OS X has "vai-Latn", "vai-Vaii". Does not yet exist on Unix. */
- /* Mac OS X has "yue-Hans", "yue-Hant".
- The default script for yue on Unix is Simplified Han. */
- { "yue-Hans", "yue" },
- /* Mac OS X has "zh-Hans", "zh-Hant".
- Country codes are used to distinguish these on Unix. */
- { "zh-Hans", "zh_CN" },
- { "zh-Hant", "zh_TW" }
- };
-
- /* Convert script names (ISO 15924) to Unix conventions.
- See https://www.unicode.org/iso15924/iso15924-codes.html */
- typedef struct { const char script[4+1]; const char unixy[9+1]; }
- script_entry;
- static const script_entry script_table[] = {
- { "Arab", "arabic" },
- { "Cyrl", "cyrillic" },
- { "Latn", "latin" },
- { "Mong", "mongolian" }
- };
-
- /* Step 1: Convert using legacy_table. */
- if (name[0] >= 'A' && name[0] <= 'Z')
- {
- unsigned int i1, i2;
- i1 = 0;
- i2 = sizeof (legacy_table) / sizeof (legacy_entry);
- while (i2 - i1 > 1)
- {
- /* At this point we know that if name occurs in legacy_table,
- its index must be >= i1 and < i2. */
- unsigned int i = (i1 + i2) >> 1;
- const legacy_entry *p = &legacy_table[i];
- if (strcmp (name, p->legacy) < 0)
- i2 = i;
- else
- i1 = i;
- }
- if (strcmp (name, legacy_table[i1].legacy) == 0)
- {
- strcpy (name, legacy_table[i1].unixy);
- return;
- }
- }
-
- /* Step 2: Convert using langtag_table and script_table. */
- if (strlen (name) == 7 && name[2] == '-')
- {
- unsigned int i1, i2;
- i1 = 0;
- i2 = sizeof (langtag_table) / sizeof (langtag_entry);
- while (i2 - i1 > 1)
- {
- /* At this point we know that if name occurs in langtag_table,
- its index must be >= i1 and < i2. */
- unsigned int i = (i1 + i2) >> 1;
- const langtag_entry *p = &langtag_table[i];
- if (strcmp (name, p->langtag) < 0)
- i2 = i;
- else
- i1 = i;
- }
- if (strcmp (name, langtag_table[i1].langtag) == 0)
- {
- strcpy (name, langtag_table[i1].unixy);
- return;
- }
-
- i1 = 0;
- i2 = sizeof (script_table) / sizeof (script_entry);
- while (i2 - i1 > 1)
- {
- /* At this point we know that if (name + 3) occurs in script_table,
- its index must be >= i1 and < i2. */
- unsigned int i = (i1 + i2) >> 1;
- const script_entry *p = &script_table[i];
- if (strcmp (name + 3, p->script) < 0)
- i2 = i;
- else
- i1 = i;
- }
- if (strcmp (name + 3, script_table[i1].script) == 0)
- {
- name[2] = '@';
- strcpy (name + 3, script_table[i1].unixy);
- return;
- }
- }
-
- /* Step 3: Convert new-style dash to Unix underscore. */
- {
- char *p;
- for (p = name; *p != '\0'; p++)
- if (*p == '-')
- *p = '_';
- }
-}
-
-#endif
-
-
-#if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
-
-/* Canonicalize a Windows native locale name to a Unix locale name.
- NAME is a sufficiently large buffer.
- On input, it contains the Windows locale name.
- On output, it contains the Unix locale name. */
-# if !defined IN_LIBINTL
-static
-# endif
-void
-gl_locale_name_canonicalize (char *name)
-{
- /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and
- "zh-Hant". */
- char *p;
-
- for (p = name; *p != '\0'; p++)
- if (*p == '-')
- {
- *p = '_';
- p++;
- for (; *p != '\0'; p++)
- {
- if (*p >= 'a' && *p <= 'z')
- *p += 'A' - 'a';
- if (*p == '-')
- {
- *p = '\0';
- return;
- }
- }
- return;
- }
-}
-
-# if !defined IN_LIBINTL
-static
-# endif
-const char *
-gl_locale_name_from_win32_LANGID (LANGID langid)
-{
- /* Activate the new code only when the GETTEXT_MUI environment variable is
- set, for the time being, since the new code is not well tested. */
- if (getenv ("GETTEXT_MUI") != NULL)
- {
- static char namebuf[256];
-
- /* Query the system's notion of locale name.
- On Windows95/98/ME, GetLocaleInfoA returns some incorrect results.
- But we don't need to support systems that are so old. */
- if (GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT), LOCALE_SNAME,
- namebuf, sizeof (namebuf) - 1))
- {
- /* Convert it to a Unix locale name. */
- gl_locale_name_canonicalize (namebuf);
- return namebuf;
- }
- }
- /* Internet Explorer has an LCID to RFC3066 name mapping stored in
- HKEY_CLASSES_ROOT\Mime\Database\Rfc1766. But we better don't use that
- since IE's i18n subsystem is known to be inconsistent with the native
- Windows base (e.g. they have different character conversion facilities
- that produce different results). */
- /* Use our own table. */
- {
- int primary, sub;
-
- /* Split into language and territory part. */
- primary = PRIMARYLANGID (langid);
- sub = SUBLANGID (langid);
-
- /* Dispatch on language.
- See also https://www.unicode.org/unicode/onlinedat/languages.html .
- For details about languages, see https://www.ethnologue.com/ . */
- switch (primary)
- {
- case LANG_AFRIKAANS:
- switch (sub)
- {
- case SUBLANG_AFRIKAANS_SOUTH_AFRICA: return "af_ZA";
- }
- return "af";
- case LANG_ALBANIAN:
- switch (sub)
- {
- case SUBLANG_ALBANIAN_ALBANIA: return "sq_AL";
- }
- return "sq";
- case LANG_ALSATIAN:
- switch (sub)
- {
- case SUBLANG_ALSATIAN_FRANCE: return "gsw_FR";
- }
- return "gsw";
- case LANG_AMHARIC:
- switch (sub)
- {
- case SUBLANG_AMHARIC_ETHIOPIA: return "am_ET";
- }
- return "am";
- case LANG_ARABIC:
- switch (sub)
- {
- case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
- case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
- case SUBLANG_ARABIC_EGYPT: return "ar_EG";
- case SUBLANG_ARABIC_LIBYA: return "ar_LY";
- case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
- case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
- case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
- case SUBLANG_ARABIC_OMAN: return "ar_OM";
- case SUBLANG_ARABIC_YEMEN: return "ar_YE";
- case SUBLANG_ARABIC_SYRIA: return "ar_SY";
- case SUBLANG_ARABIC_JORDAN: return "ar_JO";
- case SUBLANG_ARABIC_LEBANON: return "ar_LB";
- case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
- case SUBLANG_ARABIC_UAE: return "ar_AE";
- case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
- case SUBLANG_ARABIC_QATAR: return "ar_QA";
- }
- return "ar";
- case LANG_ARMENIAN:
- switch (sub)
- {
- case SUBLANG_ARMENIAN_ARMENIA: return "hy_AM";
- }
- return "hy";
- case LANG_ASSAMESE:
- switch (sub)
- {
- case SUBLANG_ASSAMESE_INDIA: return "as_IN";
- }
- return "as";
- case LANG_AZERI:
- switch (sub)
- {
- /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
- case 0x1e: return "az@latin";
- case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
- case 0x1d: return "az@cyrillic";
- case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
- }
- return "az";
- case LANG_BASHKIR:
- switch (sub)
- {
- case SUBLANG_BASHKIR_RUSSIA: return "ba_RU";
- }
- return "ba";
- case LANG_BASQUE:
- switch (sub)
- {
- case SUBLANG_BASQUE_BASQUE: return "eu_ES";
- }
- return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
- case LANG_BELARUSIAN:
- switch (sub)
- {
- case SUBLANG_BELARUSIAN_BELARUS: return "be_BY";
- }
- return "be";
- case LANG_BENGALI:
- switch (sub)
- {
- case SUBLANG_BENGALI_INDIA: return "bn_IN";
- case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
- }
- return "bn";
- case LANG_BRETON:
- switch (sub)
- {
- case SUBLANG_BRETON_FRANCE: return "br_FR";
- }
- return "br";
- case LANG_BULGARIAN:
- switch (sub)
- {
- case SUBLANG_BULGARIAN_BULGARIA: return "bg_BG";
- }
- return "bg";
- case LANG_BURMESE:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "my_MM";
- }
- return "my";
- case LANG_CAMBODIAN:
- switch (sub)
- {
- case SUBLANG_CAMBODIAN_CAMBODIA: return "km_KH";
- }
- return "km";
- case LANG_CATALAN:
- switch (sub)
- {
- case SUBLANG_CATALAN_SPAIN: return "ca_ES";
- }
- return "ca";
- case LANG_CHEROKEE:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "chr_US";
- }
- return "chr";
- case LANG_CHINESE:
- switch (sub)
- {
- case SUBLANG_CHINESE_TRADITIONAL: case 0x1f: return "zh_TW";
- case SUBLANG_CHINESE_SIMPLIFIED: case 0x00: return "zh_CN";
- case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; /* traditional */
- case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; /* simplified */
- case SUBLANG_CHINESE_MACAU: return "zh_MO"; /* traditional */
- }
- return "zh";
- case LANG_CORSICAN:
- switch (sub)
- {
- case SUBLANG_CORSICAN_FRANCE: return "co_FR";
- }
- return "co";
- case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN
- * What used to be called Serbo-Croatian
- * should really now be two separate
- * languages because of political reasons.
- * (Says tml, who knows nothing about Serbian
- * or Croatian.)
- * (I can feel those flames coming already.)
- */
- switch (sub)
- {
- /* Croatian */
- case 0x00: return "hr";
- case SUBLANG_CROATIAN_CROATIA: return "hr_HR";
- case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: return "hr_BA";
- /* Serbian */
- case 0x1f: return "sr";
- case 0x1c: return "sr"; /* latin */
- case SUBLANG_SERBIAN_LATIN: return "sr_CS"; /* latin */
- case 0x09: return "sr_RS"; /* latin */
- case 0x0b: return "sr_ME"; /* latin */
- case 0x06: return "sr_BA"; /* latin */
- case 0x1b: return "sr@cyrillic";
- case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
- case 0x0a: return "sr_RS@cyrillic";
- case 0x0c: return "sr_ME@cyrillic";
- case 0x07: return "sr_BA@cyrillic";
- /* Bosnian */
- case 0x1e: return "bs";
- case 0x1a: return "bs"; /* latin */
- case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: return "bs_BA"; /* latin */
- case 0x19: return "bs@cyrillic";
- case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: return "bs_BA@cyrillic";
- }
- return "hr";
- case LANG_CZECH:
- switch (sub)
- {
- case SUBLANG_CZECH_CZECH_REPUBLIC: return "cs_CZ";
- }
- return "cs";
- case LANG_DANISH:
- switch (sub)
- {
- case SUBLANG_DANISH_DENMARK: return "da_DK";
- }
- return "da";
- case LANG_DARI:
- /* FIXME: Adjust this when such locales appear on Unix. */
- switch (sub)
- {
- case SUBLANG_DARI_AFGHANISTAN: return "prs_AF";
- }
- return "prs";
- case LANG_DIVEHI:
- switch (sub)
- {
- case SUBLANG_DIVEHI_MALDIVES: return "dv_MV";
- }
- return "dv";
- case LANG_DUTCH:
- switch (sub)
- {
- case SUBLANG_DUTCH: return "nl_NL";
- case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
- case SUBLANG_DUTCH_SURINAM: return "nl_SR";
- }
- return "nl";
- case LANG_EDO:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "bin_NG";
- }
- return "bin";
- case LANG_ENGLISH:
- switch (sub)
- {
- /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
- * English was the language spoken in England.
- * Oh well.
- */
- case SUBLANG_ENGLISH_US: return "en_US";
- case SUBLANG_ENGLISH_UK: return "en_GB";
- case SUBLANG_ENGLISH_AUS: return "en_AU";
- case SUBLANG_ENGLISH_CAN: return "en_CA";
- case SUBLANG_ENGLISH_NZ: return "en_NZ";
- case SUBLANG_ENGLISH_EIRE: return "en_IE";
- case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
- case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
- case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
- case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
- case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
- case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
- case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
- case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
- case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
- case SUBLANG_ENGLISH_INDIA: return "en_IN";
- case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
- case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
- }
- return "en";
- case LANG_ESTONIAN:
- switch (sub)
- {
- case SUBLANG_ESTONIAN_ESTONIA: return "et_EE";
- }
- return "et";
- case LANG_FAEROESE:
- switch (sub)
- {
- case SUBLANG_FAEROESE_FAROE_ISLANDS: return "fo_FO";
- }
- return "fo";
- case LANG_FARSI:
- switch (sub)
- {
- case SUBLANG_FARSI_IRAN: return "fa_IR";
- }
- return "fa";
- case LANG_FINNISH:
- switch (sub)
- {
- case SUBLANG_FINNISH_FINLAND: return "fi_FI";
- }
- return "fi";
- case LANG_FRENCH:
- switch (sub)
- {
- case SUBLANG_FRENCH: return "fr_FR";
- case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
- case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
- case SUBLANG_FRENCH_SWISS: return "fr_CH";
- case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
- case SUBLANG_FRENCH_MONACO: return "fr_MC";
- case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
- case SUBLANG_FRENCH_REUNION: return "fr_RE";
- case SUBLANG_FRENCH_CONGO: return "fr_CG";
- case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
- case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
- case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
- case SUBLANG_FRENCH_MALI: return "fr_ML";
- case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
- case SUBLANG_FRENCH_HAITI: return "fr_HT";
- }
- return "fr";
- case LANG_FRISIAN:
- switch (sub)
- {
- case SUBLANG_FRISIAN_NETHERLANDS: return "fy_NL";
- }
- return "fy";
- case LANG_FULFULDE:
- /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "ff_NG";
- }
- return "ff";
- case LANG_GAELIC:
- switch (sub)
- {
- case 0x01: /* SCOTTISH */
- /* old, superseded by LANG_SCOTTISH_GAELIC */
- return "gd_GB";
- case SUBLANG_IRISH_IRELAND: return "ga_IE";
- }
- return "ga";
- case LANG_GALICIAN:
- switch (sub)
- {
- case SUBLANG_GALICIAN_SPAIN: return "gl_ES";
- }
- return "gl";
- case LANG_GEORGIAN:
- switch (sub)
- {
- case SUBLANG_GEORGIAN_GEORGIA: return "ka_GE";
- }
- return "ka";
- case LANG_GERMAN:
- switch (sub)
- {
- case SUBLANG_GERMAN: return "de_DE";
- case SUBLANG_GERMAN_SWISS: return "de_CH";
- case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
- case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
- case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
- }
- return "de";
- case LANG_GREEK:
- switch (sub)
- {
- case SUBLANG_GREEK_GREECE: return "el_GR";
- }
- return "el";
- case LANG_GREENLANDIC:
- switch (sub)
- {
- case SUBLANG_GREENLANDIC_GREENLAND: return "kl_GL";
- }
- return "kl";
- case LANG_GUARANI:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "gn_PY";
- }
- return "gn";
- case LANG_GUJARATI:
- switch (sub)
- {
- case SUBLANG_GUJARATI_INDIA: return "gu_IN";
- }
- return "gu";
- case LANG_HAUSA:
- switch (sub)
- {
- case 0x1f: return "ha";
- case SUBLANG_HAUSA_NIGERIA_LATIN: return "ha_NG";
- }
- return "ha";
- case LANG_HAWAIIAN:
- /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
- or Hawaii Creole English ("cpe_US", 600000 speakers)? */
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "cpe_US";
- }
- return "cpe";
- case LANG_HEBREW:
- switch (sub)
- {
- case SUBLANG_HEBREW_ISRAEL: return "he_IL";
- }
- return "he";
- case LANG_HINDI:
- switch (sub)
- {
- case SUBLANG_HINDI_INDIA: return "hi_IN";
- }
- return "hi";
- case LANG_HUNGARIAN:
- switch (sub)
- {
- case SUBLANG_HUNGARIAN_HUNGARY: return "hu_HU";
- }
- return "hu";
- case LANG_IBIBIO:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "nic_NG";
- }
- return "nic";
- case LANG_ICELANDIC:
- switch (sub)
- {
- case SUBLANG_ICELANDIC_ICELAND: return "is_IS";
- }
- return "is";
- case LANG_IGBO:
- switch (sub)
- {
- case SUBLANG_IGBO_NIGERIA: return "ig_NG";
- }
- return "ig";
- case LANG_INDONESIAN:
- switch (sub)
- {
- case SUBLANG_INDONESIAN_INDONESIA: return "id_ID";
- }
- return "id";
- case LANG_INUKTITUT:
- switch (sub)
- {
- case 0x1e: return "iu"; /* syllabic */
- case SUBLANG_INUKTITUT_CANADA: return "iu_CA"; /* syllabic */
- case 0x1f: return "iu@latin";
- case SUBLANG_INUKTITUT_CANADA_LATIN: return "iu_CA@latin";
- }
- return "iu";
- case LANG_ITALIAN:
- switch (sub)
- {
- case SUBLANG_ITALIAN: return "it_IT";
- case SUBLANG_ITALIAN_SWISS: return "it_CH";
- }
- return "it";
- case LANG_JAPANESE:
- switch (sub)
- {
- case SUBLANG_JAPANESE_JAPAN: return "ja_JP";
- }
- return "ja";
- case LANG_KANNADA:
- switch (sub)
- {
- case SUBLANG_KANNADA_INDIA: return "kn_IN";
- }
- return "kn";
- case LANG_KANURI:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "kr_NG";
- }
- return "kr";
- case LANG_KASHMIRI:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "ks_PK";
- case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
- }
- return "ks";
- case LANG_KAZAK:
- switch (sub)
- {
- case SUBLANG_KAZAK_KAZAKHSTAN: return "kk_KZ";
- }
- return "kk";
- case LANG_KICHE:
- /* FIXME: Adjust this when such locales appear on Unix. */
- switch (sub)
- {
- case SUBLANG_KICHE_GUATEMALA: return "qut_GT";
- }
- return "qut";
- case LANG_KINYARWANDA:
- switch (sub)
- {
- case SUBLANG_KINYARWANDA_RWANDA: return "rw_RW";
- }
- return "rw";
- case LANG_KONKANI:
- /* FIXME: Adjust this when such locales appear on Unix. */
- switch (sub)
- {
- case SUBLANG_KONKANI_INDIA: return "kok_IN";
- }
- return "kok";
- case LANG_KOREAN:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "ko_KR";
- }
- return "ko";
- case LANG_KYRGYZ:
- switch (sub)
- {
- case SUBLANG_KYRGYZ_KYRGYZSTAN: return "ky_KG";
- }
- return "ky";
- case LANG_LAO:
- switch (sub)
- {
- case SUBLANG_LAO_LAOS: return "lo_LA";
- }
- return "lo";
- case LANG_LATIN:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "la_VA";
- }
- return "la";
- case LANG_LATVIAN:
- switch (sub)
- {
- case SUBLANG_LATVIAN_LATVIA: return "lv_LV";
- }
- return "lv";
- case LANG_LITHUANIAN:
- switch (sub)
- {
- case SUBLANG_LITHUANIAN_LITHUANIA: return "lt_LT";
- }
- return "lt";
- case LANG_LUXEMBOURGISH:
- switch (sub)
- {
- case SUBLANG_LUXEMBOURGISH_LUXEMBOURG: return "lb_LU";
- }
- return "lb";
- case LANG_MACEDONIAN:
- switch (sub)
- {
- case SUBLANG_MACEDONIAN_MACEDONIA: return "mk_MK";
- }
- return "mk";
- case LANG_MALAY:
- switch (sub)
- {
- case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
- case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
- }
- return "ms";
- case LANG_MALAYALAM:
- switch (sub)
- {
- case SUBLANG_MALAYALAM_INDIA: return "ml_IN";
- }
- return "ml";
- case LANG_MALTESE:
- switch (sub)
- {
- case SUBLANG_MALTESE_MALTA: return "mt_MT";
- }
- return "mt";
- case LANG_MANIPURI:
- /* FIXME: Adjust this when such locales appear on Unix. */
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "mni_IN";
- }
- return "mni";
- case LANG_MAORI:
- switch (sub)
- {
- case SUBLANG_MAORI_NEW_ZEALAND: return "mi_NZ";
- }
- return "mi";
- case LANG_MAPUDUNGUN:
- switch (sub)
- {
- case SUBLANG_MAPUDUNGUN_CHILE: return "arn_CL";
- }
- return "arn";
- case LANG_MARATHI:
- switch (sub)
- {
- case SUBLANG_MARATHI_INDIA: return "mr_IN";
- }
- return "mr";
- case LANG_MOHAWK:
- switch (sub)
- {
- case SUBLANG_MOHAWK_CANADA: return "moh_CA";
- }
- return "moh";
- case LANG_MONGOLIAN:
- switch (sub)
- {
- case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA: case 0x1e: return "mn_MN";
- case SUBLANG_MONGOLIAN_PRC: case 0x1f: return "mn_CN";
- }
- return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
- case LANG_NEPALI:
- switch (sub)
- {
- case SUBLANG_NEPALI_NEPAL: return "ne_NP";
- case SUBLANG_NEPALI_INDIA: return "ne_IN";
- }
- return "ne";
- case LANG_NORWEGIAN:
- switch (sub)
- {
- case 0x1f: return "nb";
- case SUBLANG_NORWEGIAN_BOKMAL: return "nb_NO";
- case 0x1e: return "nn";
- case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
- }
- return "no";
- case LANG_OCCITAN:
- switch (sub)
- {
- case SUBLANG_OCCITAN_FRANCE: return "oc_FR";
- }
- return "oc";
- case LANG_ORIYA:
- switch (sub)
- {
- case SUBLANG_ORIYA_INDIA: return "or_IN";
- }
- return "or";
- case LANG_OROMO:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "om_ET";
- }
- return "om";
- case LANG_PAPIAMENTU:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "pap_AN";
- }
- return "pap";
- case LANG_PASHTO:
- switch (sub)
- {
- case SUBLANG_PASHTO_AFGHANISTAN: return "ps_AF";
- }
- return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
- case LANG_POLISH:
- switch (sub)
- {
- case SUBLANG_POLISH_POLAND: return "pl_PL";
- }
- return "pl";
- case LANG_PORTUGUESE:
- switch (sub)
- {
- /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
- Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
- case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
- case SUBLANG_PORTUGUESE: return "pt_PT";
- }
- return "pt";
- case LANG_PUNJABI:
- switch (sub)
- {
- case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
- case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */
- }
- return "pa";
- case LANG_QUECHUA:
- /* Note: Microsoft uses the non-ISO language code "quz". */
- switch (sub)
- {
- case SUBLANG_QUECHUA_BOLIVIA: return "qu_BO";
- case SUBLANG_QUECHUA_ECUADOR: return "qu_EC";
- case SUBLANG_QUECHUA_PERU: return "qu_PE";
- }
- return "qu";
- case LANG_ROMANIAN:
- switch (sub)
- {
- case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
- case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD";
- }
- return "ro";
- case LANG_ROMANSH:
- switch (sub)
- {
- case SUBLANG_ROMANSH_SWITZERLAND: return "rm_CH";
- }
- return "rm";
- case LANG_RUSSIAN:
- switch (sub)
- {
- case SUBLANG_RUSSIAN_RUSSIA: return "ru_RU";
- case SUBLANG_RUSSIAN_MOLDAVIA: return "ru_MD";
- }
- return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
- case LANG_SAMI:
- switch (sub)
- {
- /* Northern Sami */
- case 0x00: return "se";
- case SUBLANG_SAMI_NORTHERN_NORWAY: return "se_NO";
- case SUBLANG_SAMI_NORTHERN_SWEDEN: return "se_SE";
- case SUBLANG_SAMI_NORTHERN_FINLAND: return "se_FI";
- /* Lule Sami */
- case 0x1f: return "smj";
- case SUBLANG_SAMI_LULE_NORWAY: return "smj_NO";
- case SUBLANG_SAMI_LULE_SWEDEN: return "smj_SE";
- /* Southern Sami */
- case 0x1e: return "sma";
- case SUBLANG_SAMI_SOUTHERN_NORWAY: return "sma_NO";
- case SUBLANG_SAMI_SOUTHERN_SWEDEN: return "sma_SE";
- /* Skolt Sami */
- case 0x1d: return "sms";
- case SUBLANG_SAMI_SKOLT_FINLAND: return "sms_FI";
- /* Inari Sami */
- case 0x1c: return "smn";
- case SUBLANG_SAMI_INARI_FINLAND: return "smn_FI";
- }
- return "se"; /* or "smi"? */
- case LANG_SANSKRIT:
- switch (sub)
- {
- case SUBLANG_SANSKRIT_INDIA: return "sa_IN";
- }
- return "sa";
- case LANG_SCOTTISH_GAELIC:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "gd_GB";
- }
- return "gd";
- case LANG_SINDHI:
- switch (sub)
- {
- case SUBLANG_SINDHI_INDIA: return "sd_IN";
- case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
- /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/
- }
- return "sd";
- case LANG_SINHALESE:
- switch (sub)
- {
- case SUBLANG_SINHALESE_SRI_LANKA: return "si_LK";
- }
- return "si";
- case LANG_SLOVAK:
- switch (sub)
- {
- case SUBLANG_SLOVAK_SLOVAKIA: return "sk_SK";
- }
- return "sk";
- case LANG_SLOVENIAN:
- switch (sub)
- {
- case SUBLANG_SLOVENIAN_SLOVENIA: return "sl_SI";
- }
- return "sl";
- case LANG_SOMALI:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "so_SO";
- }
- return "so";
- case LANG_SORBIAN:
- /* FIXME: Adjust this when such locales appear on Unix. */
- switch (sub)
- {
- /* Upper Sorbian */
- case 0x00: return "hsb";
- case SUBLANG_UPPER_SORBIAN_GERMANY: return "hsb_DE";
- /* Lower Sorbian */
- case 0x1f: return "dsb";
- case SUBLANG_LOWER_SORBIAN_GERMANY: return "dsb_DE";
- }
- return "wen";
- case LANG_SOTHO:
- /* <https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings>
- calls it "Sesotho sa Leboa"; according to
- <https://www.ethnologue.com/show_language.asp?code=nso>
- <https://www.ethnologue.com/show_language.asp?code=sot>
- it's the same as Northern Sotho. */
- switch (sub)
- {
- case SUBLANG_SOTHO_SOUTH_AFRICA: return "nso_ZA";
- }
- return "nso";
- case LANG_SPANISH:
- switch (sub)
- {
- case SUBLANG_SPANISH: return "es_ES";
- case SUBLANG_SPANISH_MEXICAN: return "es_MX";
- case SUBLANG_SPANISH_MODERN:
- return "es_ES@modern"; /* not seen on Unix */
- case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
- case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
- case SUBLANG_SPANISH_PANAMA: return "es_PA";
- case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
- case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
- case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
- case SUBLANG_SPANISH_PERU: return "es_PE";
- case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
- case SUBLANG_SPANISH_ECUADOR: return "es_EC";
- case SUBLANG_SPANISH_CHILE: return "es_CL";
- case SUBLANG_SPANISH_URUGUAY: return "es_UY";
- case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
- case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
- case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
- case SUBLANG_SPANISH_HONDURAS: return "es_HN";
- case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
- case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
- case SUBLANG_SPANISH_US: return "es_US";
- }
- return "es";
- case LANG_SUTU:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
- }
- return "bnt";
- case LANG_SWAHILI:
- switch (sub)
- {
- case SUBLANG_SWAHILI_KENYA: return "sw_KE";
- }
- return "sw";
- case LANG_SWEDISH:
- switch (sub)
- {
- case SUBLANG_SWEDISH_SWEDEN: return "sv_SE";
- case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
- }
- return "sv";
- case LANG_SYRIAC:
- switch (sub)
- {
- case SUBLANG_SYRIAC_SYRIA: return "syr_SY"; /* An extinct language. */
- }
- return "syr";
- case LANG_TAGALOG:
- switch (sub)
- {
- case SUBLANG_TAGALOG_PHILIPPINES: return "tl_PH"; /* or "fil_PH"? */
- }
- return "tl"; /* or "fil"? */
- case LANG_TAJIK:
- switch (sub)
- {
- case 0x1f: return "tg";
- case SUBLANG_TAJIK_TAJIKISTAN: return "tg_TJ";
- }
- return "tg";
- case LANG_TAMAZIGHT:
- /* Note: Microsoft uses the non-ISO language code "tmz". */
- switch (sub)
- {
- /* FIXME: Adjust this when Tamazight locales appear on Unix. */
- case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
- case 0x1f: return "ber@latin";
- case SUBLANG_TAMAZIGHT_ALGERIA_LATIN: return "ber_DZ@latin";
- }
- return "ber";
- case LANG_TAMIL:
- switch (sub)
- {
- case SUBLANG_TAMIL_INDIA: return "ta_IN";
- }
- return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
- case LANG_TATAR:
- switch (sub)
- {
- case SUBLANG_TATAR_RUSSIA: return "tt_RU";
- }
- return "tt";
- case LANG_TELUGU:
- switch (sub)
- {
- case SUBLANG_TELUGU_INDIA: return "te_IN";
- }
- return "te";
- case LANG_THAI:
- switch (sub)
- {
- case SUBLANG_THAI_THAILAND: return "th_TH";
- }
- return "th";
- case LANG_TIBETAN:
- switch (sub)
- {
- case SUBLANG_TIBETAN_PRC:
- /* Most Tibetans would not like "bo_CN". But Tibet does not yet
- have a country code of its own. */
- return "bo";
- case SUBLANG_TIBETAN_BHUTAN: return "bo_BT";
- }
- return "bo";
- case LANG_TIGRINYA:
- switch (sub)
- {
- case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
- case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
- }
- return "ti";
- case LANG_TSONGA:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "ts_ZA";
- }
- return "ts";
- case LANG_TSWANA:
- /* Spoken in South Africa, Botswana. */
- switch (sub)
- {
- case SUBLANG_TSWANA_SOUTH_AFRICA: return "tn_ZA";
- }
- return "tn";
- case LANG_TURKISH:
- switch (sub)
- {
- case SUBLANG_TURKISH_TURKEY: return "tr_TR";
- }
- return "tr";
- case LANG_TURKMEN:
- switch (sub)
- {
- case SUBLANG_TURKMEN_TURKMENISTAN: return "tk_TM";
- }
- return "tk";
- case LANG_UIGHUR:
- switch (sub)
- {
- case SUBLANG_UIGHUR_PRC: return "ug_CN";
- }
- return "ug";
- case LANG_UKRAINIAN:
- switch (sub)
- {
- case SUBLANG_UKRAINIAN_UKRAINE: return "uk_UA";
- }
- return "uk";
- case LANG_URDU:
- switch (sub)
- {
- case SUBLANG_URDU_PAKISTAN: return "ur_PK";
- case SUBLANG_URDU_INDIA: return "ur_IN";
- }
- return "ur";
- case LANG_UZBEK:
- switch (sub)
- {
- case 0x1f: return "uz";
- case SUBLANG_UZBEK_LATIN: return "uz_UZ";
- case 0x1e: return "uz@cyrillic";
- case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
- }
- return "uz";
- case LANG_VENDA:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "ve_ZA";
- }
- return "ve";
- case LANG_VIETNAMESE:
- switch (sub)
- {
- case SUBLANG_VIETNAMESE_VIETNAM: return "vi_VN";
- }
- return "vi";
- case LANG_WELSH:
- switch (sub)
- {
- case SUBLANG_WELSH_UNITED_KINGDOM: return "cy_GB";
- }
- return "cy";
- case LANG_WOLOF:
- switch (sub)
- {
- case SUBLANG_WOLOF_SENEGAL: return "wo_SN";
- }
- return "wo";
- case LANG_XHOSA:
- switch (sub)
- {
- case SUBLANG_XHOSA_SOUTH_AFRICA: return "xh_ZA";
- }
- return "xh";
- case LANG_YAKUT:
- switch (sub)
- {
- case SUBLANG_YAKUT_RUSSIA: return "sah_RU";
- }
- return "sah";
- case LANG_YI:
- switch (sub)
- {
- case SUBLANG_YI_PRC: return "ii_CN";
- }
- return "ii";
- case LANG_YIDDISH:
- switch (sub)
- {
- case SUBLANG_DEFAULT: return "yi_IL";
- }
- return "yi";
- case LANG_YORUBA:
- switch (sub)
- {
- case SUBLANG_YORUBA_NIGERIA: return "yo_NG";
- }
- return "yo";
- case LANG_ZULU:
- switch (sub)
- {
- case SUBLANG_ZULU_SOUTH_AFRICA: return "zu_ZA";
- }
- return "zu";
- default: return "C";
- }
- }
-}
-
-# if !defined IN_LIBINTL
-static
-# endif
-const char *
-gl_locale_name_from_win32_LCID (LCID lcid)
-{
- LANGID langid;
-
- /* Strip off the sorting rules, keep only the language part. */
- langid = LANGIDFROMLCID (lcid);
-
- return gl_locale_name_from_win32_LANGID (langid);
-}
-
-# ifdef WINDOWS_NATIVE
-
-/* Two variables to interface between get_lcid and the EnumLocales
- callback function below. */
-static LCID found_lcid;
-static char lname[LC_MAX * (LOCALE_NAME_MAX_LENGTH + 1) + 1];
-
-/* Callback function for EnumLocales. */
-static BOOL CALLBACK
-enum_locales_fn (LPSTR locale_num_str)
-{
- char *endp;
- char locval[2 * LOCALE_NAME_MAX_LENGTH + 1 + 1];
- LCID try_lcid = strtoul (locale_num_str, &endp, 16);
-
- if (GetLocaleInfo (try_lcid, LOCALE_SENGLANGUAGE,
- locval, LOCALE_NAME_MAX_LENGTH))
- {
- strcat (locval, "_");
- if (GetLocaleInfo (try_lcid, LOCALE_SENGCOUNTRY,
- locval + strlen (locval), LOCALE_NAME_MAX_LENGTH))
- {
- size_t locval_len = strlen (locval);
-
- if (strncmp (locval, lname, locval_len) == 0
- && (lname[locval_len] == '.'
- || lname[locval_len] == '\0'))
- {
- found_lcid = try_lcid;
- return FALSE;
- }
- }
- }
- return TRUE;
-}
-
-/* This lock protects the get_lcid against multiple simultaneous calls. */
-gl_lock_define_initialized(static, get_lcid_lock)
-
-/* Return the Locale ID (LCID) number given the locale's name, a
- string, in LOCALE_NAME. This works by enumerating all the locales
- supported by the system, until we find one whose name matches
- LOCALE_NAME. */
-static LCID
-get_lcid (const char *locale_name)
-{
- /* A simple cache. */
- static LCID last_lcid;
- static char last_locale[1000];
-
- /* Lock while looking for an LCID, to protect access to static
- variables: last_lcid, last_locale, found_lcid, and lname. */
- gl_lock_lock (get_lcid_lock);
- if (last_lcid > 0 && strcmp (locale_name, last_locale) == 0)
- {
- gl_lock_unlock (get_lcid_lock);
- return last_lcid;
- }
- strncpy (lname, locale_name, sizeof (lname) - 1);
- lname[sizeof (lname) - 1] = '\0';
- found_lcid = 0;
- EnumSystemLocales (enum_locales_fn, LCID_SUPPORTED);
- if (found_lcid > 0)
- {
- last_lcid = found_lcid;
- strcpy (last_locale, locale_name);
- }
- gl_lock_unlock (get_lcid_lock);
- return found_lcid;
-}
-
-# endif
-#endif
-
-
-#if HAVE_GOOD_USELOCALE /* glibc, Mac OS X, FreeBSD >= 9.1, Cygwin >= 2.6,
- Solaris 11 OpenIndiana, or Solaris >= 11.4 */
-
-/* Simple hash set of strings. We don't want to drag in lots of hash table
- code here. */
-
-# define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
-
-/* A hash function for NUL-terminated char* strings using
- the method described by Bruno Haible.
- See https://www.haible.de/bruno/hashfunc.html. */
-static size_t _GL_ATTRIBUTE_PURE
-string_hash (const void *x)
-{
- const char *s = (const char *) x;
- size_t h = 0;
-
- for (; *s; s++)
- h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
-
- return h;
-}
-
-/* A hash table of fixed size. Multiple threads can access it read-only
- simultaneously, but only one thread can insert into it at the same time. */
-
-/* A node in a hash bucket collision list. */
-struct struniq_hash_node
- {
- struct struniq_hash_node * volatile next;
- char contents[FLEXIBLE_ARRAY_MEMBER];
- };
-
-# define STRUNIQ_HASH_TABLE_SIZE 257
-static struct struniq_hash_node * volatile struniq_hash_table[STRUNIQ_HASH_TABLE_SIZE]
- /* = { NULL, ..., NULL } */;
-
-/* This lock protects the struniq_hash_table against multiple simultaneous
- insertions. */
-gl_lock_define_initialized(static, struniq_lock)
-
-/* Store a copy of the given string in a string pool with indefinite extent.
- Return a pointer to this copy. */
-static const char *
-struniq (const char *string)
-{
- size_t hashcode = string_hash (string);
- size_t slot = hashcode % STRUNIQ_HASH_TABLE_SIZE;
- size_t size;
- struct struniq_hash_node *new_node;
- struct struniq_hash_node *p;
- for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
- if (strcmp (p->contents, string) == 0)
- return p->contents;
- size = strlen (string) + 1;
- new_node =
- (struct struniq_hash_node *)
- malloc (FLEXSIZEOF (struct struniq_hash_node, contents, size));
- if (new_node == NULL)
- /* Out of memory. Return a statically allocated string. */
- return "C";
- memcpy (new_node->contents, string, size);
- {
- bool mt = gl_multithreaded ();
- /* Lock while inserting new_node. */
- if (mt) gl_lock_lock (struniq_lock);
- /* Check whether another thread already added the string while we were
- waiting on the lock. */
- for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
- if (strcmp (p->contents, string) == 0)
- {
- free (new_node);
- new_node = p;
- goto done;
- }
- /* Really insert new_node into the hash table. Fill new_node entirely
- first, because other threads may be iterating over the linked list. */
- new_node->next = struniq_hash_table[slot];
- struniq_hash_table[slot] = new_node;
- done:
- /* Unlock after new_node is inserted. */
- if (mt) gl_lock_unlock (struniq_lock);
- }
- return new_node->contents;
-}
-
-#endif
-
-
-#if LOCALENAME_ENHANCE_LOCALE_FUNCS
-
-/* The 'locale_t' object does not contain the names of the locale categories.
- We have to associate them with the object through a hash table.
- The hash table is defined in localename-table.[hc]. */
-
-/* Returns the name of a given locale category in a given locale_t object,
- allocated as a string with indefinite extent. */
-static const char *
-get_locale_t_name (int category, locale_t locale)
-{
- if (locale == LC_GLOBAL_LOCALE)
- {
- /* Query the global locale. */
- const char *name = setlocale_null (category);
- if (name != NULL)
- return struniq (name);
- else
- /* Should normally not happen. */
- return "";
- }
- else
- {
- /* Look up the names in the hash table. */
- size_t hashcode = locale_hash_function (locale);
- size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
- /* If the locale was not found in the table, return "". This can
- happen if the application uses the original newlocale()/duplocale()
- functions instead of the overridden ones. */
- const char *name = "";
- struct locale_hash_node *p;
- /* Lock while looking up the hash node. */
- gl_rwlock_rdlock (locale_lock);
- for (p = locale_hash_table[slot]; p != NULL; p = p->next)
- if (p->locale == locale)
- {
- name = p->names.category_name[category];
- break;
- }
- gl_rwlock_unlock (locale_lock);
- return name;
- }
-}
-
-# if !(defined newlocale && defined duplocale && defined freelocale)
-# error "newlocale, duplocale, freelocale not being replaced as expected!"
-# endif
-
-/* newlocale() override. */
-locale_t
-newlocale (int category_mask, const char *name, locale_t base)
-#undef newlocale
-{
- struct locale_categories_names names;
- struct locale_hash_node *node;
- locale_t result;
-
- /* Make sure name has indefinite extent. */
- if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK
- | LC_MONETARY_MASK | LC_MESSAGES_MASK)
- & category_mask) != 0)
- name = struniq (name);
-
- /* Determine the category names of the result. */
- if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK
- | LC_MONETARY_MASK | LC_MESSAGES_MASK)
- & ~category_mask) == 0)
- {
- /* Use name, ignore base. */
- int category;
-
- name = struniq (name);
- for (category = 0; category < 6; category++)
- names.category_name[category] = name;
- }
- else
- {
- /* Use base, possibly also name. */
- if (base == NULL)
- {
- int category;
-
- for (category = 0; category < 6; category++)
- {
- int mask;
-
- switch (category)
- {
- case LC_CTYPE:
- mask = LC_CTYPE_MASK;
- break;
- case LC_NUMERIC:
- mask = LC_NUMERIC_MASK;
- break;
- case LC_TIME:
- mask = LC_TIME_MASK;
- break;
- case LC_COLLATE:
- mask = LC_COLLATE_MASK;
- break;
- case LC_MONETARY:
- mask = LC_MONETARY_MASK;
- break;
- case LC_MESSAGES:
- mask = LC_MESSAGES_MASK;
- break;
- default:
- abort ();
- }
- names.category_name[category] =
- ((mask & category_mask) != 0 ? name : "C");
- }
- }
- else if (base == LC_GLOBAL_LOCALE)
- {
- int category;
-
- for (category = 0; category < 6; category++)
- {
- int mask;
-
- switch (category)
- {
- case LC_CTYPE:
- mask = LC_CTYPE_MASK;
- break;
- case LC_NUMERIC:
- mask = LC_NUMERIC_MASK;
- break;
- case LC_TIME:
- mask = LC_TIME_MASK;
- break;
- case LC_COLLATE:
- mask = LC_COLLATE_MASK;
- break;
- case LC_MONETARY:
- mask = LC_MONETARY_MASK;
- break;
- case LC_MESSAGES:
- mask = LC_MESSAGES_MASK;
- break;
- default:
- abort ();
- }
- names.category_name[category] =
- ((mask & category_mask) != 0
- ? name
- : get_locale_t_name (category, LC_GLOBAL_LOCALE));
- }
- }
- else
- {
- /* Look up the names of base in the hash table. Like multiple calls
- of get_locale_t_name, but locking only once. */
- struct locale_hash_node *p;
- int category;
-
- /* Lock while looking up the hash node. */
- gl_rwlock_rdlock (locale_lock);
- for (p = locale_hash_table[locale_hash_function (base) % LOCALE_HASH_TABLE_SIZE];
- p != NULL;
- p = p->next)
- if (p->locale == base)
- break;
-
- for (category = 0; category < 6; category++)
- {
- int mask;
-
- switch (category)
- {
- case LC_CTYPE:
- mask = LC_CTYPE_MASK;
- break;
- case LC_NUMERIC:
- mask = LC_NUMERIC_MASK;
- break;
- case LC_TIME:
- mask = LC_TIME_MASK;
- break;
- case LC_COLLATE:
- mask = LC_COLLATE_MASK;
- break;
- case LC_MONETARY:
- mask = LC_MONETARY_MASK;
- break;
- case LC_MESSAGES:
- mask = LC_MESSAGES_MASK;
- break;
- default:
- abort ();
- }
- names.category_name[category] =
- ((mask & category_mask) != 0
- ? name
- : (p != NULL ? p->names.category_name[category] : ""));
- }
-
- gl_rwlock_unlock (locale_lock);
- }
- }
-
- node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node));
- if (node == NULL)
- /* errno is set to ENOMEM. */
- return NULL;
-
- result = newlocale (category_mask, name, base);
- if (result == NULL)
- {
- int saved_errno = errno;
- free (node);
- errno = saved_errno;
- return NULL;
- }
-
- /* Fill the hash node. */
- node->locale = result;
- node->names = names;
-
- /* Insert it in the hash table. */
- {
- size_t hashcode = locale_hash_function (result);
- size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
- struct locale_hash_node *p;
-
- /* Lock while inserting the new node. */
- gl_rwlock_wrlock (locale_lock);
- for (p = locale_hash_table[slot]; p != NULL; p = p->next)
- if (p->locale == result)
- {
- /* This can happen if the application uses the original freelocale()
- function instead of the overridden one. */
- p->names = node->names;
- break;
- }
- if (p == NULL)
- {
- node->next = locale_hash_table[slot];
- locale_hash_table[slot] = node;
- }
-
- gl_rwlock_unlock (locale_lock);
-
- if (p != NULL)
- free (node);
- }
-
- return result;
-}
-
-/* duplocale() override. */
-locale_t
-duplocale (locale_t locale)
-#undef duplocale
-{
- struct locale_hash_node *node;
- locale_t result;
-
- if (locale == NULL)
- /* Invalid argument. */
- abort ();
-
- node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node));
- if (node == NULL)
- /* errno is set to ENOMEM. */
- return NULL;
-
- result = duplocale (locale);
- if (result == NULL)
- {
- int saved_errno = errno;
- free (node);
- errno = saved_errno;
- return NULL;
- }
-
- /* Fill the hash node. */
- node->locale = result;
- if (locale == LC_GLOBAL_LOCALE)
- {
- int category;
-
- for (category = 0; category < 6; category++)
- node->names.category_name[category] =
- get_locale_t_name (category, LC_GLOBAL_LOCALE);
-
- /* Lock before inserting the new node. */
- gl_rwlock_wrlock (locale_lock);
- }
- else
- {
- struct locale_hash_node *p;
-
- /* Lock once, for the lookup and the insertion. */
- gl_rwlock_wrlock (locale_lock);
-
- for (p = locale_hash_table[locale_hash_function (locale) % LOCALE_HASH_TABLE_SIZE];
- p != NULL;
- p = p->next)
- if (p->locale == locale)
- break;
- if (p != NULL)
- node->names = p->names;
- else
- {
- /* This can happen if the application uses the original
- newlocale()/duplocale() functions instead of the overridden
- ones. */
- int category;
-
- for (category = 0; category < 6; category++)
- node->names.category_name[category] = "";
- }
- }
-
- /* Insert it in the hash table. */
- {
- size_t hashcode = locale_hash_function (result);
- size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
- struct locale_hash_node *p;
-
- for (p = locale_hash_table[slot]; p != NULL; p = p->next)
- if (p->locale == result)
- {
- /* This can happen if the application uses the original freelocale()
- function instead of the overridden one. */
- p->names = node->names;
- break;
- }
- if (p == NULL)
- {
- node->next = locale_hash_table[slot];
- locale_hash_table[slot] = node;
- }
-
- gl_rwlock_unlock (locale_lock);
-
- if (p != NULL)
- free (node);
- }
-
- return result;
-}
-
-/* freelocale() override. */
-void
-freelocale (locale_t locale)
-#undef freelocale
-{
- if (locale == NULL || locale == LC_GLOBAL_LOCALE)
- /* Invalid argument. */
- abort ();
-
- {
- size_t hashcode = locale_hash_function (locale);
- size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
- struct locale_hash_node *found;
- struct locale_hash_node **p;
-
- found = NULL;
- /* Lock while removing the hash node. */
- gl_rwlock_wrlock (locale_lock);
- for (p = &locale_hash_table[slot]; *p != NULL; p = &(*p)->next)
- if ((*p)->locale == locale)
- {
- found = *p;
- *p = (*p)->next;
- break;
- }
- gl_rwlock_unlock (locale_lock);
- free (found);
- }
-
- freelocale (locale);
-}
-
-#endif
-
-
-#if defined IN_LIBINTL || HAVE_GOOD_USELOCALE
-
-/* Like gl_locale_name_thread, except that the result is not in storage of
- indefinite extent. */
-# if !defined IN_LIBINTL
-static
-# endif
-const char *
-gl_locale_name_thread_unsafe (int category, const char *categoryname _GL_UNUSED)
-{
-# if HAVE_GOOD_USELOCALE
- {
- locale_t thread_locale = uselocale (NULL);
- if (thread_locale != LC_GLOBAL_LOCALE)
- {
-# if __GLIBC__ >= 2 && !defined __UCLIBC__
- /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
- glibc < 2.12.
- See <https://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
- const char *name =
- nl_langinfo (_NL_ITEM ((category), _NL_ITEM_INDEX (-1)));
- if (name[0] == '\0')
- /* Fallback code for glibc < 2.4, which did not implement
- nl_langinfo (_NL_LOCALE_NAME (category)). */
- name = thread_locale->__names[category];
- return name;
-# elif defined __linux__ && HAVE_LANGINFO_H && defined NL_LOCALE_NAME
- /* musl libc */
- return nl_langinfo_l (NL_LOCALE_NAME (category), thread_locale);
-# elif (defined __FreeBSD__ || defined __DragonFly__) || (defined __APPLE__ && defined __MACH__)
- /* FreeBSD, Mac OS X */
- int mask;
-
- switch (category)
- {
- case LC_CTYPE:
- mask = LC_CTYPE_MASK;
- break;
- case LC_NUMERIC:
- mask = LC_NUMERIC_MASK;
- break;
- case LC_TIME:
- mask = LC_TIME_MASK;
- break;
- case LC_COLLATE:
- mask = LC_COLLATE_MASK;
- break;
- case LC_MONETARY:
- mask = LC_MONETARY_MASK;
- break;
- case LC_MESSAGES:
- mask = LC_MESSAGES_MASK;
- break;
- default: /* We shouldn't get here. */
- return "";
- }
- return querylocale (mask, thread_locale);
-# elif defined __sun
-# if HAVE_GETLOCALENAME_L
- /* Solaris >= 12. */
- return getlocalename_l (category, thread_locale);
-# elif HAVE_SOLARIS114_LOCALES
- /* Solaris >= 11.4. */
- void *lcp = (*thread_locale)->core.data->lcp;
- if (lcp != NULL)
- switch (category)
- {
- case LC_CTYPE:
- case LC_NUMERIC:
- case LC_TIME:
- case LC_COLLATE:
- case LC_MONETARY:
- case LC_MESSAGES:
- return ((const char * const *) lcp)[category];
- default: /* We shouldn't get here. */
- return "";
- }
-# elif HAVE_NAMELESS_LOCALES
- return get_locale_t_name (category, thread_locale);
-# else
- /* Solaris 11 OpenIndiana.
- For the internal structure of locale objects, see
- https://github.com/OpenIndiana/illumos-gate/blob/master/usr/src/lib/libc/port/locale/localeimpl.h */
- switch (category)
- {
- case LC_CTYPE:
- case LC_NUMERIC:
- case LC_TIME:
- case LC_COLLATE:
- case LC_MONETARY:
- case LC_MESSAGES:
- return ((const char * const *) thread_locale)[category];
- default: /* We shouldn't get here. */
- return "";
- }
-# endif
-# elif defined _AIX && HAVE_NAMELESS_LOCALES
- return get_locale_t_name (category, thread_locale);
-# elif defined __CYGWIN__
- /* Cygwin < 2.6 lacks uselocale and thread-local locales altogether.
- Cygwin <= 2.6.1 lacks NL_LOCALE_NAME, requiring peeking inside
- an opaque struct. */
-# ifdef NL_LOCALE_NAME
- return nl_langinfo_l (NL_LOCALE_NAME (category), thread_locale);
-# else
- /* FIXME: Remove when we can assume new-enough Cygwin. */
- struct __locale_t {
- char categories[7][32];
- };
- return ((struct __locale_t *) thread_locale)->categories[category];
-# endif
-# elif defined __ANDROID__
- return MB_CUR_MAX == 4 ? "C.UTF-8" : "C";
-# endif
- }
- }
-# endif
- return NULL;
-}
-
-#endif
-
-const char *
-gl_locale_name_thread (int category, const char *categoryname _GL_UNUSED)
-{
-#if HAVE_GOOD_USELOCALE
- const char *name = gl_locale_name_thread_unsafe (category, categoryname);
- if (name != NULL)
- return struniq (name);
-#endif
- /* On WINDOWS_NATIVE, don't use GetThreadLocale() here, because when
- SetThreadLocale has not been called - which is a very frequent case -
- the value of GetThreadLocale() ignores past calls to 'setlocale'. */
- return NULL;
-}
-
-/* XPG3 defines the result of 'setlocale (category, NULL)' as:
- "Directs 'setlocale()' to query 'category' and return the current
- setting of 'local'."
- However it does not specify the exact format. Neither do SUSV2 and
- ISO C 99. So we can use this feature only on selected systems (e.g.
- those using GNU C Library). */
-#if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__)
-# define HAVE_LOCALE_NULL
-#endif
-
-const char *
-gl_locale_name_posix (int category, const char *categoryname _GL_UNUSED)
-{
-#if defined WINDOWS_NATIVE
- if (LC_MIN <= category && category <= LC_MAX)
- {
- const char *locname =
- /* setlocale_null (category) is identical to setlocale (category, NULL)
- on this platform. */
- setlocale (category, NULL);
-
- /* Convert locale name to LCID. We don't want to use
- LocaleNameToLCID because (a) it is only available since Vista,
- and (b) it doesn't accept locale names returned by 'setlocale'. */
- LCID lcid = get_lcid (locname);
-
- if (lcid > 0)
- return gl_locale_name_from_win32_LCID (lcid);
- }
-#endif
- {
- const char *locname;
-
- /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
- On some systems this can be done by the 'setlocale' function itself. */
-#if defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
- locname = setlocale_null (category);
-#else
- /* On other systems we ignore what setlocale reports and instead look at the
- environment variables directly. This is necessary
- 1. on systems which have a facility for customizing the default locale
- (Mac OS X, native Windows, Cygwin) and where the system's setlocale()
- function ignores this default locale (Mac OS X, Cygwin), in two cases:
- a. when the user missed to use the setlocale() override from libintl
- (for example by not including <libintl.h>),
- b. when setlocale supports only the "C" locale, such as on Cygwin
- 1.5.x. In this case even the override from libintl cannot help.
- 2. on all systems where setlocale supports only the "C" locale. */
- /* Strictly speaking, it is a POSIX violation to look at the environment
- variables regardless whether setlocale has been called or not. POSIX
- says:
- "For C-language programs, the POSIX locale shall be the
- default locale when the setlocale() function is not called."
- But we assume that all programs that use internationalized APIs call
- setlocale (LC_ALL, ""). */
- locname = gl_locale_name_environ (category, categoryname);
-#endif
- /* Convert the locale name from the format returned by setlocale() or found
- in the environment variables to the XPG syntax. */
-#if defined WINDOWS_NATIVE
- if (locname != NULL)
- {
- /* Convert locale name to LCID. We don't want to use
- LocaleNameToLCID because (a) it is only available since Vista,
- and (b) it doesn't accept locale names returned by 'setlocale'. */
- LCID lcid = get_lcid (locname);
-
- if (lcid > 0)
- return gl_locale_name_from_win32_LCID (lcid);
- }
-#endif
- return locname;
- }
-}
-
-const char *
-gl_locale_name_environ (int category _GL_UNUSED, const char *categoryname)
-{
- const char *retval;
-
- /* Setting of LC_ALL overrides all other. */
- retval = getenv ("LC_ALL");
- if (retval != NULL && retval[0] != '\0')
- return retval;
- /* Next comes the name of the desired category. */
- retval = getenv (categoryname);
- if (retval != NULL && retval[0] != '\0')
- return retval;
- /* Last possibility is the LANG environment variable. */
- retval = getenv ("LANG");
- if (retval != NULL && retval[0] != '\0')
- {
-#if HAVE_CFPREFERENCESCOPYAPPVALUE
- /* Mac OS X 10.2 or newer.
- Ignore invalid LANG value set by the Terminal application. */
- if (strcmp (retval, "UTF-8") != 0)
-#endif
-#if defined __CYGWIN__
- /* Cygwin.
- Ignore dummy LANG value set by ~/.profile. */
- if (strcmp (retval, "C.UTF-8") != 0)
-#endif
- return retval;
- }
-
- return NULL;
-}
-
-const char *
-gl_locale_name_default (void)
-{
- /* POSIX:2001 says:
- "All implementations shall define a locale as the default locale, to be
- invoked when no environment variables are set, or set to the empty
- string. This default locale can be the POSIX locale or any other
- implementation-defined locale. Some implementations may provide
- facilities for local installation administrators to set the default
- locale, customizing it for each location. POSIX:2001 does not require
- such a facility.
-
- The systems with such a facility are Mac OS X and Windows: They provide a
- GUI that allows the user to choose a locale.
- - On Mac OS X, by default, none of LC_* or LANG are set. Starting with
- Mac OS X 10.4 or 10.5, LANG is set for processes launched by the
- 'Terminal' application (but sometimes to an incorrect value "UTF-8").
- When no environment variable is set, setlocale (LC_ALL, "") uses the
- "C" locale.
- - On native Windows, by default, none of LC_* or LANG are set.
- When no environment variable is set, setlocale (LC_ALL, "") uses the
- locale chosen by the user.
- - On Cygwin 1.5.x, by default, none of LC_* or LANG are set.
- When no environment variable is set, setlocale (LC_ALL, "") uses the
- "C" locale.
- - On Cygwin 1.7, by default, LANG is set to "C.UTF-8" when the default
- ~/.profile is executed.
- When no environment variable is set, setlocale (LC_ALL, "") uses the
- "C.UTF-8" locale, which operates in the same way as the "C" locale.
- */
-
-#if !(HAVE_CFPREFERENCESCOPYAPPVALUE || defined WINDOWS_NATIVE || defined __CYGWIN__)
-
- /* The system does not have a way of setting the locale, other than the
- POSIX specified environment variables. We use C as default locale. */
- return "C";
-
-#else
-
- /* Return an XPG style locale name language[_territory][@modifier].
- Don't even bother determining the codeset; it's not useful in this
- context, because message catalogs are not specific to a single
- codeset. */
-
-# if HAVE_CFPREFERENCESCOPYAPPVALUE
- /* Mac OS X 10.4 or newer */
- /* Don't use the API introduced in Mac OS X 10.5, CFLocaleCopyCurrent,
- because in macOS 10.13.4 it has the following behaviour:
- When two or more languages are specified in the
- "System Preferences > Language & Region > Preferred Languages" panel,
- it returns en_CC where CC is the territory (even when English is not among
- the preferred languages!). What we want instead is what
- CFLocaleCopyCurrent returned in earlier macOS releases and what
- CFPreferencesCopyAppValue still returns, namely ll_CC where ll is the
- first among the preferred languages and CC is the territory. */
- {
- /* Cache the locale name, since CoreFoundation calls are expensive. */
- static const char *cached_localename;
-
- if (cached_localename == NULL)
- {
- char namebuf[256];
- CFTypeRef value =
- CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
- kCFPreferencesCurrentApplication);
- if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
- {
- CFStringRef name = (CFStringRef)value;
-
- if (CFStringGetCString (name, namebuf, sizeof (namebuf),
- kCFStringEncodingASCII))
- {
- gl_locale_name_canonicalize (namebuf);
- cached_localename = strdup (namebuf);
- }
- }
- if (cached_localename == NULL)
- cached_localename = "C";
- }
- return cached_localename;
- }
-
-# endif
-
-# if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
- {
- LCID lcid;
-
- /* Use native Windows API locale ID. */
- lcid = GetThreadLocale ();
-
- return gl_locale_name_from_win32_LCID (lcid);
- }
-# endif
-#endif
-}
-
-/* Determine the current locale's name, and canonicalize it into XPG syntax
- language[_territory][.codeset][@modifier]
- The codeset part in the result is not reliable; the locale_charset()
- should be used for codeset information instead.
- The result must not be freed; it is statically allocated. */
-
-const char *
-gl_locale_name (int category, const char *categoryname)
-{
- const char *retval;
-
- retval = gl_locale_name_thread (category, categoryname);
- if (retval != NULL)
- return retval;
-
- retval = gl_locale_name_posix (category, categoryname);
- if (retval != NULL)
- return retval;
-
- return gl_locale_name_default ();
-}
+++ /dev/null
-/* Locking in multithreaded situations.
- Copyright (C) 2005-2008, 2012, 2017, 2019-2020 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-posix.h, gthr-posix95.h. */
-
-#include <config.h>
-
-#include "lock.h"
-
-/* ========================================================================= */
-
-#if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-int
-glthread_lock_init (gl_lock_t *lock)
-{
- if (mtx_init (&lock->mutex, mtx_plain) != thrd_success)
- return ENOMEM;
- lock->init_needed = 0;
- return 0;
-}
-
-int
-glthread_lock_lock (gl_lock_t *lock)
-{
- if (lock->init_needed)
- call_once (&lock->init_once, lock->init_func);
- if (mtx_lock (&lock->mutex) != thrd_success)
- return EAGAIN;
- return 0;
-}
-
-int
-glthread_lock_unlock (gl_lock_t *lock)
-{
- if (lock->init_needed)
- call_once (&lock->init_once, lock->init_func);
- if (mtx_unlock (&lock->mutex) != thrd_success)
- return EINVAL;
- return 0;
-}
-
-int
-glthread_lock_destroy (gl_lock_t *lock)
-{
- if (lock->init_needed)
- call_once (&lock->init_once, lock->init_func);
- mtx_destroy (&lock->mutex);
- return 0;
-}
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-int
-glthread_rwlock_init (gl_rwlock_t *lock)
-{
- if (mtx_init (&lock->lock, mtx_plain) != thrd_success
- || cnd_init (&lock->waiting_readers) != thrd_success
- || cnd_init (&lock->waiting_writers) != thrd_success)
- return ENOMEM;
- lock->waiting_writers_count = 0;
- lock->runcount = 0;
- lock->init_needed = 0;
- return 0;
-}
-
-int
-glthread_rwlock_rdlock (gl_rwlock_t *lock)
-{
- if (lock->init_needed)
- call_once (&lock->init_once, lock->init_func);
- if (mtx_lock (&lock->lock) != thrd_success)
- return EAGAIN;
- /* Test whether only readers are currently running, and whether the runcount
- field will not overflow, and whether no writer is waiting. The latter
- condition is because POSIX recommends that "write locks shall take
- precedence over read locks", to avoid "writer starvation". */
- while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
- {
- /* This thread has to wait for a while. Enqueue it among the
- waiting_readers. */
- if (cnd_wait (&lock->waiting_readers, &lock->lock) != thrd_success)
- {
- mtx_unlock (&lock->lock);
- return EINVAL;
- }
- }
- lock->runcount++;
- if (mtx_unlock (&lock->lock) != thrd_success)
- return EINVAL;
- return 0;
-}
-
-int
-glthread_rwlock_wrlock (gl_rwlock_t *lock)
-{
- if (lock->init_needed)
- call_once (&lock->init_once, lock->init_func);
- if (mtx_lock (&lock->lock) != thrd_success)
- return EAGAIN;
- /* Test whether no readers or writers are currently running. */
- while (!(lock->runcount == 0))
- {
- /* This thread has to wait for a while. Enqueue it among the
- waiting_writers. */
- lock->waiting_writers_count++;
- if (cnd_wait (&lock->waiting_writers, &lock->lock) != thrd_success)
- {
- lock->waiting_writers_count--;
- mtx_unlock (&lock->lock);
- return EINVAL;
- }
- lock->waiting_writers_count--;
- }
- lock->runcount--; /* runcount becomes -1 */
- if (mtx_unlock (&lock->lock) != thrd_success)
- return EINVAL;
- return 0;
-}
-
-int
-glthread_rwlock_unlock (gl_rwlock_t *lock)
-{
- if (lock->init_needed)
- call_once (&lock->init_once, lock->init_func);
- if (mtx_lock (&lock->lock) != thrd_success)
- return EAGAIN;
- if (lock->runcount < 0)
- {
- /* Drop a writer lock. */
- if (!(lock->runcount == -1))
- {
- mtx_unlock (&lock->lock);
- return EINVAL;
- }
- lock->runcount = 0;
- }
- else
- {
- /* Drop a reader lock. */
- if (!(lock->runcount > 0))
- {
- mtx_unlock (&lock->lock);
- return EINVAL;
- }
- lock->runcount--;
- }
- if (lock->runcount == 0)
- {
- /* POSIX recommends that "write locks shall take precedence over read
- locks", to avoid "writer starvation". */
- if (lock->waiting_writers_count > 0)
- {
- /* Wake up one of the waiting writers. */
- if (cnd_signal (&lock->waiting_writers) != thrd_success)
- {
- mtx_unlock (&lock->lock);
- return EINVAL;
- }
- }
- else
- {
- /* Wake up all waiting readers. */
- if (cnd_broadcast (&lock->waiting_readers) != thrd_success)
- {
- mtx_unlock (&lock->lock);
- return EINVAL;
- }
- }
- }
- if (mtx_unlock (&lock->lock) != thrd_success)
- return EINVAL;
- return 0;
-}
-
-int
-glthread_rwlock_destroy (gl_rwlock_t *lock)
-{
- if (lock->init_needed)
- call_once (&lock->init_once, lock->init_func);
- mtx_destroy (&lock->lock);
- cnd_destroy (&lock->waiting_readers);
- cnd_destroy (&lock->waiting_writers);
- return 0;
-}
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-int
-glthread_recursive_lock_init (gl_recursive_lock_t *lock)
-{
- if (mtx_init (&lock->mutex, mtx_plain | mtx_recursive) != thrd_success)
- return ENOMEM;
- lock->init_needed = 0;
- return 0;
-}
-
-int
-glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
-{
- if (lock->init_needed)
- call_once (&lock->init_once, lock->init_func);
- if (mtx_lock (&lock->mutex) != thrd_success)
- return EAGAIN;
- return 0;
-}
-
-int
-glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
-{
- if (lock->init_needed)
- call_once (&lock->init_once, lock->init_func);
- if (mtx_unlock (&lock->mutex) != thrd_success)
- return EINVAL;
- return 0;
-}
-
-int
-glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
-{
- if (lock->init_needed)
- call_once (&lock->init_once, lock->init_func);
- mtx_destroy (&lock->mutex);
- return 0;
-}
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-#endif
-
-/* ========================================================================= */
-
-#if USE_POSIX_THREADS
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
-
-# if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
-
-# if !HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
- /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
-
-int
-glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock)
-{
- pthread_rwlockattr_t attributes;
- int err;
-
- err = pthread_rwlockattr_init (&attributes);
- if (err != 0)
- return err;
- /* Note: PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP is the only value that
- causes the writer to be preferred. PTHREAD_RWLOCK_PREFER_WRITER_NP does not
- do this; see
- http://man7.org/linux/man-pages/man3/pthread_rwlockattr_setkind_np.3.html */
- err = pthread_rwlockattr_setkind_np (&attributes,
- PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
- if (err == 0)
- err = pthread_rwlock_init(lock, &attributes);
- /* pthread_rwlockattr_destroy always returns 0. It cannot influence the
- return value. */
- pthread_rwlockattr_destroy (&attributes);
- return err;
-}
-
-# endif
-# else
-
-int
-glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
-{
- int err;
-
- err = pthread_rwlock_init (&lock->rwlock, NULL);
- if (err != 0)
- return err;
- lock->initialized = 1;
- return 0;
-}
-
-int
-glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
-{
- if (!lock->initialized)
- {
- int err;
-
- err = pthread_mutex_lock (&lock->guard);
- if (err != 0)
- return err;
- if (!lock->initialized)
- {
- err = glthread_rwlock_init_multithreaded (lock);
- if (err != 0)
- {
- pthread_mutex_unlock (&lock->guard);
- return err;
- }
- }
- err = pthread_mutex_unlock (&lock->guard);
- if (err != 0)
- return err;
- }
- return pthread_rwlock_rdlock (&lock->rwlock);
-}
-
-int
-glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
-{
- if (!lock->initialized)
- {
- int err;
-
- err = pthread_mutex_lock (&lock->guard);
- if (err != 0)
- return err;
- if (!lock->initialized)
- {
- err = glthread_rwlock_init_multithreaded (lock);
- if (err != 0)
- {
- pthread_mutex_unlock (&lock->guard);
- return err;
- }
- }
- err = pthread_mutex_unlock (&lock->guard);
- if (err != 0)
- return err;
- }
- return pthread_rwlock_wrlock (&lock->rwlock);
-}
-
-int
-glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
-{
- if (!lock->initialized)
- return EINVAL;
- return pthread_rwlock_unlock (&lock->rwlock);
-}
-
-int
-glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
-{
- int err;
-
- if (!lock->initialized)
- return EINVAL;
- err = pthread_rwlock_destroy (&lock->rwlock);
- if (err != 0)
- return err;
- lock->initialized = 0;
- return 0;
-}
-
-# endif
-
-# else
-
-int
-glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
-{
- int err;
-
- err = pthread_mutex_init (&lock->lock, NULL);
- if (err != 0)
- return err;
- err = pthread_cond_init (&lock->waiting_readers, NULL);
- if (err != 0)
- return err;
- err = pthread_cond_init (&lock->waiting_writers, NULL);
- if (err != 0)
- return err;
- lock->waiting_writers_count = 0;
- lock->runcount = 0;
- return 0;
-}
-
-int
-glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
-{
- int err;
-
- err = pthread_mutex_lock (&lock->lock);
- if (err != 0)
- return err;
- /* Test whether only readers are currently running, and whether the runcount
- field will not overflow, and whether no writer is waiting. The latter
- condition is because POSIX recommends that "write locks shall take
- precedence over read locks", to avoid "writer starvation". */
- while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
- {
- /* This thread has to wait for a while. Enqueue it among the
- waiting_readers. */
- err = pthread_cond_wait (&lock->waiting_readers, &lock->lock);
- if (err != 0)
- {
- pthread_mutex_unlock (&lock->lock);
- return err;
- }
- }
- lock->runcount++;
- return pthread_mutex_unlock (&lock->lock);
-}
-
-int
-glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
-{
- int err;
-
- err = pthread_mutex_lock (&lock->lock);
- if (err != 0)
- return err;
- /* Test whether no readers or writers are currently running. */
- while (!(lock->runcount == 0))
- {
- /* This thread has to wait for a while. Enqueue it among the
- waiting_writers. */
- lock->waiting_writers_count++;
- err = pthread_cond_wait (&lock->waiting_writers, &lock->lock);
- if (err != 0)
- {
- lock->waiting_writers_count--;
- pthread_mutex_unlock (&lock->lock);
- return err;
- }
- lock->waiting_writers_count--;
- }
- lock->runcount--; /* runcount becomes -1 */
- return pthread_mutex_unlock (&lock->lock);
-}
-
-int
-glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
-{
- int err;
-
- err = pthread_mutex_lock (&lock->lock);
- if (err != 0)
- return err;
- if (lock->runcount < 0)
- {
- /* Drop a writer lock. */
- if (!(lock->runcount == -1))
- {
- pthread_mutex_unlock (&lock->lock);
- return EINVAL;
- }
- lock->runcount = 0;
- }
- else
- {
- /* Drop a reader lock. */
- if (!(lock->runcount > 0))
- {
- pthread_mutex_unlock (&lock->lock);
- return EINVAL;
- }
- lock->runcount--;
- }
- if (lock->runcount == 0)
- {
- /* POSIX recommends that "write locks shall take precedence over read
- locks", to avoid "writer starvation". */
- if (lock->waiting_writers_count > 0)
- {
- /* Wake up one of the waiting writers. */
- err = pthread_cond_signal (&lock->waiting_writers);
- if (err != 0)
- {
- pthread_mutex_unlock (&lock->lock);
- return err;
- }
- }
- else
- {
- /* Wake up all waiting readers. */
- err = pthread_cond_broadcast (&lock->waiting_readers);
- if (err != 0)
- {
- pthread_mutex_unlock (&lock->lock);
- return err;
- }
- }
- }
- return pthread_mutex_unlock (&lock->lock);
-}
-
-int
-glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
-{
- int err;
-
- err = pthread_mutex_destroy (&lock->lock);
- if (err != 0)
- return err;
- err = pthread_cond_destroy (&lock->waiting_readers);
- if (err != 0)
- return err;
- err = pthread_cond_destroy (&lock->waiting_writers);
- if (err != 0)
- return err;
- return 0;
-}
-
-# endif
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-# if HAVE_PTHREAD_MUTEX_RECURSIVE
-
-# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
-
-int
-glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
-{
- pthread_mutexattr_t attributes;
- int err;
-
- err = pthread_mutexattr_init (&attributes);
- if (err != 0)
- return err;
- err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
- if (err != 0)
- {
- pthread_mutexattr_destroy (&attributes);
- return err;
- }
- err = pthread_mutex_init (lock, &attributes);
- if (err != 0)
- {
- pthread_mutexattr_destroy (&attributes);
- return err;
- }
- err = pthread_mutexattr_destroy (&attributes);
- if (err != 0)
- return err;
- return 0;
-}
-
-# else
-
-int
-glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
-{
- pthread_mutexattr_t attributes;
- int err;
-
- err = pthread_mutexattr_init (&attributes);
- if (err != 0)
- return err;
- err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
- if (err != 0)
- {
- pthread_mutexattr_destroy (&attributes);
- return err;
- }
- err = pthread_mutex_init (&lock->recmutex, &attributes);
- if (err != 0)
- {
- pthread_mutexattr_destroy (&attributes);
- return err;
- }
- err = pthread_mutexattr_destroy (&attributes);
- if (err != 0)
- return err;
- lock->initialized = 1;
- return 0;
-}
-
-int
-glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
-{
- if (!lock->initialized)
- {
- int err;
-
- err = pthread_mutex_lock (&lock->guard);
- if (err != 0)
- return err;
- if (!lock->initialized)
- {
- err = glthread_recursive_lock_init_multithreaded (lock);
- if (err != 0)
- {
- pthread_mutex_unlock (&lock->guard);
- return err;
- }
- }
- err = pthread_mutex_unlock (&lock->guard);
- if (err != 0)
- return err;
- }
- return pthread_mutex_lock (&lock->recmutex);
-}
-
-int
-glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
-{
- if (!lock->initialized)
- return EINVAL;
- return pthread_mutex_unlock (&lock->recmutex);
-}
-
-int
-glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
-{
- int err;
-
- if (!lock->initialized)
- return EINVAL;
- err = pthread_mutex_destroy (&lock->recmutex);
- if (err != 0)
- return err;
- lock->initialized = 0;
- return 0;
-}
-
-# endif
-
-# else
-
-int
-glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
-{
- int err;
-
- err = pthread_mutex_init (&lock->mutex, NULL);
- if (err != 0)
- return err;
- lock->owner = (pthread_t) 0;
- lock->depth = 0;
- return 0;
-}
-
-int
-glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
-{
- pthread_t self = pthread_self ();
- if (lock->owner != self)
- {
- int err;
-
- err = pthread_mutex_lock (&lock->mutex);
- if (err != 0)
- return err;
- lock->owner = self;
- }
- if (++(lock->depth) == 0) /* wraparound? */
- {
- lock->depth--;
- return EAGAIN;
- }
- return 0;
-}
-
-int
-glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
-{
- if (lock->owner != pthread_self ())
- return EPERM;
- if (lock->depth == 0)
- return EINVAL;
- if (--(lock->depth) == 0)
- {
- lock->owner = (pthread_t) 0;
- return pthread_mutex_unlock (&lock->mutex);
- }
- else
- return 0;
-}
-
-int
-glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
-{
- if (lock->owner != (pthread_t) 0)
- return EBUSY;
- return pthread_mutex_destroy (&lock->mutex);
-}
-
-# endif
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT;
-
-int
-glthread_once_singlethreaded (pthread_once_t *once_control)
-{
- /* We don't know whether pthread_once_t is an integer type, a floating-point
- type, a pointer type, or a structure type. */
- char *firstbyte = (char *)once_control;
- if (*firstbyte == *(const char *)&fresh_once)
- {
- /* First time use of once_control. Invert the first byte. */
- *firstbyte = ~ *(const char *)&fresh_once;
- return 1;
- }
- else
- return 0;
-}
-
-# if !(PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK)
-
-int
-glthread_once_multithreaded (pthread_once_t *once_control,
- void (*init_function) (void))
-{
- int err = pthread_once (once_control, init_function);
- if (err == ENOSYS)
- {
- /* This happens on FreeBSD 11: The pthread_once function in libc returns
- ENOSYS. */
- if (glthread_once_singlethreaded (once_control))
- init_function ();
- return 0;
- }
- return err;
-}
-
-# endif
-
-#endif
-
-/* ========================================================================= */
-
-#if USE_WINDOWS_THREADS
-
-#endif
-
-/* ========================================================================= */
+++ /dev/null
-/* Locking in multithreaded situations.
- Copyright (C) 2005-2008, 2017-2020 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */
-
-/* This file contains locking primitives for use with a given thread library.
- It does not contain primitives for creating threads or for other
- synchronization primitives.
-
- Normal (non-recursive) locks:
- Type: gl_lock_t
- Declaration: gl_lock_define(extern, name)
- Initializer: gl_lock_define_initialized(, name)
- Initialization: gl_lock_init (name);
- Taking the lock: gl_lock_lock (name);
- Releasing the lock: gl_lock_unlock (name);
- De-initialization: gl_lock_destroy (name);
- Equivalent functions with control of error handling:
- Initialization: err = glthread_lock_init (&name);
- Taking the lock: err = glthread_lock_lock (&name);
- Releasing the lock: err = glthread_lock_unlock (&name);
- De-initialization: err = glthread_lock_destroy (&name);
-
- Read-Write (non-recursive) locks:
- Type: gl_rwlock_t
- Declaration: gl_rwlock_define(extern, name)
- Initializer: gl_rwlock_define_initialized(, name)
- Initialization: gl_rwlock_init (name);
- Taking the lock: gl_rwlock_rdlock (name);
- gl_rwlock_wrlock (name);
- Releasing the lock: gl_rwlock_unlock (name);
- De-initialization: gl_rwlock_destroy (name);
- Equivalent functions with control of error handling:
- Initialization: err = glthread_rwlock_init (&name);
- Taking the lock: err = glthread_rwlock_rdlock (&name);
- err = glthread_rwlock_wrlock (&name);
- Releasing the lock: err = glthread_rwlock_unlock (&name);
- De-initialization: err = glthread_rwlock_destroy (&name);
-
- Recursive locks:
- Type: gl_recursive_lock_t
- Declaration: gl_recursive_lock_define(extern, name)
- Initializer: gl_recursive_lock_define_initialized(, name)
- Initialization: gl_recursive_lock_init (name);
- Taking the lock: gl_recursive_lock_lock (name);
- Releasing the lock: gl_recursive_lock_unlock (name);
- De-initialization: gl_recursive_lock_destroy (name);
- Equivalent functions with control of error handling:
- Initialization: err = glthread_recursive_lock_init (&name);
- Taking the lock: err = glthread_recursive_lock_lock (&name);
- Releasing the lock: err = glthread_recursive_lock_unlock (&name);
- De-initialization: err = glthread_recursive_lock_destroy (&name);
-
- Once-only execution:
- Type: gl_once_t
- Initializer: gl_once_define(extern, name)
- Execution: gl_once (name, initfunction);
- Equivalent functions with control of error handling:
- Execution: err = glthread_once (&name, initfunction);
-*/
-
-
-#ifndef _LOCK_H
-#define _LOCK_H
-
-#include <errno.h>
-#include <stdlib.h>
-
-#if !defined c11_threads_in_use
-# if HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
-# include <threads.h>
-# pragma weak thrd_exit
-# define c11_threads_in_use() (thrd_exit != NULL)
-# else
-# define c11_threads_in_use() 0
-# endif
-#endif
-
-/* ========================================================================= */
-
-#if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
-
-/* Use the ISO C threads library. */
-
-# include <threads.h>
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-typedef struct
- {
- int volatile init_needed;
- once_flag init_once;
- void (*init_func) (void);
- mtx_t mutex;
- }
- gl_lock_t;
-# define gl_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_lock_t NAME;
-# define gl_lock_define_initialized(STORAGECLASS, NAME) \
- static void _atomic_init_##NAME (void); \
- STORAGECLASS gl_lock_t NAME = \
- { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
- static void _atomic_init_##NAME (void) \
- { \
- if (glthread_lock_init (&(NAME))) \
- abort (); \
- }
-extern int glthread_lock_init (gl_lock_t *lock);
-extern int glthread_lock_lock (gl_lock_t *lock);
-extern int glthread_lock_unlock (gl_lock_t *lock);
-extern int glthread_lock_destroy (gl_lock_t *lock);
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-typedef struct
- {
- int volatile init_needed;
- once_flag init_once;
- void (*init_func) (void);
- mtx_t lock; /* protects the remaining fields */
- cnd_t waiting_readers; /* waiting readers */
- cnd_t waiting_writers; /* waiting writers */
- unsigned int waiting_writers_count; /* number of waiting writers */
- int runcount; /* number of readers running, or -1 when a writer runs */
- }
- gl_rwlock_t;
-# define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME;
-# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- static void _atomic_init_##NAME (void); \
- STORAGECLASS gl_rwlock_t NAME = \
- { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
- static void _atomic_init_##NAME (void) \
- { \
- if (glthread_rwlock_init (&(NAME))) \
- abort (); \
- }
-extern int glthread_rwlock_init (gl_rwlock_t *lock);
-extern int glthread_rwlock_rdlock (gl_rwlock_t *lock);
-extern int glthread_rwlock_wrlock (gl_rwlock_t *lock);
-extern int glthread_rwlock_unlock (gl_rwlock_t *lock);
-extern int glthread_rwlock_destroy (gl_rwlock_t *lock);
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-typedef struct
- {
- int volatile init_needed;
- once_flag init_once;
- void (*init_func) (void);
- mtx_t mutex;
- }
- gl_recursive_lock_t;
-# define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME;
-# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- static void _atomic_init_##NAME (void); \
- STORAGECLASS gl_recursive_lock_t NAME = \
- { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
- static void _atomic_init_##NAME (void) \
- { \
- if (glthread_recursive_lock_init (&(NAME))) \
- abort (); \
- }
-extern int glthread_recursive_lock_init (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-typedef once_flag gl_once_t;
-# define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS once_flag NAME = ONCE_FLAG_INIT;
-# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
- (call_once (ONCE_CONTROL, INITFUNCTION), 0)
-
-# ifdef __cplusplus
-}
-# endif
-
-#endif
-
-/* ========================================================================= */
-
-#if USE_POSIX_THREADS
-
-/* Use the POSIX threads library. */
-
-# include <pthread.h>
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-# if PTHREAD_IN_USE_DETECTION_HARD
-
-/* The pthread_in_use() detection needs to be done at runtime. */
-# define pthread_in_use() \
- glthread_in_use ()
-extern int glthread_in_use (void);
-
-# endif
-
-# if USE_POSIX_THREADS_WEAK
-
-/* Use weak references to the POSIX threads library. */
-
-/* Weak references avoid dragging in external libraries if the other parts
- of the program don't use them. Here we use them, because we don't want
- every program that uses libintl to depend on libpthread. This assumes
- that libpthread would not be loaded after libintl; i.e. if libintl is
- loaded first, by an executable that does not depend on libpthread, and
- then a module is dynamically loaded that depends on libpthread, libintl
- will not be multithread-safe. */
-
-/* The way to test at runtime whether libpthread is present is to test
- whether a function pointer's value, such as &pthread_mutex_init, is
- non-NULL. However, some versions of GCC have a bug through which, in
- PIC mode, &foo != NULL always evaluates to true if there is a direct
- call to foo(...) in the same function. To avoid this, we test the
- address of a function in libpthread that we don't use. */
-
-# pragma weak pthread_mutex_init
-# pragma weak pthread_mutex_lock
-# pragma weak pthread_mutex_unlock
-# pragma weak pthread_mutex_destroy
-# pragma weak pthread_rwlock_init
-# pragma weak pthread_rwlock_rdlock
-# pragma weak pthread_rwlock_wrlock
-# pragma weak pthread_rwlock_unlock
-# pragma weak pthread_rwlock_destroy
-# pragma weak pthread_once
-# pragma weak pthread_cond_init
-# pragma weak pthread_cond_wait
-# pragma weak pthread_cond_signal
-# pragma weak pthread_cond_broadcast
-# pragma weak pthread_cond_destroy
-# pragma weak pthread_mutexattr_init
-# pragma weak pthread_mutexattr_settype
-# pragma weak pthread_mutexattr_destroy
-# pragma weak pthread_rwlockattr_init
-# if __GNU_LIBRARY__ > 1
-# pragma weak pthread_rwlockattr_setkind_np
-# endif
-# pragma weak pthread_rwlockattr_destroy
-# ifndef pthread_self
-# pragma weak pthread_self
-# endif
-
-# if !PTHREAD_IN_USE_DETECTION_HARD
- /* Considering all platforms with USE_POSIX_THREADS_WEAK, only few symbols
- can be used to determine whether libpthread is in use. These are:
- pthread_mutexattr_gettype
- pthread_rwlockattr_destroy
- pthread_rwlockattr_init
- */
-# pragma weak pthread_mutexattr_gettype
-# define pthread_in_use() \
- (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
-# endif
-
-# else
-
-# if !PTHREAD_IN_USE_DETECTION_HARD
-# define pthread_in_use() 1
-# endif
-
-# endif
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-typedef pthread_mutex_t gl_lock_t;
-# define gl_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS pthread_mutex_t NAME;
-# define gl_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
-# define gl_lock_initializer \
- PTHREAD_MUTEX_INITIALIZER
-# define glthread_lock_init(LOCK) \
- (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0)
-# define glthread_lock_lock(LOCK) \
- (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
-# define glthread_lock_unlock(LOCK) \
- (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
-# define glthread_lock_destroy(LOCK) \
- (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
-
-# if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
-
-typedef pthread_rwlock_t gl_rwlock_t;
-# define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS pthread_rwlock_t NAME;
-# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
-# if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
-# if defined PTHREAD_RWLOCK_INITIALIZER
-# define gl_rwlock_initializer \
- PTHREAD_RWLOCK_INITIALIZER
-# else
-# define gl_rwlock_initializer \
- PTHREAD_RWLOCK_INITIALIZER_NP
-# endif
-# define glthread_rwlock_init(LOCK) \
- (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
-# else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
-# define gl_rwlock_initializer \
- PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
-# define glthread_rwlock_init(LOCK) \
- (pthread_in_use () ? glthread_rwlock_init_for_glibc (LOCK) : 0)
-extern int glthread_rwlock_init_for_glibc (pthread_rwlock_t *lock);
-# endif
-# define glthread_rwlock_rdlock(LOCK) \
- (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
-# define glthread_rwlock_wrlock(LOCK) \
- (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0)
-# define glthread_rwlock_unlock(LOCK) \
- (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0)
-# define glthread_rwlock_destroy(LOCK) \
- (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0)
-
-# else
-
-typedef struct
- {
- int initialized;
- pthread_mutex_t guard; /* protects the initialization */
- pthread_rwlock_t rwlock; /* read-write lock */
- }
- gl_rwlock_t;
-# define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME;
-# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
-# define gl_rwlock_initializer \
- { 0, PTHREAD_MUTEX_INITIALIZER }
-# define glthread_rwlock_init(LOCK) \
- (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
-# define glthread_rwlock_rdlock(LOCK) \
- (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
-# define glthread_rwlock_wrlock(LOCK) \
- (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
-# define glthread_rwlock_unlock(LOCK) \
- (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
-# define glthread_rwlock_destroy(LOCK) \
- (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
-extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
-
-# endif
-
-# else
-
-typedef struct
- {
- pthread_mutex_t lock; /* protects the remaining fields */
- pthread_cond_t waiting_readers; /* waiting readers */
- pthread_cond_t waiting_writers; /* waiting writers */
- unsigned int waiting_writers_count; /* number of waiting writers */
- int runcount; /* number of readers running, or -1 when a writer runs */
- }
- gl_rwlock_t;
-# define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME;
-# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
-# define gl_rwlock_initializer \
- { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
-# define glthread_rwlock_init(LOCK) \
- (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
-# define glthread_rwlock_rdlock(LOCK) \
- (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
-# define glthread_rwlock_wrlock(LOCK) \
- (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
-# define glthread_rwlock_unlock(LOCK) \
- (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
-# define glthread_rwlock_destroy(LOCK) \
- (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
-extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
-
-# endif
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-# if HAVE_PTHREAD_MUTEX_RECURSIVE
-
-# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
-
-typedef pthread_mutex_t gl_recursive_lock_t;
-# define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS pthread_mutex_t NAME;
-# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
-# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
-# define gl_recursive_lock_initializer \
- PTHREAD_RECURSIVE_MUTEX_INITIALIZER
-# else
-# define gl_recursive_lock_initializer \
- PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
-# endif
-# define glthread_recursive_lock_init(LOCK) \
- (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_lock(LOCK) \
- (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
-# define glthread_recursive_lock_unlock(LOCK) \
- (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
-# define glthread_recursive_lock_destroy(LOCK) \
- (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
-extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
-
-# else
-
-typedef struct
- {
- pthread_mutex_t recmutex; /* recursive mutex */
- pthread_mutex_t guard; /* protects the initialization */
- int initialized;
- }
- gl_recursive_lock_t;
-# define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME;
-# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
-# define gl_recursive_lock_initializer \
- { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
-# define glthread_recursive_lock_init(LOCK) \
- (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_lock(LOCK) \
- (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_unlock(LOCK) \
- (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_destroy(LOCK) \
- (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
-extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
-
-# endif
-
-# else
-
-/* Old versions of POSIX threads on Solaris did not have recursive locks.
- We have to implement them ourselves. */
-
-typedef struct
- {
- pthread_mutex_t mutex;
- pthread_t owner;
- unsigned long depth;
- }
- gl_recursive_lock_t;
-# define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME;
-# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
-# define gl_recursive_lock_initializer \
- { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
-# define glthread_recursive_lock_init(LOCK) \
- (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_lock(LOCK) \
- (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_unlock(LOCK) \
- (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_destroy(LOCK) \
- (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
-extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
-
-# endif
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-typedef pthread_once_t gl_once_t;
-# define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
-# if PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK
-# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
- (pthread_in_use () \
- ? pthread_once (ONCE_CONTROL, INITFUNCTION) \
- : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
-# else
-# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
- (pthread_in_use () \
- ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
- : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
-extern int glthread_once_multithreaded (pthread_once_t *once_control,
- void (*init_function) (void));
-# endif
-extern int glthread_once_singlethreaded (pthread_once_t *once_control);
-
-# ifdef __cplusplus
-}
-# endif
-
-#endif
-
-/* ========================================================================= */
-
-#if USE_WINDOWS_THREADS
-
-# define WIN32_LEAN_AND_MEAN /* avoid including junk */
-# include <windows.h>
-
-# include "windows-mutex.h"
-# include "windows-rwlock.h"
-# include "windows-recmutex.h"
-# include "windows-once.h"
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-/* We can use CRITICAL_SECTION directly, rather than the native Windows Event,
- Mutex, Semaphore types, because
- - we need only to synchronize inside a single process (address space),
- not inter-process locking,
- - we don't need to support trylock operations. (TryEnterCriticalSection
- does not work on Windows 95/98/ME. Packages that need trylock usually
- define their own mutex type.) */
-
-/* There is no way to statically initialize a CRITICAL_SECTION. It needs
- to be done lazily, once only. For this we need spinlocks. */
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-typedef glwthread_mutex_t gl_lock_t;
-# define gl_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_lock_t NAME;
-# define gl_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
-# define gl_lock_initializer \
- GLWTHREAD_MUTEX_INIT
-# define glthread_lock_init(LOCK) \
- (glwthread_mutex_init (LOCK), 0)
-# define glthread_lock_lock(LOCK) \
- glwthread_mutex_lock (LOCK)
-# define glthread_lock_unlock(LOCK) \
- glwthread_mutex_unlock (LOCK)
-# define glthread_lock_destroy(LOCK) \
- glwthread_mutex_destroy (LOCK)
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-typedef glwthread_rwlock_t gl_rwlock_t;
-# define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME;
-# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
-# define gl_rwlock_initializer \
- GLWTHREAD_RWLOCK_INIT
-# define glthread_rwlock_init(LOCK) \
- (glwthread_rwlock_init (LOCK), 0)
-# define glthread_rwlock_rdlock(LOCK) \
- glwthread_rwlock_rdlock (LOCK)
-# define glthread_rwlock_wrlock(LOCK) \
- glwthread_rwlock_wrlock (LOCK)
-# define glthread_rwlock_unlock(LOCK) \
- glwthread_rwlock_unlock (LOCK)
-# define glthread_rwlock_destroy(LOCK) \
- glwthread_rwlock_destroy (LOCK)
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-typedef glwthread_recmutex_t gl_recursive_lock_t;
-# define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME;
-# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
-# define gl_recursive_lock_initializer \
- GLWTHREAD_RECMUTEX_INIT
-# define glthread_recursive_lock_init(LOCK) \
- (glwthread_recmutex_init (LOCK), 0)
-# define glthread_recursive_lock_lock(LOCK) \
- glwthread_recmutex_lock (LOCK)
-# define glthread_recursive_lock_unlock(LOCK) \
- glwthread_recmutex_unlock (LOCK)
-# define glthread_recursive_lock_destroy(LOCK) \
- glwthread_recmutex_destroy (LOCK)
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-typedef glwthread_once_t gl_once_t;
-# define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
-# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
- (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
-
-# ifdef __cplusplus
-}
-# endif
-
-#endif
-
-/* ========================================================================= */
-
-#if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
-
-/* Provide dummy implementation if threads are not supported. */
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-typedef int gl_lock_t;
-# define gl_lock_define(STORAGECLASS, NAME)
-# define gl_lock_define_initialized(STORAGECLASS, NAME)
-# define glthread_lock_init(NAME) 0
-# define glthread_lock_lock(NAME) 0
-# define glthread_lock_unlock(NAME) 0
-# define glthread_lock_destroy(NAME) 0
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-typedef int gl_rwlock_t;
-# define gl_rwlock_define(STORAGECLASS, NAME)
-# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
-# define glthread_rwlock_init(NAME) 0
-# define glthread_rwlock_rdlock(NAME) 0
-# define glthread_rwlock_wrlock(NAME) 0
-# define glthread_rwlock_unlock(NAME) 0
-# define glthread_rwlock_destroy(NAME) 0
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-typedef int gl_recursive_lock_t;
-# define gl_recursive_lock_define(STORAGECLASS, NAME)
-# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
-# define glthread_recursive_lock_init(NAME) 0
-# define glthread_recursive_lock_lock(NAME) 0
-# define glthread_recursive_lock_unlock(NAME) 0
-# define glthread_recursive_lock_destroy(NAME) 0
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-typedef int gl_once_t;
-# define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_once_t NAME = 0;
-# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
- (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
-
-#endif
-
-/* ========================================================================= */
-
-/* Macros with built-in error handling. */
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-#define gl_lock_init(NAME) \
- do \
- { \
- if (glthread_lock_init (&NAME)) \
- abort (); \
- } \
- while (0)
-#define gl_lock_lock(NAME) \
- do \
- { \
- if (glthread_lock_lock (&NAME)) \
- abort (); \
- } \
- while (0)
-#define gl_lock_unlock(NAME) \
- do \
- { \
- if (glthread_lock_unlock (&NAME)) \
- abort (); \
- } \
- while (0)
-#define gl_lock_destroy(NAME) \
- do \
- { \
- if (glthread_lock_destroy (&NAME)) \
- abort (); \
- } \
- while (0)
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-#define gl_rwlock_init(NAME) \
- do \
- { \
- if (glthread_rwlock_init (&NAME)) \
- abort (); \
- } \
- while (0)
-#define gl_rwlock_rdlock(NAME) \
- do \
- { \
- if (glthread_rwlock_rdlock (&NAME)) \
- abort (); \
- } \
- while (0)
-#define gl_rwlock_wrlock(NAME) \
- do \
- { \
- if (glthread_rwlock_wrlock (&NAME)) \
- abort (); \
- } \
- while (0)
-#define gl_rwlock_unlock(NAME) \
- do \
- { \
- if (glthread_rwlock_unlock (&NAME)) \
- abort (); \
- } \
- while (0)
-#define gl_rwlock_destroy(NAME) \
- do \
- { \
- if (glthread_rwlock_destroy (&NAME)) \
- abort (); \
- } \
- while (0)
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-#define gl_recursive_lock_init(NAME) \
- do \
- { \
- if (glthread_recursive_lock_init (&NAME)) \
- abort (); \
- } \
- while (0)
-#define gl_recursive_lock_lock(NAME) \
- do \
- { \
- if (glthread_recursive_lock_lock (&NAME)) \
- abort (); \
- } \
- while (0)
-#define gl_recursive_lock_unlock(NAME) \
- do \
- { \
- if (glthread_recursive_lock_unlock (&NAME)) \
- abort (); \
- } \
- while (0)
-#define gl_recursive_lock_destroy(NAME) \
- do \
- { \
- if (glthread_recursive_lock_destroy (&NAME)) \
- abort (); \
- } \
- while (0)
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-#define gl_once(NAME, INITFUNCTION) \
- do \
- { \
- if (glthread_once (&NAME, INITFUNCTION)) \
- abort (); \
- } \
- while (0)
-
-/* ========================================================================= */
-
-#endif /* _LOCK_H */
/* Log file output.
- Copyright (C) 2003, 2005, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005, 2009, 2021 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
#ifdef _LIBC
# include <bits/libc-lock.h>
#else
-# include "lock.h"
+# include "glthread/lock.h"
#endif
/* Separator between msgctxt and msgid in .mo files. */
/* Expression parsing and evaluation for plural form selection.
- Copyright (C) 2000-2016, 2019 Free Software Foundation, Inc.
+ Copyright (C) 2000-2016, 2019, 2021 Free Software Foundation, Inc.
Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
This program is free software: you can redistribute it and/or modify
# define GERMANIC_PLURAL __gettext_germanic_plural
# define EXTRACT_PLURAL_EXPRESSION __gettext_extract_plural
#elif defined (IN_LIBINTL)
-# define FREE_EXPRESSION libintl_gettext_free_exp
-# define PLURAL_PARSE libintl_gettextparse
-# define GERMANIC_PLURAL libintl_gettext_germanic_plural
-# define EXTRACT_PLURAL_EXPRESSION libintl_gettext_extract_plural
+# define FREE_EXPRESSION _libintl_gettext_free_exp
+# define PLURAL_PARSE _libintl_gettextparse
+# define GERMANIC_PLURAL _libintl_gettext_germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION _libintl_gettext_extract_plural
#else
# define FREE_EXPRESSION free_plural_expression
# define PLURAL_PARSE parse_plural_expression
+++ /dev/null
-/* Decomposed printf argument list.
- Copyright (C) 1999, 2002-2003, 2005-2007 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* This file can be parametrized with the following macros:
- ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions.
- PRINTF_FETCHARGS Name of the function to be defined.
- STATIC Set to 'static' to declare the function static. */
-
-#ifndef PRINTF_FETCHARGS
-# include <config.h>
-#endif
-
-/* Specification. */
-#ifndef PRINTF_FETCHARGS
-# include "printf-args.h"
-#endif
-
-#ifdef STATIC
-STATIC
-#endif
-int
-PRINTF_FETCHARGS (va_list args, arguments *a)
-{
- size_t i;
- argument *ap;
-
- for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
- switch (ap->type)
- {
- case TYPE_SCHAR:
- ap->a.a_schar = va_arg (args, /*signed char*/ int);
- break;
- case TYPE_UCHAR:
- ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
- break;
- case TYPE_SHORT:
- ap->a.a_short = va_arg (args, /*short*/ int);
- break;
- case TYPE_USHORT:
- ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
- break;
- case TYPE_INT:
- ap->a.a_int = va_arg (args, int);
- break;
- case TYPE_UINT:
- ap->a.a_uint = va_arg (args, unsigned int);
- break;
- case TYPE_LONGINT:
- ap->a.a_longint = va_arg (args, long int);
- break;
- case TYPE_ULONGINT:
- ap->a.a_ulongint = va_arg (args, unsigned long int);
- break;
-#if HAVE_LONG_LONG_INT
- case TYPE_LONGLONGINT:
- ap->a.a_longlongint = va_arg (args, long long int);
- break;
- case TYPE_ULONGLONGINT:
- ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
- break;
-#endif
- case TYPE_DOUBLE:
- ap->a.a_double = va_arg (args, double);
- break;
- case TYPE_LONGDOUBLE:
- ap->a.a_longdouble = va_arg (args, long double);
- break;
- case TYPE_CHAR:
- ap->a.a_char = va_arg (args, int);
- break;
-#if HAVE_WINT_T
- case TYPE_WIDE_CHAR:
- /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by
- default argument promotions", this is not the case in mingw32,
- where wint_t is 'unsigned short'. */
- ap->a.a_wide_char =
- (sizeof (wint_t) < sizeof (int)
- ? va_arg (args, int)
- : va_arg (args, wint_t));
- break;
-#endif
- case TYPE_STRING:
- ap->a.a_string = va_arg (args, const char *);
- /* A null pointer is an invalid argument for "%s", but in practice
- it occurs quite frequently in printf statements that produce
- debug output. Use a fallback in this case. */
- if (ap->a.a_string == NULL)
- ap->a.a_string = "(NULL)";
- break;
-#if HAVE_WCHAR_T
- case TYPE_WIDE_STRING:
- ap->a.a_wide_string = va_arg (args, const wchar_t *);
- /* A null pointer is an invalid argument for "%ls", but in practice
- it occurs quite frequently in printf statements that produce
- debug output. Use a fallback in this case. */
- if (ap->a.a_wide_string == NULL)
- {
- static const wchar_t wide_null_string[] =
- {
- (wchar_t)'(',
- (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L',
- (wchar_t)')',
- (wchar_t)0
- };
- ap->a.a_wide_string = wide_null_string;
- }
- break;
-#endif
- case TYPE_POINTER:
- ap->a.a_pointer = va_arg (args, void *);
- break;
- case TYPE_COUNT_SCHAR_POINTER:
- ap->a.a_count_schar_pointer = va_arg (args, signed char *);
- break;
- case TYPE_COUNT_SHORT_POINTER:
- ap->a.a_count_short_pointer = va_arg (args, short *);
- break;
- case TYPE_COUNT_INT_POINTER:
- ap->a.a_count_int_pointer = va_arg (args, int *);
- break;
- case TYPE_COUNT_LONGINT_POINTER:
- ap->a.a_count_longint_pointer = va_arg (args, long int *);
- break;
-#if HAVE_LONG_LONG_INT
- case TYPE_COUNT_LONGLONGINT_POINTER:
- ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
- break;
-#endif
-#if ENABLE_UNISTDIO
- /* The unistdio extensions. */
- case TYPE_U8_STRING:
- ap->a.a_u8_string = va_arg (args, const uint8_t *);
- /* A null pointer is an invalid argument for "%U", but in practice
- it occurs quite frequently in printf statements that produce
- debug output. Use a fallback in this case. */
- if (ap->a.a_u8_string == NULL)
- {
- static const uint8_t u8_null_string[] =
- { '(', 'N', 'U', 'L', 'L', ')', 0 };
- ap->a.a_u8_string = u8_null_string;
- }
- break;
- case TYPE_U16_STRING:
- ap->a.a_u16_string = va_arg (args, const uint16_t *);
- /* A null pointer is an invalid argument for "%lU", but in practice
- it occurs quite frequently in printf statements that produce
- debug output. Use a fallback in this case. */
- if (ap->a.a_u16_string == NULL)
- {
- static const uint16_t u16_null_string[] =
- { '(', 'N', 'U', 'L', 'L', ')', 0 };
- ap->a.a_u16_string = u16_null_string;
- }
- break;
- case TYPE_U32_STRING:
- ap->a.a_u32_string = va_arg (args, const uint32_t *);
- /* A null pointer is an invalid argument for "%llU", but in practice
- it occurs quite frequently in printf statements that produce
- debug output. Use a fallback in this case. */
- if (ap->a.a_u32_string == NULL)
- {
- static const uint32_t u32_null_string[] =
- { '(', 'N', 'U', 'L', 'L', ')', 0 };
- ap->a.a_u32_string = u32_null_string;
- }
- break;
-#endif
- default:
- /* Unknown type. */
- return -1;
- }
- return 0;
-}
+++ /dev/null
-/* Decomposed printf argument list.
- Copyright (C) 1999, 2002-2003, 2006-2007, 2011 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-#ifndef _PRINTF_ARGS_H
-#define _PRINTF_ARGS_H
-
-/* This file can be parametrized with the following macros:
- ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions.
- PRINTF_FETCHARGS Name of the function to be declared.
- STATIC Set to 'static' to declare the function static. */
-
-/* Default parameters. */
-#ifndef PRINTF_FETCHARGS
-# define PRINTF_FETCHARGS printf_fetchargs
-#endif
-
-/* Get size_t. */
-#include <stddef.h>
-
-/* Get wchar_t. */
-#if HAVE_WCHAR_T
-# include <stddef.h>
-#endif
-
-/* Get wint_t. */
-#if HAVE_WINT_T
-# include <wchar.h>
-#endif
-
-/* Get va_list. */
-#include <stdarg.h>
-
-
-/* Argument types */
-typedef enum
-{
- TYPE_NONE,
- TYPE_SCHAR,
- TYPE_UCHAR,
- TYPE_SHORT,
- TYPE_USHORT,
- TYPE_INT,
- TYPE_UINT,
- TYPE_LONGINT,
- TYPE_ULONGINT,
-#if HAVE_LONG_LONG_INT
- TYPE_LONGLONGINT,
- TYPE_ULONGLONGINT,
-#endif
- TYPE_DOUBLE,
- TYPE_LONGDOUBLE,
- TYPE_CHAR,
-#if HAVE_WINT_T
- TYPE_WIDE_CHAR,
-#endif
- TYPE_STRING,
-#if HAVE_WCHAR_T
- TYPE_WIDE_STRING,
-#endif
- TYPE_POINTER,
- TYPE_COUNT_SCHAR_POINTER,
- TYPE_COUNT_SHORT_POINTER,
- TYPE_COUNT_INT_POINTER,
- TYPE_COUNT_LONGINT_POINTER
-#if HAVE_LONG_LONG_INT
-, TYPE_COUNT_LONGLONGINT_POINTER
-#endif
-#if ENABLE_UNISTDIO
- /* The unistdio extensions. */
-, TYPE_U8_STRING
-, TYPE_U16_STRING
-, TYPE_U32_STRING
-#endif
-} arg_type;
-
-/* Polymorphic argument */
-typedef struct
-{
- arg_type type;
- union
- {
- signed char a_schar;
- unsigned char a_uchar;
- short a_short;
- unsigned short a_ushort;
- int a_int;
- unsigned int a_uint;
- long int a_longint;
- unsigned long int a_ulongint;
-#if HAVE_LONG_LONG_INT
- long long int a_longlongint;
- unsigned long long int a_ulonglongint;
-#endif
- float a_float;
- double a_double;
- long double a_longdouble;
- int a_char;
-#if HAVE_WINT_T
- wint_t a_wide_char;
-#endif
- const char* a_string;
-#if HAVE_WCHAR_T
- const wchar_t* a_wide_string;
-#endif
- void* a_pointer;
- signed char * a_count_schar_pointer;
- short * a_count_short_pointer;
- int * a_count_int_pointer;
- long int * a_count_longint_pointer;
-#if HAVE_LONG_LONG_INT
- long long int * a_count_longlongint_pointer;
-#endif
-#if ENABLE_UNISTDIO
- /* The unistdio extensions. */
- const uint8_t * a_u8_string;
- const uint16_t * a_u16_string;
- const uint32_t * a_u32_string;
-#endif
- }
- a;
-}
-argument;
-
-/* Number of directly allocated arguments (no malloc() needed). */
-#define N_DIRECT_ALLOC_ARGUMENTS 7
-
-typedef struct
-{
- size_t count;
- argument *arg;
- argument direct_alloc_arg[N_DIRECT_ALLOC_ARGUMENTS];
-}
-arguments;
-
-
-/* Fetch the arguments, putting them into a. */
-#ifdef STATIC
-STATIC
-#else
-extern
-#endif
-int PRINTF_FETCHARGS (va_list args, arguments *a);
-
-#endif /* _PRINTF_ARGS_H */
+++ /dev/null
-/* Formatted output to strings.
- Copyright (C) 1999-2000, 2002-2003, 2006-2008, 2010-2011, 2018 Free Software
- Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* This file can be parametrized with the following macros:
- CHAR_T The element type of the format string.
- CHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
- in the format string are ASCII.
- DIRECTIVE Structure denoting a format directive.
- Depends on CHAR_T.
- DIRECTIVES Structure denoting the set of format directives of a
- format string. Depends on CHAR_T.
- PRINTF_PARSE Function that parses a format string.
- Depends on CHAR_T.
- STATIC Set to 'static' to declare the function static.
- ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. */
-
-#ifndef PRINTF_PARSE
-# include <config.h>
-#endif
-
-/* Specification. */
-#ifndef PRINTF_PARSE
-# include "printf-parse.h"
-#endif
-
-/* Default parameters. */
-#ifndef PRINTF_PARSE
-# define PRINTF_PARSE printf_parse
-# define CHAR_T char
-# define DIRECTIVE char_directive
-# define DIRECTIVES char_directives
-#endif
-
-/* Get size_t, NULL. */
-#include <stddef.h>
-
-/* Get intmax_t. */
-#if defined IN_LIBINTL || defined IN_LIBASPRINTF
-# if HAVE_STDINT_H_WITH_UINTMAX
-# include <stdint.h>
-# endif
-# if HAVE_INTTYPES_H_WITH_UINTMAX
-# include <inttypes.h>
-# endif
-#else
-# include <stdint.h>
-#endif
-
-/* malloc(), realloc(), free(). */
-#include <stdlib.h>
-
-/* memcpy(). */
-#include <string.h>
-
-/* errno. */
-#include <errno.h>
-
-/* Checked size_t computations. */
-#include "xsize.h"
-
-#if CHAR_T_ONLY_ASCII
-/* c_isascii(). */
-# include "c-ctype.h"
-#endif
-
-#ifdef STATIC
-STATIC
-#endif
-int
-PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
-{
- const CHAR_T *cp = format; /* pointer into format */
- size_t arg_posn = 0; /* number of regular arguments consumed */
- size_t d_allocated; /* allocated elements of d->dir */
- size_t a_allocated; /* allocated elements of a->arg */
- size_t max_width_length = 0;
- size_t max_precision_length = 0;
-
- d->count = 0;
- d_allocated = N_DIRECT_ALLOC_DIRECTIVES;
- d->dir = d->direct_alloc_dir;
-
- a->count = 0;
- a_allocated = N_DIRECT_ALLOC_ARGUMENTS;
- a->arg = a->direct_alloc_arg;
-
-#define REGISTER_ARG(_index_,_type_) \
- { \
- size_t n = (_index_); \
- if (n >= a_allocated) \
- { \
- size_t memory_size; \
- argument *memory; \
- \
- a_allocated = xtimes (a_allocated, 2); \
- if (a_allocated <= n) \
- a_allocated = xsum (n, 1); \
- memory_size = xtimes (a_allocated, sizeof (argument)); \
- if (size_overflow_p (memory_size)) \
- /* Overflow, would lead to out of memory. */ \
- goto out_of_memory; \
- memory = (argument *) (a->arg != a->direct_alloc_arg \
- ? realloc (a->arg, memory_size) \
- : malloc (memory_size)); \
- if (memory == NULL) \
- /* Out of memory. */ \
- goto out_of_memory; \
- if (a->arg == a->direct_alloc_arg) \
- memcpy (memory, a->arg, a->count * sizeof (argument)); \
- a->arg = memory; \
- } \
- while (a->count <= n) \
- a->arg[a->count++].type = TYPE_NONE; \
- if (a->arg[n].type == TYPE_NONE) \
- a->arg[n].type = (_type_); \
- else if (a->arg[n].type != (_type_)) \
- /* Ambiguous type for positional argument. */ \
- goto error; \
- }
-
- while (*cp != '\0')
- {
- CHAR_T c = *cp++;
- if (c == '%')
- {
- size_t arg_index = ARG_NONE;
- DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */
-
- /* Initialize the next directive. */
- dp->dir_start = cp - 1;
- dp->flags = 0;
- dp->width_start = NULL;
- dp->width_end = NULL;
- dp->width_arg_index = ARG_NONE;
- dp->precision_start = NULL;
- dp->precision_end = NULL;
- dp->precision_arg_index = ARG_NONE;
- dp->arg_index = ARG_NONE;
-
- /* Test for positional argument. */
- if (*cp >= '0' && *cp <= '9')
- {
- const CHAR_T *np;
-
- for (np = cp; *np >= '0' && *np <= '9'; np++)
- ;
- if (*np == '$')
- {
- size_t n = 0;
-
- for (np = cp; *np >= '0' && *np <= '9'; np++)
- n = xsum (xtimes (n, 10), *np - '0');
- if (n == 0)
- /* Positional argument 0. */
- goto error;
- if (size_overflow_p (n))
- /* n too large, would lead to out of memory later. */
- goto error;
- arg_index = n - 1;
- cp = np + 1;
- }
- }
-
- /* Read the flags. */
- for (;;)
- {
- if (*cp == '\'')
- {
- dp->flags |= FLAG_GROUP;
- cp++;
- }
- else if (*cp == '-')
- {
- dp->flags |= FLAG_LEFT;
- cp++;
- }
- else if (*cp == '+')
- {
- dp->flags |= FLAG_SHOWSIGN;
- cp++;
- }
- else if (*cp == ' ')
- {
- dp->flags |= FLAG_SPACE;
- cp++;
- }
- else if (*cp == '#')
- {
- dp->flags |= FLAG_ALT;
- cp++;
- }
- else if (*cp == '0')
- {
- dp->flags |= FLAG_ZERO;
- cp++;
- }
-#if __GLIBC__ >= 2 && !defined __UCLIBC__
- else if (*cp == 'I')
- {
- dp->flags |= FLAG_LOCALIZED;
- cp++;
- }
-#endif
- else
- break;
- }
-
- /* Parse the field width. */
- if (*cp == '*')
- {
- dp->width_start = cp;
- cp++;
- dp->width_end = cp;
- if (max_width_length < 1)
- max_width_length = 1;
-
- /* Test for positional argument. */
- if (*cp >= '0' && *cp <= '9')
- {
- const CHAR_T *np;
-
- for (np = cp; *np >= '0' && *np <= '9'; np++)
- ;
- if (*np == '$')
- {
- size_t n = 0;
-
- for (np = cp; *np >= '0' && *np <= '9'; np++)
- n = xsum (xtimes (n, 10), *np - '0');
- if (n == 0)
- /* Positional argument 0. */
- goto error;
- if (size_overflow_p (n))
- /* n too large, would lead to out of memory later. */
- goto error;
- dp->width_arg_index = n - 1;
- cp = np + 1;
- }
- }
- if (dp->width_arg_index == ARG_NONE)
- {
- dp->width_arg_index = arg_posn++;
- if (dp->width_arg_index == ARG_NONE)
- /* arg_posn wrapped around. */
- goto error;
- }
- REGISTER_ARG (dp->width_arg_index, TYPE_INT);
- }
- else if (*cp >= '0' && *cp <= '9')
- {
- size_t width_length;
-
- dp->width_start = cp;
- for (; *cp >= '0' && *cp <= '9'; cp++)
- ;
- dp->width_end = cp;
- width_length = dp->width_end - dp->width_start;
- if (max_width_length < width_length)
- max_width_length = width_length;
- }
-
- /* Parse the precision. */
- if (*cp == '.')
- {
- cp++;
- if (*cp == '*')
- {
- dp->precision_start = cp - 1;
- cp++;
- dp->precision_end = cp;
- if (max_precision_length < 2)
- max_precision_length = 2;
-
- /* Test for positional argument. */
- if (*cp >= '0' && *cp <= '9')
- {
- const CHAR_T *np;
-
- for (np = cp; *np >= '0' && *np <= '9'; np++)
- ;
- if (*np == '$')
- {
- size_t n = 0;
-
- for (np = cp; *np >= '0' && *np <= '9'; np++)
- n = xsum (xtimes (n, 10), *np - '0');
- if (n == 0)
- /* Positional argument 0. */
- goto error;
- if (size_overflow_p (n))
- /* n too large, would lead to out of memory
- later. */
- goto error;
- dp->precision_arg_index = n - 1;
- cp = np + 1;
- }
- }
- if (dp->precision_arg_index == ARG_NONE)
- {
- dp->precision_arg_index = arg_posn++;
- if (dp->precision_arg_index == ARG_NONE)
- /* arg_posn wrapped around. */
- goto error;
- }
- REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
- }
- else
- {
- size_t precision_length;
-
- dp->precision_start = cp - 1;
- for (; *cp >= '0' && *cp <= '9'; cp++)
- ;
- dp->precision_end = cp;
- precision_length = dp->precision_end - dp->precision_start;
- if (max_precision_length < precision_length)
- max_precision_length = precision_length;
- }
- }
-
- {
- arg_type type;
-
- /* Parse argument type/size specifiers. */
- {
- int flags = 0;
-
- for (;;)
- {
- if (*cp == 'h')
- {
- flags |= (1 << (flags & 1));
- cp++;
- }
- else if (*cp == 'L')
- {
- flags |= 4;
- cp++;
- }
- else if (*cp == 'l')
- {
- flags += 8;
- cp++;
- }
- else if (*cp == 'j')
- {
- if (sizeof (intmax_t) > sizeof (long))
- {
- /* intmax_t = long long */
- flags += 16;
- }
- else if (sizeof (intmax_t) > sizeof (int))
- {
- /* intmax_t = long */
- flags += 8;
- }
- cp++;
- }
- else if (*cp == 'z' || *cp == 'Z')
- {
- /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
- because the warning facility in gcc-2.95.2 understands
- only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
- if (sizeof (size_t) > sizeof (long))
- {
- /* size_t = long long */
- flags += 16;
- }
- else if (sizeof (size_t) > sizeof (int))
- {
- /* size_t = long */
- flags += 8;
- }
- cp++;
- }
- else if (*cp == 't')
- {
- if (sizeof (ptrdiff_t) > sizeof (long))
- {
- /* ptrdiff_t = long long */
- flags += 16;
- }
- else if (sizeof (ptrdiff_t) > sizeof (int))
- {
- /* ptrdiff_t = long */
- flags += 8;
- }
- cp++;
- }
-#if defined __APPLE__ && defined __MACH__
- /* On Mac OS X 10.3, PRIdMAX is defined as "qd".
- We cannot change it to "lld" because PRIdMAX must also
- be understood by the system's printf routines. */
- else if (*cp == 'q')
- {
- if (64 / 8 > sizeof (long))
- {
- /* int64_t = long long */
- flags += 16;
- }
- else
- {
- /* int64_t = long */
- flags += 8;
- }
- cp++;
- }
-#endif
-#if defined _WIN32 && ! defined __CYGWIN__
- /* On native Windows, PRIdMAX is defined as "I64d".
- We cannot change it to "lld" because PRIdMAX must also
- be understood by the system's printf routines. */
- else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
- {
- if (64 / 8 > sizeof (long))
- {
- /* __int64 = long long */
- flags += 16;
- }
- else
- {
- /* __int64 = long */
- flags += 8;
- }
- cp += 3;
- }
-#endif
- else
- break;
- }
-
- /* Read the conversion character. */
- c = *cp++;
- switch (c)
- {
- case 'd': case 'i':
-#if HAVE_LONG_LONG_INT
- /* If 'long long' exists and is larger than 'long': */
- if (flags >= 16 || (flags & 4))
- type = TYPE_LONGLONGINT;
- else
-#endif
- /* If 'long long' exists and is the same as 'long', we parse
- "lld" into TYPE_LONGINT. */
- if (flags >= 8)
- type = TYPE_LONGINT;
- else if (flags & 2)
- type = TYPE_SCHAR;
- else if (flags & 1)
- type = TYPE_SHORT;
- else
- type = TYPE_INT;
- break;
- case 'o': case 'u': case 'x': case 'X':
-#if HAVE_LONG_LONG_INT
- /* If 'long long' exists and is larger than 'long': */
- if (flags >= 16 || (flags & 4))
- type = TYPE_ULONGLONGINT;
- else
-#endif
- /* If 'unsigned long long' exists and is the same as
- 'unsigned long', we parse "llu" into TYPE_ULONGINT. */
- if (flags >= 8)
- type = TYPE_ULONGINT;
- else if (flags & 2)
- type = TYPE_UCHAR;
- else if (flags & 1)
- type = TYPE_USHORT;
- else
- type = TYPE_UINT;
- break;
- case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
- case 'a': case 'A':
- if (flags >= 16 || (flags & 4))
- type = TYPE_LONGDOUBLE;
- else
- type = TYPE_DOUBLE;
- break;
- case 'c':
- if (flags >= 8)
-#if HAVE_WINT_T
- type = TYPE_WIDE_CHAR;
-#else
- goto error;
-#endif
- else
- type = TYPE_CHAR;
- break;
-#if HAVE_WINT_T
- case 'C':
- type = TYPE_WIDE_CHAR;
- c = 'c';
- break;
-#endif
- case 's':
- if (flags >= 8)
-#if HAVE_WCHAR_T
- type = TYPE_WIDE_STRING;
-#else
- goto error;
-#endif
- else
- type = TYPE_STRING;
- break;
-#if HAVE_WCHAR_T
- case 'S':
- type = TYPE_WIDE_STRING;
- c = 's';
- break;
-#endif
- case 'p':
- type = TYPE_POINTER;
- break;
- case 'n':
-#if HAVE_LONG_LONG_INT
- /* If 'long long' exists and is larger than 'long': */
- if (flags >= 16 || (flags & 4))
- type = TYPE_COUNT_LONGLONGINT_POINTER;
- else
-#endif
- /* If 'long long' exists and is the same as 'long', we parse
- "lln" into TYPE_COUNT_LONGINT_POINTER. */
- if (flags >= 8)
- type = TYPE_COUNT_LONGINT_POINTER;
- else if (flags & 2)
- type = TYPE_COUNT_SCHAR_POINTER;
- else if (flags & 1)
- type = TYPE_COUNT_SHORT_POINTER;
- else
- type = TYPE_COUNT_INT_POINTER;
- break;
-#if ENABLE_UNISTDIO
- /* The unistdio extensions. */
- case 'U':
- if (flags >= 16)
- type = TYPE_U32_STRING;
- else if (flags >= 8)
- type = TYPE_U16_STRING;
- else
- type = TYPE_U8_STRING;
- break;
-#endif
- case '%':
- type = TYPE_NONE;
- break;
- default:
- /* Unknown conversion character. */
- goto error;
- }
- }
-
- if (type != TYPE_NONE)
- {
- dp->arg_index = arg_index;
- if (dp->arg_index == ARG_NONE)
- {
- dp->arg_index = arg_posn++;
- if (dp->arg_index == ARG_NONE)
- /* arg_posn wrapped around. */
- goto error;
- }
- REGISTER_ARG (dp->arg_index, type);
- }
- dp->conversion = c;
- dp->dir_end = cp;
- }
-
- d->count++;
- if (d->count >= d_allocated)
- {
- size_t memory_size;
- DIRECTIVE *memory;
-
- d_allocated = xtimes (d_allocated, 2);
- memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
- if (size_overflow_p (memory_size))
- /* Overflow, would lead to out of memory. */
- goto out_of_memory;
- memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir
- ? realloc (d->dir, memory_size)
- : malloc (memory_size));
- if (memory == NULL)
- /* Out of memory. */
- goto out_of_memory;
- if (d->dir == d->direct_alloc_dir)
- memcpy (memory, d->dir, d->count * sizeof (DIRECTIVE));
- d->dir = memory;
- }
- }
-#if CHAR_T_ONLY_ASCII
- else if (!c_isascii (c))
- {
- /* Non-ASCII character. Not supported. */
- goto error;
- }
-#endif
- }
- d->dir[d->count].dir_start = cp;
-
- d->max_width_length = max_width_length;
- d->max_precision_length = max_precision_length;
- return 0;
-
-error:
- if (a->arg != a->direct_alloc_arg)
- free (a->arg);
- if (d->dir != d->direct_alloc_dir)
- free (d->dir);
- errno = EINVAL;
- return -1;
-
-out_of_memory:
- if (a->arg != a->direct_alloc_arg)
- free (a->arg);
- if (d->dir != d->direct_alloc_dir)
- free (d->dir);
- errno = ENOMEM;
- return -1;
-}
-
-#undef PRINTF_PARSE
-#undef DIRECTIVES
-#undef DIRECTIVE
-#undef CHAR_T_ONLY_ASCII
-#undef CHAR_T
+++ /dev/null
-/* Parse printf format string.
- Copyright (C) 1999, 2002-2003, 2005, 2007, 2010-2011 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-#ifndef _PRINTF_PARSE_H
-#define _PRINTF_PARSE_H
-
-#if HAVE_FEATURES_H
-# include <features.h> /* for __GLIBC__, __UCLIBC__ */
-#endif
-
-#include "printf-args.h"
-
-
-/* Flags */
-#define FLAG_GROUP 1 /* ' flag */
-#define FLAG_LEFT 2 /* - flag */
-#define FLAG_SHOWSIGN 4 /* + flag */
-#define FLAG_SPACE 8 /* space flag */
-#define FLAG_ALT 16 /* # flag */
-#define FLAG_ZERO 32
-#if __GLIBC__ >= 2 && !defined __UCLIBC__
-# define FLAG_LOCALIZED 64 /* I flag, uses localized digits */
-#endif
-
-/* arg_index value indicating that no argument is consumed. */
-#define ARG_NONE (~(size_t)0)
-
-/* Number of directly allocated directives (no malloc() needed). */
-#define N_DIRECT_ALLOC_DIRECTIVES 7
-
-/* A parsed directive. */
-typedef struct
-{
- const char* dir_start;
- const char* dir_end;
- int flags;
- const char* width_start;
- const char* width_end;
- size_t width_arg_index;
- const char* precision_start;
- const char* precision_end;
- size_t precision_arg_index;
- char conversion; /* d i o u x X f e E g G c s p n U % but not C S */
- size_t arg_index;
-}
-char_directive;
-
-/* A parsed format string. */
-typedef struct
-{
- size_t count;
- char_directive *dir;
- size_t max_width_length;
- size_t max_precision_length;
- char_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES];
-}
-char_directives;
-
-
-/* Parses the format string. Fills in the number N of directives, and fills
- in directives[0], ..., directives[N-1], and sets directives[N].dir_start
- to the end of the format string. Also fills in the arg_type fields of the
- arguments and the needed count of arguments. */
-#ifdef STATIC
-STATIC
-#else
-extern
-#endif
-int printf_parse (const char *format, char_directives *d, arguments *a);
-
-#endif /* _PRINTF_PARSE_H */
/* Formatted output to strings, using POSIX/XSI format strings with positions.
- Copyright (C) 2003, 2006-2007, 2009-2011, 2018, 2020 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006-2007, 2009-2011, 2018, 2020-2021 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software: you can redistribute it and/or modify
# define libintl_printf __printf__
#endif
+#if 0 /* not needed */
+
/* Define auxiliary functions declared in "printf-args.h". */
#include "printf-args.c"
#include "printf-parse.c"
/* Define functions declared in "vasnprintf.h". */
-#define vasnprintf libintl_vasnprintf
+#define vasnprintf _libintl_vasnprintf
#include "vasnprintf.c"
-#if 0 /* not needed */
-#define asnprintf libintl_asnprintf
+#define asnprintf _libintl_asnprintf
#include "asnprintf.c"
+
+#else
+
+/* Get the declaration of _libintl_vasnprintf. */
+#include "vasnprintf.h"
+
#endif
/* Users don't expect libintl_fprintf to be less POSIX compliant
#endif
{
size_t length;
- char *result = libintl_vasnprintf (NULL, &length, format, args);
+ char *result = _libintl_vasnprintf (NULL, &length, format, args);
int retval = -1;
if (result != NULL)
{
#endif
{
size_t length = (size_t) ~0 / (4 * sizeof (char));
- char *result = libintl_vasnprintf (resultbuf, &length, format, args);
+ char *result = _libintl_vasnprintf (resultbuf, &length, format, args);
if (result != resultbuf)
{
free (result);
# endif
{
size_t maxlength = length;
- char *result = libintl_vasnprintf (resultbuf, &length, format, args);
+ char *result = _libintl_vasnprintf (resultbuf, &length, format, args);
if (result == NULL)
return -1;
if (result != resultbuf)
libintl_vasprintf (char **resultp, const char *format, va_list args)
{
size_t length;
- char *result = libintl_vasnprintf (NULL, &length, format, args);
+ char *result = _libintl_vasnprintf (NULL, &length, format, args);
if (result == NULL)
return -1;
if (length > INT_MAX)
#include "printf-parse.c"
/* Define functions declared in "vasnprintf.h". */
-#define vasnwprintf libintl_vasnwprintf
+#define vasnwprintf _libintl_vasnwprintf
#include "vasnprintf.c"
#if 0 /* not needed */
-#define asnwprintf libintl_asnwprintf
+#define asnwprintf _libintl_asnwprintf
#include "asnprintf.c"
#endif
# endif
{
size_t length;
- wchar_t *result = libintl_vasnwprintf (NULL, &length, format, args);
+ wchar_t *result = _libintl_vasnwprintf (NULL, &length, format, args);
int retval = -1;
if (result != NULL)
{
# endif
{
size_t maxlength = length;
- wchar_t *result = libintl_vasnwprintf (resultbuf, &length, format, args);
+ wchar_t *result = _libintl_vasnwprintf (resultbuf, &length, format, args);
if (result == NULL)
return -1;
if (result != resultbuf)
+++ /dev/null
-/* Provide relocatable packages.
- Copyright (C) 2003-2006, 2008-2020 Free Software Foundation, Inc.
- Written by Bruno Haible <bruno@clisp.org>, 2003.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-
-/* Tell glibc's <stdio.h> to provide a prototype for getline().
- This must come before <config.h> because <config.h> may include
- <features.h>, and once <features.h> has been included, it's too late. */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-
-#define _GL_USE_STDLIB_ALLOC 1
-#include <config.h>
-
-/* Specification. */
-#include "relocatable.h"
-
-#if ENABLE_RELOCATABLE
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef NO_XMALLOC
-# define xmalloc malloc
-#else
-# include "xalloc.h"
-#endif
-
-#if defined _WIN32 && !defined __CYGWIN__
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-#endif
-
-#ifdef __EMX__
-# define INCL_DOS
-# include <os2.h>
-
-# define strcmp stricmp
-# define strncmp strnicmp
-#endif
-
-#if DEPENDS_ON_LIBCHARSET
-# include <libcharset.h>
-#endif
-#if DEPENDS_ON_LIBICONV && HAVE_ICONV
-# include <iconv.h>
-#endif
-#if DEPENDS_ON_LIBINTL && ENABLE_NLS
-# include <libintl.h>
-#endif
-
-#if defined _WIN32 && !defined __CYGWIN__
-/* Don't assume that UNICODE is not defined. */
-# undef GetModuleFileName
-# define GetModuleFileName GetModuleFileNameA
-#endif
-
-/* Faked cheap 'bool'. */
-#undef bool
-#undef false
-#undef true
-#define bool int
-#define false 0
-#define true 1
-
-/* Pathname support.
- ISSLASH(C) tests whether C is a directory separator character.
- IS_FILE_NAME_WITH_DIR(P) tests whether P contains a directory specification.
- */
-#if (defined _WIN32 && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
- /* Native Windows, OS/2, DOS */
-# define ISSLASH(C) ((C) == '/' || (C) == '\\')
-# define HAS_DEVICE(P) \
- ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
- && (P)[1] == ':')
-# define IS_FILE_NAME_WITH_DIR(P) \
- (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
-# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
-#else
- /* Unix */
-# define ISSLASH(C) ((C) == '/')
-# define IS_FILE_NAME_WITH_DIR(P) (strchr (P, '/') != NULL)
-# define FILE_SYSTEM_PREFIX_LEN(P) 0
-#endif
-
-/* Whether to enable the more costly support for relocatable libraries.
- It allows libraries to be have been installed with a different original
- prefix than the program. But it is quite costly, especially on Cygwin
- platforms, see below. Therefore we enable it by default only on native
- Windows platforms. */
-#ifndef ENABLE_COSTLY_RELOCATABLE
-# if defined _WIN32 && !defined __CYGWIN__
-# define ENABLE_COSTLY_RELOCATABLE 1
-# else
-# define ENABLE_COSTLY_RELOCATABLE 0
-# endif
-#endif
-
-/* Original installation prefix. */
-static char *orig_prefix;
-static size_t orig_prefix_len;
-/* Current installation prefix. */
-static char *curr_prefix;
-static size_t curr_prefix_len;
-/* These prefixes do not end in a slash. Anything that will be concatenated
- to them must start with a slash. */
-
-/* Sets the original and the current installation prefix of this module.
- Relocation simply replaces a pathname starting with the original prefix
- by the corresponding pathname with the current prefix instead. Both
- prefixes should be directory names without trailing slash (i.e. use ""
- instead of "/"). */
-static void
-set_this_relocation_prefix (const char *orig_prefix_arg,
- const char *curr_prefix_arg)
-{
- if (orig_prefix_arg != NULL && curr_prefix_arg != NULL
- /* Optimization: if orig_prefix and curr_prefix are equal, the
- relocation is a nop. */
- && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)
- {
- /* Duplicate the argument strings. */
- char *memory;
-
- orig_prefix_len = strlen (orig_prefix_arg);
- curr_prefix_len = strlen (curr_prefix_arg);
- memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1);
-#ifdef NO_XMALLOC
- if (memory != NULL)
-#endif
- {
- memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
- orig_prefix = memory;
- memory += orig_prefix_len + 1;
- memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
- curr_prefix = memory;
- return;
- }
- }
- orig_prefix = NULL;
- curr_prefix = NULL;
- /* Don't worry about wasted memory here - this function is usually only
- called once. */
-}
-
-/* Sets the original and the current installation prefix of the package.
- Relocation simply replaces a pathname starting with the original prefix
- by the corresponding pathname with the current prefix instead. Both
- prefixes should be directory names without trailing slash (i.e. use ""
- instead of "/"). */
-void
-set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg)
-{
- set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
-
- /* Now notify all dependent libraries. */
-#if DEPENDS_ON_LIBCHARSET
- libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
-#endif
-#if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109
- libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
-#endif
-#if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix
- libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
-#endif
-}
-
-#if !defined IN_LIBRARY || (defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE)
-
-/* Convenience function:
- Computes the current installation prefix, based on the original
- installation prefix, the original installation directory of a particular
- file, and the current pathname of this file.
- Returns it, freshly allocated. Returns NULL upon failure. */
-#ifdef IN_LIBRARY
-#define compute_curr_prefix local_compute_curr_prefix
-static
-#endif
-char *
-compute_curr_prefix (const char *orig_installprefix,
- const char *orig_installdir,
- const char *curr_pathname)
-{
- char *curr_installdir;
- const char *rel_installdir;
-
- if (curr_pathname == NULL)
- return NULL;
-
- /* Determine the relative installation directory, relative to the prefix.
- This is simply the difference between orig_installprefix and
- orig_installdir. */
- if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix))
- != 0)
- /* Shouldn't happen - nothing should be installed outside $(prefix). */
- return NULL;
- rel_installdir = orig_installdir + strlen (orig_installprefix);
-
- /* Determine the current installation directory. */
- {
- const char *p_base = curr_pathname + FILE_SYSTEM_PREFIX_LEN (curr_pathname);
- const char *p = curr_pathname + strlen (curr_pathname);
- char *q;
-
- while (p > p_base)
- {
- p--;
- if (ISSLASH (*p))
- break;
- }
-
- q = (char *) xmalloc (p - curr_pathname + 1);
-#ifdef NO_XMALLOC
- if (q == NULL)
- return NULL;
-#endif
- memcpy (q, curr_pathname, p - curr_pathname);
- q[p - curr_pathname] = '\0';
- curr_installdir = q;
- }
-
- /* Compute the current installation prefix by removing the trailing
- rel_installdir from it. */
- {
- const char *rp = rel_installdir + strlen (rel_installdir);
- const char *cp = curr_installdir + strlen (curr_installdir);
- const char *cp_base =
- curr_installdir + FILE_SYSTEM_PREFIX_LEN (curr_installdir);
-
- while (rp > rel_installdir && cp > cp_base)
- {
- bool same = false;
- const char *rpi = rp;
- const char *cpi = cp;
-
- while (rpi > rel_installdir && cpi > cp_base)
- {
- rpi--;
- cpi--;
- if (ISSLASH (*rpi) || ISSLASH (*cpi))
- {
- if (ISSLASH (*rpi) && ISSLASH (*cpi))
- same = true;
- break;
- }
- /* Do case-insensitive comparison if the file system is always or
- often case-insensitive. It's better to accept the comparison
- if the difference is only in case, rather than to fail. */
-#if defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
- /* Native Windows, Cygwin, OS/2, DOS - case insignificant file system */
- if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
- != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
- break;
-#else
- if (*rpi != *cpi)
- break;
-#endif
- }
- if (!same)
- break;
- /* The last pathname component was the same. rpi and cpi now point
- to the slash before it. */
- rp = rpi;
- cp = cpi;
- }
-
- if (rp > rel_installdir)
- {
- /* Unexpected: The curr_installdir does not end with rel_installdir. */
- free (curr_installdir);
- return NULL;
- }
-
- {
- size_t computed_curr_prefix_len = cp - curr_installdir;
- char *computed_curr_prefix;
-
- computed_curr_prefix = (char *) xmalloc (computed_curr_prefix_len + 1);
-#ifdef NO_XMALLOC
- if (computed_curr_prefix == NULL)
- {
- free (curr_installdir);
- return NULL;
- }
-#endif
- memcpy (computed_curr_prefix, curr_installdir, computed_curr_prefix_len);
- computed_curr_prefix[computed_curr_prefix_len] = '\0';
-
- free (curr_installdir);
-
- return computed_curr_prefix;
- }
- }
-}
-
-#endif /* !IN_LIBRARY || PIC */
-
-#if defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE
-
-/* Full pathname of shared library, or NULL. */
-static char *shared_library_fullname;
-
-#if defined _WIN32 && !defined __CYGWIN__
-/* Native Windows only.
- On Cygwin, it is better to use the Cygwin provided /proc interface, than
- to use native Windows API and cygwin_conv_to_posix_path, because it
- supports longer file names
- (see <https://cygwin.com/ml/cygwin/2011-01/msg00410.html>). */
-
-/* Determine the full pathname of the shared library when it is loaded. */
-
-BOOL WINAPI
-DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
-{
- (void) reserved;
-
- if (event == DLL_PROCESS_ATTACH)
- {
- /* The DLL is being loaded into an application's address range. */
- static char location[MAX_PATH];
-
- if (!GetModuleFileName (module_handle, location, sizeof (location)))
- /* Shouldn't happen. */
- return FALSE;
-
- if (!IS_FILE_NAME_WITH_DIR (location))
- /* Shouldn't happen. */
- return FALSE;
-
- shared_library_fullname = strdup (location);
- }
-
- return TRUE;
-}
-
-#elif defined __EMX__
-
-extern int _CRT_init (void);
-extern void _CRT_term (void);
-extern void __ctordtorInit (void);
-extern void __ctordtorTerm (void);
-
-unsigned long _System
-_DLL_InitTerm (unsigned long hModule, unsigned long ulFlag)
-{
- static char location[CCHMAXPATH];
-
- switch (ulFlag)
- {
- case 0:
- if (_CRT_init () == -1)
- return 0;
-
- __ctordtorInit();
-
- /* See http://cyberkinetica.homeunix.net/os2tk45/cp1/1247_L2H_DosQueryModuleNameSy.html
- for specification of DosQueryModuleName(). */
- if (DosQueryModuleName (hModule, sizeof (location), location))
- return 0;
-
- _fnslashify (location);
- shared_library_fullname = strdup (location);
- break;
-
- case 1:
- __ctordtorTerm();
-
- _CRT_term ();
- break;
- }
-
- return 1;
-}
-
-#else /* Unix */
-
-static void
-find_shared_library_fullname ()
-{
-#if (defined __linux__ && (__GLIBC__ >= 2 || defined __UCLIBC__)) || defined __CYGWIN__
- /* Linux has /proc/self/maps. glibc 2 and uClibc have the getline()
- function.
- Cygwin >= 1.5 has /proc/self/maps and the getline() function too.
- But it is costly: ca. 0.3 ms on Linux, 3 ms on Cygwin 1.5, and 5 ms on
- Cygwin 1.7. */
- FILE *fp;
-
- /* Open the current process' maps file. It describes one VMA per line. */
- fp = fopen ("/proc/self/maps", "r");
- if (fp)
- {
- unsigned long address = (unsigned long) &find_shared_library_fullname;
- for (;;)
- {
- unsigned long start, end;
- int c;
-
- if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
- break;
- if (address >= start && address <= end - 1)
- {
- /* Found it. Now see if this line contains a filename. */
- while (c = getc (fp), c != EOF && c != '\n' && c != '/')
- continue;
- if (c == '/')
- {
- size_t size;
- int len;
-
- ungetc (c, fp);
- shared_library_fullname = NULL; size = 0;
- len = getline (&shared_library_fullname, &size, fp);
- if (len >= 0)
- {
- /* Success: filled shared_library_fullname. */
- if (len > 0 && shared_library_fullname[len - 1] == '\n')
- shared_library_fullname[len - 1] = '\0';
- }
- }
- break;
- }
- while (c = getc (fp), c != EOF && c != '\n')
- continue;
- }
- fclose (fp);
- }
-#endif
-}
-
-#endif /* Native Windows / EMX / Unix */
-
-/* Return the full pathname of the current shared library.
- Return NULL if unknown.
- Guaranteed to work only on Linux, EMX, Cygwin, and native Windows. */
-static char *
-get_shared_library_fullname ()
-{
-#if !(defined _WIN32 && !defined __CYGWIN__) && !defined __EMX__
- static bool tried_find_shared_library_fullname;
- if (!tried_find_shared_library_fullname)
- {
- find_shared_library_fullname ();
- tried_find_shared_library_fullname = true;
- }
-#endif
- return shared_library_fullname;
-}
-
-#endif /* PIC */
-
-/* Returns the pathname, relocated according to the current installation
- directory.
- The returned string is either PATHNAME unmodified or a freshly allocated
- string that you can free with free() after casting it to 'char *'. */
-const char *
-relocate (const char *pathname)
-{
-#if defined PIC && defined INSTALLDIR && ENABLE_COSTLY_RELOCATABLE
- static int initialized;
-
- /* Initialization code for a shared library. */
- if (!initialized)
- {
- /* At this point, orig_prefix and curr_prefix likely have already been
- set through the main program's set_program_name_and_installdir
- function. This is sufficient in the case that the library has
- initially been installed in the same orig_prefix. But we can do
- better, to also cover the cases that 1. it has been installed
- in a different prefix before being moved to orig_prefix and (later)
- to curr_prefix, 2. unlike the program, it has not moved away from
- orig_prefix. */
- const char *orig_installprefix = INSTALLPREFIX;
- const char *orig_installdir = INSTALLDIR;
- char *curr_prefix_better;
-
- curr_prefix_better =
- compute_curr_prefix (orig_installprefix, orig_installdir,
- get_shared_library_fullname ());
-
- set_relocation_prefix (orig_installprefix,
- curr_prefix_better != NULL
- ? curr_prefix_better
- : curr_prefix);
-
- if (curr_prefix_better != NULL)
- free (curr_prefix_better);
-
- initialized = 1;
- }
-#endif
-
- /* Note: It is not necessary to perform case insensitive comparison here,
- even for DOS-like file systems, because the pathname argument was
- typically created from the same Makefile variable as orig_prefix came
- from. */
- if (orig_prefix != NULL && curr_prefix != NULL
- && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
- {
- if (pathname[orig_prefix_len] == '\0')
- {
- /* pathname equals orig_prefix. */
- char *result = (char *) xmalloc (strlen (curr_prefix) + 1);
-
-#ifdef NO_XMALLOC
- if (result != NULL)
-#endif
- {
- strcpy (result, curr_prefix);
- return result;
- }
- }
- else if (ISSLASH (pathname[orig_prefix_len]))
- {
- /* pathname starts with orig_prefix. */
- const char *pathname_tail = &pathname[orig_prefix_len];
- char *result =
- (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
-
-#ifdef NO_XMALLOC
- if (result != NULL)
-#endif
- {
- memcpy (result, curr_prefix, curr_prefix_len);
- strcpy (result + curr_prefix_len, pathname_tail);
- return result;
- }
- }
- }
-
-#ifdef __EMX__
-# ifdef __KLIBC__
-# undef strncmp
-
- if (strncmp (pathname, "/@unixroot", 10) == 0
- && (pathname[10] == '\0' || ISSLASH (pathname[10])))
- {
- /* kLIBC itself processes /@unixroot prefix */
- return pathname;
- }
- else
-# endif
- if (ISSLASH (pathname[0]))
- {
- const char *unixroot = getenv ("UNIXROOT");
-
- if (unixroot && HAS_DEVICE (unixroot) && unixroot[2] == '\0')
- {
- char *result = (char *) xmalloc (2 + strlen (pathname) + 1);
-#ifdef NO_XMALLOC
- if (result != NULL)
-#endif
- {
- memcpy (result, unixroot, 2);
- strcpy (result + 2, pathname);
- return result;
- }
- }
- }
-#endif
-
- /* Nothing to relocate. */
- return pathname;
-}
-
-/* Returns the pathname, relocated according to the current installation
- directory.
- This function sets *ALLOCATEDP to the allocated memory, or to NULL if
- no memory allocation occurs. So that, after you're done with the return
- value, to reclaim allocated memory, you can do: free (*ALLOCATEDP). */
-const char *
-relocate2 (const char *pathname, char **allocatedp)
-{
- const char *result = relocate (pathname);
- *allocatedp = (result != pathname ? (char *) result : NULL);
- return result;
-}
-
-#endif
+++ /dev/null
-/* Provide relocatable packages.
- Copyright (C) 2003, 2005, 2008-2017 Free Software Foundation, Inc.
- Written by Bruno Haible <bruno@clisp.org>, 2003.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-#ifndef _RELOCATABLE_H
-#define _RELOCATABLE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* This can be enabled through the configure --enable-relocatable option. */
-#if ENABLE_RELOCATABLE
-
-/* When building a DLL, we must export some functions. Note that because
- this is a private .h file, we don't need to use __declspec(dllimport)
- in any case. */
-#if HAVE_VISIBILITY && BUILDING_DLL
-# define RELOCATABLE_DLL_EXPORTED __attribute__((__visibility__("default")))
-#elif defined _MSC_VER && BUILDING_DLL
-# define RELOCATABLE_DLL_EXPORTED __declspec(dllexport)
-#else
-# define RELOCATABLE_DLL_EXPORTED
-#endif
-
-/* Sets the original and the current installation prefix of the package.
- Relocation simply replaces a pathname starting with the original prefix
- by the corresponding pathname with the current prefix instead. Both
- prefixes should be directory names without trailing slash (i.e. use ""
- instead of "/"). */
-extern RELOCATABLE_DLL_EXPORTED void
- set_relocation_prefix (const char *orig_prefix,
- const char *curr_prefix);
-
-/* Returns the pathname, relocated according to the current installation
- directory.
- The returned string is either PATHNAME unmodified or a freshly allocated
- string that you can free with free() after casting it to 'char *'. */
-extern const char * relocate (const char *pathname);
-
-/* Returns the pathname, relocated according to the current installation
- directory.
- This function sets *ALLOCATEDP to the allocated memory, or to NULL if
- no memory allocation occurs. So that, after you're done with the return
- value, to reclaim allocated memory, you can do: free (*ALLOCATEDP). */
-extern const char * relocate2 (const char *pathname, char **allocatedp);
-
-/* Memory management: relocate() potentially allocates memory, because it has
- to construct a fresh pathname. If this is a problem because your program
- calls relocate() frequently or because you want to fix all potential memory
- leaks anyway, you have three options:
- 1) Use this idiom:
- const char *pathname = ...;
- const char *rel_pathname = relocate (pathname);
- ...
- if (rel_pathname != pathname)
- free ((char *) rel_pathname);
- 2) Use this idiom:
- char *allocated;
- const char *rel_pathname = relocate2 (..., &allocated);
- ...
- free (allocated);
- 3) Think about caching the result. */
-
-/* Convenience function:
- Computes the current installation prefix, based on the original
- installation prefix, the original installation directory of a particular
- file, and the current pathname of this file.
- Returns it, freshly allocated. Returns NULL upon failure. */
-extern char * compute_curr_prefix (const char *orig_installprefix,
- const char *orig_installdir,
- const char *curr_pathname);
-
-#else
-
-/* By default, we use the hardwired pathnames. */
-#define relocate(pathname) (pathname)
-#define relocate2(pathname,allocatedp) (*(allocatedp) = NULL, (pathname))
-
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _RELOCATABLE_H */
+++ /dev/null
-/* Return the internal lock used by setlocale_null_r.
- Copyright (C) 2019-2020 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2019. */
-
-#include <config.h>
-
-/* When it is known that the gl_get_setlocale_null_lock function is defined
- by a dependency library, it should not be defined here. */
-#if OMIT_SETLOCALE_LOCK
-
-/* This declaration is solely to ensure that after preprocessing
- this file is never empty. */
-typedef int dummy;
-
-#else
-
-/* This file defines the internal lock used by setlocale_null_r.
- It is a separate compilation unit, so that only one copy of it is
- present when linking statically. */
-
-/* Prohibit renaming this symbol. */
-# undef gl_get_setlocale_null_lock
-
-/* Macro for exporting a symbol (function, not variable) defined in this file,
- when compiled into a shared library. */
-# ifndef DLL_EXPORTED
-# if HAVE_VISIBILITY
- /* Override the effect of the compiler option '-fvisibility=hidden'. */
-# define DLL_EXPORTED __attribute__((__visibility__("default")))
-# elif defined _WIN32 || defined __CYGWIN__
-# define DLL_EXPORTED __declspec(dllexport)
-# else
-# define DLL_EXPORTED
-# endif
-# endif
-
-# if defined _WIN32 && !defined __CYGWIN__
-
-# define WIN32_LEAN_AND_MEAN /* avoid including junk */
-# include <windows.h>
-
-# include "windows-initguard.h"
-
-/* The return type is a 'CRITICAL_SECTION *', not a 'glwthread_mutex_t *',
- because the latter is not guaranteed to be a stable ABI in the future. */
-
-/* Make sure the function gets exported from DLLs. */
-DLL_EXPORTED CRITICAL_SECTION *gl_get_setlocale_null_lock (void);
-
-static glwthread_initguard_t guard = GLWTHREAD_INITGUARD_INIT;
-static CRITICAL_SECTION lock;
-
-/* Returns the internal lock used by setlocale_null_r. */
-CRITICAL_SECTION *
-gl_get_setlocale_null_lock (void)
-{
- if (!guard.done)
- {
- if (InterlockedIncrement (&guard.started) == 0)
- {
- /* This thread is the first one to need the lock. Initialize it. */
- InitializeCriticalSection (&lock);
- guard.done = 1;
- }
- else
- {
- /* Don't let guard.started grow and wrap around. */
- InterlockedDecrement (&guard.started);
- /* Yield the CPU while waiting for another thread to finish
- initializing this mutex. */
- while (!guard.done)
- Sleep (0);
- }
- }
- return &lock;
-}
-
-# elif HAVE_PTHREAD_API
-
-# include <pthread.h>
-
-static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/* Make sure the function gets exported from shared libraries. */
-DLL_EXPORTED pthread_mutex_t *gl_get_setlocale_null_lock (void);
-
-/* Returns the internal lock used by setlocale_null_r. */
-pthread_mutex_t *
-gl_get_setlocale_null_lock (void)
-{
- return &mutex;
-}
-
-# elif HAVE_THREADS_H
-
-# include <threads.h>
-# include <stdlib.h>
-
-static int volatile init_needed = 1;
-static once_flag init_once = ONCE_FLAG_INIT;
-static mtx_t mutex;
-
-static void
-atomic_init (void)
-{
- if (mtx_init (&mutex, mtx_plain) != thrd_success)
- abort ();
- init_needed = 0;
-}
-
-/* Make sure the function gets exported from shared libraries. */
-DLL_EXPORTED mtx_t *gl_get_setlocale_null_lock (void);
-
-/* Returns the internal lock used by setlocale_null_r. */
-mtx_t *
-gl_get_setlocale_null_lock (void)
-{
- if (init_needed)
- call_once (&init_once, atomic_init);
- return &mutex;
-}
-
-# endif
-
-# if (defined _WIN32 || defined __CYGWIN__) && !defined _MSC_VER
-/* Make sure the '__declspec(dllimport)' in setlocale_null.c does not cause
- a link failure when no DLLs are involved. */
-# if defined _WIN64 || defined _LP64
-# define IMP(x) __imp_##x
-# else
-# define IMP(x) _imp__##x
-# endif
-void * IMP(gl_get_setlocale_null_lock) = &gl_get_setlocale_null_lock;
-# endif
-
-#endif
This matters on MacOS X 10 and Windows.
See the comments in localename.c, function gl_locale_name_default. */
+/* Specification. */
#include <locale.h>
+
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
# define DLL_EXPORTED
#endif
-#include "gettextP.h"
+#include "localename.h"
#if HAVE_CFLOCALECOPYPREFERREDLANGUAGES || HAVE_CFPREFERENCESCOPYAPPVALUE
# if HAVE_CFLOCALECOPYPREFERREDLANGUAGES
# include <CoreFoundation/CFPropertyList.h>
# include <CoreFoundation/CFArray.h>
# include <CoreFoundation/CFString.h>
+extern void gl_locale_name_canonicalize (char *name);
#endif
+/* Get _nl_msg_cat_cntr declaration. */
+#include "gettextP.h"
+
#if (defined __APPLE__ && defined __MACH__) || defined _WIN32 || defined __CYGWIN__
# undef setlocale
+++ /dev/null
-/* Query the name of the current global locale.
- Copyright (C) 2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2019. */
-
-#include <config.h>
-
-/* Specification. */
-#include "setlocale_null.h"
-
-#include <errno.h>
-#include <locale.h>
-#include <stdlib.h>
-#include <string.h>
-#if defined _WIN32 && !defined __CYGWIN__
-# include <wchar.h>
-#endif
-
-#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE)
-# if defined _WIN32 && !defined __CYGWIN__
-
-# define WIN32_LEAN_AND_MEAN /* avoid including junk */
-# include <windows.h>
-
-# elif HAVE_PTHREAD_API
-
-# include <pthread.h>
-# if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
-# include <threads.h>
-# pragma weak thrd_exit
-# define c11_threads_in_use() (thrd_exit != NULL)
-# else
-# define c11_threads_in_use() 0
-# endif
-
-# elif HAVE_THREADS_H
-
-# include <threads.h>
-
-# endif
-#endif
-
-/* Use the system's setlocale() function, not the gnulib override, here. */
-#undef setlocale
-
-static const char *
-setlocale_null_androidfix (int category)
-{
- const char *result = setlocale (category, NULL);
-
-#ifdef __ANDROID__
- if (result == NULL)
- switch (category)
- {
- case LC_CTYPE:
- case LC_NUMERIC:
- case LC_TIME:
- case LC_COLLATE:
- case LC_MONETARY:
- case LC_MESSAGES:
- case LC_ALL:
- case LC_PAPER:
- case LC_NAME:
- case LC_ADDRESS:
- case LC_TELEPHONE:
- case LC_MEASUREMENT:
- result = "C";
- break;
- default:
- break;
- }
-#endif
-
- return result;
-}
-
-static int
-setlocale_null_unlocked (int category, char *buf, size_t bufsize)
-{
-#if defined _WIN32 && !defined __CYGWIN__ && defined _MSC_VER
- /* On native Windows, nowadays, the setlocale() implementation is based
- on _wsetlocale() and uses malloc() for the result. We are better off
- using _wsetlocale() directly. */
- const wchar_t *result = _wsetlocale (category, NULL);
-
- if (result == NULL)
- {
- /* CATEGORY is invalid. */
- if (bufsize > 0)
- /* Return an empty string in BUF.
- This is a convenience for callers that don't want to write explicit
- code for handling EINVAL. */
- buf[0] = '\0';
- return EINVAL;
- }
- else
- {
- size_t length = wcslen (result);
- if (length < bufsize)
- {
- size_t i;
-
- /* Convert wchar_t[] -> char[], assuming plain ASCII. */
- for (i = 0; i <= length; i++)
- buf[i] = result[i];
-
- return 0;
- }
- else
- {
- if (bufsize > 0)
- {
- /* Return a truncated result in BUF.
- This is a convenience for callers that don't want to write
- explicit code for handling ERANGE. */
- size_t i;
-
- /* Convert wchar_t[] -> char[], assuming plain ASCII. */
- for (i = 0; i < bufsize; i++)
- buf[i] = result[i];
- buf[bufsize - 1] = '\0';
- }
- return ERANGE;
- }
- }
-#else
- const char *result = setlocale_null_androidfix (category);
-
- if (result == NULL)
- {
- /* CATEGORY is invalid. */
- if (bufsize > 0)
- /* Return an empty string in BUF.
- This is a convenience for callers that don't want to write explicit
- code for handling EINVAL. */
- buf[0] = '\0';
- return EINVAL;
- }
- else
- {
- size_t length = strlen (result);
- if (length < bufsize)
- {
- memcpy (buf, result, length + 1);
- return 0;
- }
- else
- {
- if (bufsize > 0)
- {
- /* Return a truncated result in BUF.
- This is a convenience for callers that don't want to write
- explicit code for handling ERANGE. */
- memcpy (buf, result, bufsize - 1);
- buf[bufsize - 1] = '\0';
- }
- return ERANGE;
- }
- }
-#endif
-}
-
-#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE) /* musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin */
-
-/* Use a lock, so that no two threads can invoke setlocale_null_unlocked
- at the same time. */
-
-/* Prohibit renaming this symbol. */
-# undef gl_get_setlocale_null_lock
-
-# if defined _WIN32 && !defined __CYGWIN__
-
-extern __declspec(dllimport) CRITICAL_SECTION *gl_get_setlocale_null_lock (void);
-
-static int
-setlocale_null_with_lock (int category, char *buf, size_t bufsize)
-{
- CRITICAL_SECTION *lock = gl_get_setlocale_null_lock ();
- int ret;
-
- EnterCriticalSection (lock);
- ret = setlocale_null_unlocked (category, buf, bufsize);
- LeaveCriticalSection (lock);
-
- return ret;
-}
-
-# elif HAVE_PTHREAD_API /* musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin */
-
-extern
-# if defined _WIN32 || defined __CYGWIN__
- __declspec(dllimport)
-# endif
- pthread_mutex_t *gl_get_setlocale_null_lock (void);
-
-# if HAVE_WEAK_SYMBOLS /* musl libc, FreeBSD, NetBSD, OpenBSD, Haiku */
-
- /* Avoid the need to link with '-lpthread'. */
-# pragma weak pthread_mutex_lock
-# pragma weak pthread_mutex_unlock
-
- /* Determine whether libpthread is in use. */
-# pragma weak pthread_mutexattr_gettype
- /* See the comments in lock.h. */
-# define pthread_in_use() \
- (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
-
-# else
-# define pthread_in_use() 1
-# endif
-
-static int
-setlocale_null_with_lock (int category, char *buf, size_t bufsize)
-{
- if (pthread_in_use())
- {
- pthread_mutex_t *lock = gl_get_setlocale_null_lock ();
- int ret;
-
- if (pthread_mutex_lock (lock))
- abort ();
- ret = setlocale_null_unlocked (category, buf, bufsize);
- if (pthread_mutex_unlock (lock))
- abort ();
-
- return ret;
- }
- else
- return setlocale_null_unlocked (category, buf, bufsize);
-}
-
-# elif HAVE_THREADS_H
-
-extern mtx_t *gl_get_setlocale_null_lock (void);
-
-static int
-setlocale_null_with_lock (int category, char *buf, size_t bufsize)
-{
- mtx_t *lock = gl_get_setlocale_null_lock ();
- int ret;
-
- if (mtx_lock (lock) != thrd_success)
- abort ();
- ret = setlocale_null_unlocked (category, buf, bufsize);
- if (mtx_unlock (lock) != thrd_success)
- abort ();
-
- return ret;
-}
-
-# endif
-
-#endif
-
-int
-setlocale_null_r (int category, char *buf, size_t bufsize)
-{
-#if SETLOCALE_NULL_ALL_MTSAFE
-# if SETLOCALE_NULL_ONE_MTSAFE
-
- return setlocale_null_unlocked (category, buf, bufsize);
-
-# else
-
- if (category == LC_ALL)
- return setlocale_null_unlocked (category, buf, bufsize);
- else
- return setlocale_null_with_lock (category, buf, bufsize);
-
-# endif
-#else
-# if SETLOCALE_NULL_ONE_MTSAFE
-
- if (category == LC_ALL)
- return setlocale_null_with_lock (category, buf, bufsize);
- else
- return setlocale_null_unlocked (category, buf, bufsize);
-
-# else
-
- return setlocale_null_with_lock (category, buf, bufsize);
-
-# endif
-#endif
-}
-
-const char *
-setlocale_null (int category)
-{
-#if SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE
- return setlocale_null_androidfix (category);
-#else
-
- /* This call must be multithread-safe. To achieve this without using
- thread-local storage:
- 1. We use a specific static buffer for each possible CATEGORY
- argument. So that different threads can call setlocale_mtsafe
- with different CATEGORY arguments, without interfering.
- 2. We use a simple strcpy or memcpy to fill this static buffer.
- Filling it through, for example, strcpy + strcat would not be
- guaranteed to leave the buffer's contents intact if another thread
- is currently accessing it. If necessary, the contents is first
- assembled in a stack-allocated buffer. */
- if (category == LC_ALL)
- {
-# if SETLOCALE_NULL_ALL_MTSAFE
- return setlocale_null_androidfix (LC_ALL);
-# else
- char buf[SETLOCALE_NULL_ALL_MAX];
- static char resultbuf[SETLOCALE_NULL_ALL_MAX];
-
- if (setlocale_null_r (LC_ALL, buf, sizeof (buf)))
- return "C";
- strcpy (resultbuf, buf);
- return resultbuf;
-# endif
- }
- else
- {
-# if SETLOCALE_NULL_ONE_MTSAFE
- return setlocale_null_androidfix (category);
-# else
- enum
- {
- LC_CTYPE_INDEX,
- LC_NUMERIC_INDEX,
- LC_TIME_INDEX,
- LC_COLLATE_INDEX,
- LC_MONETARY_INDEX,
- LC_MESSAGES_INDEX,
-# ifdef LC_PAPER
- LC_PAPER_INDEX,
-# endif
-# ifdef LC_NAME
- LC_NAME_INDEX,
-# endif
-# ifdef LC_ADDRESS
- LC_ADDRESS_INDEX,
-# endif
-# ifdef LC_TELEPHONE
- LC_TELEPHONE_INDEX,
-# endif
-# ifdef LC_MEASUREMENT
- LC_MEASUREMENT_INDEX,
-# endif
-# ifdef LC_IDENTIFICATION
- LC_IDENTIFICATION_INDEX,
-# endif
- LC_INDICES_COUNT
- }
- i;
- char buf[SETLOCALE_NULL_MAX];
- static char resultbuf[LC_INDICES_COUNT][SETLOCALE_NULL_MAX];
- int err;
-
- err = setlocale_null_r (category, buf, sizeof (buf));
- if (err == EINVAL)
- return NULL;
- if (err)
- return "C";
-
- switch (category)
- {
- case LC_CTYPE: i = LC_CTYPE_INDEX; break;
- case LC_NUMERIC: i = LC_NUMERIC_INDEX; break;
- case LC_TIME: i = LC_TIME_INDEX; break;
- case LC_COLLATE: i = LC_COLLATE_INDEX; break;
- case LC_MONETARY: i = LC_MONETARY_INDEX; break;
- case LC_MESSAGES: i = LC_MESSAGES_INDEX; break;
-# ifdef LC_PAPER
- case LC_PAPER: i = LC_PAPER_INDEX; break;
-# endif
-# ifdef LC_NAME
- case LC_NAME: i = LC_NAME_INDEX; break;
-# endif
-# ifdef LC_ADDRESS
- case LC_ADDRESS: i = LC_ADDRESS_INDEX; break;
-# endif
-# ifdef LC_TELEPHONE
- case LC_TELEPHONE: i = LC_TELEPHONE_INDEX; break;
-# endif
-# ifdef LC_MEASUREMENT
- case LC_MEASUREMENT: i = LC_MEASUREMENT_INDEX; break;
-# endif
-# ifdef LC_IDENTIFICATION
- case LC_IDENTIFICATION: i = LC_IDENTIFICATION_INDEX; break;
-# endif
- default:
- /* If you get here, a #ifdef LC_xxx is missing. */
- abort ();
- }
-
- strcpy (resultbuf[i], buf);
- return resultbuf[i];
-# endif
- }
-#endif
-}
+++ /dev/null
-/* Query the name of the current global locale.
- Copyright (C) 2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2019. */
-
-#ifndef _SETLOCALE_NULL_H
-#define _SETLOCALE_NULL_H
-
-#include <stddef.h>
-
-#include "arg-nonnull.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* Recommended size of a buffer for a locale name for a single category.
- On glibc systems, you can have locale names that are relative file names;
- assume a maximum length 256.
- In native Windows, in 2018 the longest locale name was of length 58
- ("FYRO Macedonian_Former Yugoslav Republic of Macedonia.1251"). */
-#define SETLOCALE_NULL_MAX (256+1)
-
-/* Recommended size of a buffer for a locale name with all categories.
- On glibc systems, you can have locale names that are relative file names;
- assume maximum length 256 for each. There are 12 categories; so, the
- maximum total length is 148+12*256.
- In native Windows, there are 5 categories, and the maximum total length is
- 55+5*58. */
-#define SETLOCALE_NULL_ALL_MAX (148+12*256+1)
-
-/* setlocale_null_r (CATEGORY, BUF, BUFSIZE) is like setlocale (CATEGORY, NULL),
- except that
- - it is guaranteed to be multithread-safe,
- - it returns the resulting locale category name or locale name in the
- user-supplied buffer BUF, which must be BUFSIZE bytes long.
- The recommended minimum buffer size is
- - SETLOCALE_NULL_MAX for CATEGORY != LC_ALL, and
- - SETLOCALE_NULL_ALL_MAX for CATEGORY == LC_ALL.
- The return value is an error code: 0 if the call is successful, EINVAL if
- CATEGORY is invalid, or ERANGE if BUFSIZE is smaller than the length needed
- size (including the trailing NUL byte). In the latter case, a truncated
- result is returned in BUF, but still NUL-terminated if BUFSIZE > 0.
- For this call to be multithread-safe, *all* calls to
- setlocale (CATEGORY, NULL) in all other threads must have been converted
- to use setlocale_null_r or setlocale_null as well, and the other threads
- must not make other setlocale invocations (since changing the global locale
- has side effects on all threads). */
-extern int setlocale_null_r (int category, char *buf, size_t bufsize)
- _GL_ARG_NONNULL ((2));
-
-/* setlocale_null (CATEGORY) is like setlocale (CATEGORY, NULL), except that
- it is guaranteed to be multithread-safe.
- The return value is NULL if CATEGORY is invalid.
- For this call to be multithread-safe, *all* calls to
- setlocale (CATEGORY, NULL) in all other threads must have been converted
- to use setlocale_null_r or setlocale_null as well, and the other threads
- must not make other setlocale invocations (since changing the global locale
- has side effects on all threads). */
-extern const char *setlocale_null (int category);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SETLOCALE_NULL_H */
/* Implementation of the textdomain(3) function.
- Copyright (C) 1995-2016 Free Software Foundation, Inc.
+ Copyright (C) 1995-2015, 2021 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
# define gl_rwlock_wrlock __libc_rwlock_wrlock
# define gl_rwlock_unlock __libc_rwlock_unlock
#else
-# include "lock.h"
+# include "glthread/lock.h"
#endif
/* @@ end of prolog @@ */
+++ /dev/null
-/* Optimization of multithreaded code.
-
- Copyright (C) 2020 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2020. */
-
-#ifndef _THREAD_OPTIM_H
-#define _THREAD_OPTIM_H
-
-/* This file defines a way to optimize multithreaded code for the single-thread
- case, based on the variable '__libc_single_threaded', defined in
- glibc >= 2.32. */
-
-/* Typical use: In a block or function, use
-
- bool mt = gl_multithreaded ();
- ...
- if (mt)
- if (pthread_mutex_lock (&lock)) abort ();
- ...
- if (mt)
- if (pthread_mutex_unlock (&lock)) abort ();
-
- The gl_multithreaded () invocation determines whether the program currently
- is multithreaded.
-
- if (mt) STATEMENT executes STATEMENT in the multithreaded case, and skips
- it in the single-threaded case.
-
- The code between the gl_multithreaded () invocation and any use of the
- variable 'mt' must not create threads or invoke functions that may
- indirectly create threads (e.g. 'dlopen' may, indirectly through C++
- initializers of global variables in the shared library being opened,
- create threads).
-
- The lock here is meant to synchronize threads in the same process. The
- same optimization cannot be applied to locks that synchronize different
- processes (e.g. through shared memory mappings). */
-
-#if HAVE_SYS_SINGLE_THREADED_H /* glibc >= 2.32 */
-# include <sys/single_threaded.h>
-# define gl_multithreaded() !__libc_single_threaded
-#else
-# define gl_multithreaded() 1
-#endif
-
-#endif /* _THREAD_OPTIM_H */
+++ /dev/null
-/* Multithreading primitives.
- Copyright (C) 2005-2020 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005. */
-
-#include <config.h>
-
-/* ========================================================================= */
-
-#if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS
-
-/* Use the POSIX threads library. */
-
-# include <errno.h>
-# include <pthread.h>
-# include <stdlib.h>
-
-# if PTHREAD_IN_USE_DETECTION_HARD
-
-# if defined __FreeBSD__ || defined __DragonFly__ /* FreeBSD */
-
-/* Test using pthread_key_create. */
-
-int
-glthread_in_use (void)
-{
- static int tested;
- static int result; /* 1: linked with -lpthread, 0: only with libc */
-
- if (!tested)
- {
- pthread_key_t key;
- int err = pthread_key_create (&key, NULL);
-
- if (err == ENOSYS)
- result = 0;
- else
- {
- result = 1;
- if (err == 0)
- pthread_key_delete (key);
- }
- tested = 1;
- }
- return result;
-}
-
-# else /* Solaris, HP-UX */
-
-/* Test using pthread_create. */
-
-/* The function to be executed by a dummy thread. */
-static void *
-dummy_thread_func (void *arg)
-{
- return arg;
-}
-
-int
-glthread_in_use (void)
-{
- static int tested;
- static int result; /* 1: linked with -lpthread, 0: only with libc */
-
- if (!tested)
- {
- pthread_t thread;
-
- if (pthread_create (&thread, NULL, dummy_thread_func, NULL) != 0)
- /* Thread creation failed. */
- result = 0;
- else
- {
- /* Thread creation works. */
- void *retval;
- if (pthread_join (thread, &retval) != 0)
- abort ();
- result = 1;
- }
- tested = 1;
- }
- return result;
-}
-
-# endif
-
-# endif
-
-#endif
-
-/* ========================================================================= */
-
-/* This declaration is solely to ensure that after preprocessing
- this file is never empty. */
-typedef int dummy;
+++ /dev/null
-/* Copyright (C) 1995-1997, 2000, 2006 Free Software Foundation, Inc.
- Contributed by Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>, 1997.
-
- NOTE: The canonical source of this file is maintained with the GNU C
- Library. Bugs can be reported to bug-glibc@gnu.org.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Tree search for red/black trees.
- The algorithm for adding nodes is taken from one of the many "Algorithms"
- books by Robert Sedgewick, although the implementation differs.
- The algorithm for deleting nodes can probably be found in a book named
- "Introduction to Algorithms" by Cormen/Leiserson/Rivest. At least that's
- the book that my professor took most algorithms from during the "Data
- Structures" course...
-
- Totally public domain. */
-
-/* Red/black trees are binary trees in which the edges are colored either red
- or black. They have the following properties:
- 1. The number of black edges on every path from the root to a leaf is
- constant.
- 2. No two red edges are adjacent.
- Therefore there is an upper bound on the length of every path, it's
- O(log n) where n is the number of nodes in the tree. No path can be longer
- than 1+2*P where P is the length of the shortest path in the tree.
- Useful for the implementation:
- 3. If one of the children of a node is NULL, then the other one is red
- (if it exists).
-
- In the implementation, not the edges are colored, but the nodes. The color
- interpreted as the color of the edge leading to this node. The color is
- meaningless for the root node, but we color the root node black for
- convenience. All added nodes are red initially.
-
- Adding to a red/black tree is rather easy. The right place is searched
- with a usual binary tree search. Additionally, whenever a node N is
- reached that has two red successors, the successors are colored black and
- the node itself colored red. This moves red edges up the tree where they
- pose less of a problem once we get to really insert the new node. Changing
- N's color to red may violate rule 2, however, so rotations may become
- necessary to restore the invariants. Adding a new red leaf may violate
- the same rule, so afterwards an additional check is run and the tree
- possibly rotated.
-
- Deleting is hairy. There are mainly two nodes involved: the node to be
- deleted (n1), and another node that is to be unchained from the tree (n2).
- If n1 has a successor (the node with a smallest key that is larger than
- n1), then the successor becomes n2 and its contents are copied into n1,
- otherwise n1 becomes n2.
- Unchaining a node may violate rule 1: if n2 is black, one subtree is
- missing one black edge afterwards. The algorithm must try to move this
- error upwards towards the root, so that the subtree that does not have
- enough black edges becomes the whole tree. Once that happens, the error
- has disappeared. It may not be necessary to go all the way up, since it
- is possible that rotations and recoloring can fix the error before that.
-
- Although the deletion algorithm must walk upwards through the tree, we
- do not store parent pointers in the nodes. Instead, delete allocates a
- small array of parent pointers and fills it while descending the tree.
- Since we know that the length of a path is O(log n), where n is the number
- of nodes, this is likely to use less memory. */
-
-/* Tree rotations look like this:
- A C
- / \ / \
- B C A G
- / \ / \ --> / \
- D E F G B F
- / \
- D E
-
- In this case, A has been rotated left. This preserves the ordering of the
- binary tree. */
-
-#include <config.h>
-
-/* Specification. */
-#ifdef IN_LIBINTL
-# include "tsearch.h"
-#else
-# include <search.h>
-#endif
-
-#include <stdlib.h>
-
-typedef int (*__compar_fn_t) (const void *, const void *);
-typedef void (*__action_fn_t) (const void *, VISIT, int);
-
-#ifndef weak_alias
-# define __tsearch tsearch
-# define __tfind tfind
-# define __tdelete tdelete
-# define __twalk twalk
-#endif
-
-#ifndef internal_function
-/* Inside GNU libc we mark some function in a special way. In other
- environments simply ignore the marking. */
-# define internal_function
-#endif
-
-typedef struct node_t
-{
- /* Callers expect this to be the first element in the structure - do not
- move! */
- const void *key;
- struct node_t *left;
- struct node_t *right;
- unsigned int red:1;
-} *node;
-typedef const struct node_t *const_node;
-
-#undef DEBUGGING
-
-#ifdef DEBUGGING
-
-/* Routines to check tree invariants. */
-
-#include <assert.h>
-
-#define CHECK_TREE(a) check_tree(a)
-
-static void
-check_tree_recurse (node p, int d_sofar, int d_total)
-{
- if (p == NULL)
- {
- assert (d_sofar == d_total);
- return;
- }
-
- check_tree_recurse (p->left, d_sofar + (p->left && !p->left->red), d_total);
- check_tree_recurse (p->right, d_sofar + (p->right && !p->right->red), d_total);
- if (p->left)
- assert (!(p->left->red && p->red));
- if (p->right)
- assert (!(p->right->red && p->red));
-}
-
-static void
-check_tree (node root)
-{
- int cnt = 0;
- node p;
- if (root == NULL)
- return;
- root->red = 0;
- for(p = root->left; p; p = p->left)
- cnt += !p->red;
- check_tree_recurse (root, 0, cnt);
-}
-
-
-#else
-
-#define CHECK_TREE(a)
-
-#endif
-
-/* Possibly "split" a node with two red successors, and/or fix up two red
- edges in a row. ROOTP is a pointer to the lowest node we visited, PARENTP
- and GPARENTP pointers to its parent/grandparent. P_R and GP_R contain the
- comparison values that determined which way was taken in the tree to reach
- ROOTP. MODE is 1 if we need not do the split, but must check for two red
- edges between GPARENTP and ROOTP. */
-static void
-maybe_split_for_insert (node *rootp, node *parentp, node *gparentp,
- int p_r, int gp_r, int mode)
-{
- node root = *rootp;
- node *rp, *lp;
- rp = &(*rootp)->right;
- lp = &(*rootp)->left;
-
- /* See if we have to split this node (both successors red). */
- if (mode == 1
- || ((*rp) != NULL && (*lp) != NULL && (*rp)->red && (*lp)->red))
- {
- /* This node becomes red, its successors black. */
- root->red = 1;
- if (*rp)
- (*rp)->red = 0;
- if (*lp)
- (*lp)->red = 0;
-
- /* If the parent of this node is also red, we have to do
- rotations. */
- if (parentp != NULL && (*parentp)->red)
- {
- node gp = *gparentp;
- node p = *parentp;
- /* There are two main cases:
- 1. The edge types (left or right) of the two red edges differ.
- 2. Both red edges are of the same type.
- There exist two symmetries of each case, so there is a total of
- 4 cases. */
- if ((p_r > 0) != (gp_r > 0))
- {
- /* Put the child at the top of the tree, with its parent
- and grandparent as successors. */
- p->red = 1;
- gp->red = 1;
- root->red = 0;
- if (p_r < 0)
- {
- /* Child is left of parent. */
- p->left = *rp;
- *rp = p;
- gp->right = *lp;
- *lp = gp;
- }
- else
- {
- /* Child is right of parent. */
- p->right = *lp;
- *lp = p;
- gp->left = *rp;
- *rp = gp;
- }
- *gparentp = root;
- }
- else
- {
- *gparentp = *parentp;
- /* Parent becomes the top of the tree, grandparent and
- child are its successors. */
- p->red = 0;
- gp->red = 1;
- if (p_r < 0)
- {
- /* Left edges. */
- gp->left = p->right;
- p->right = gp;
- }
- else
- {
- /* Right edges. */
- gp->right = p->left;
- p->left = gp;
- }
- }
- }
- }
-}
-
-/* Find or insert datum into search tree.
- KEY is the key to be located, ROOTP is the address of tree root,
- COMPAR the ordering function. */
-void *
-__tsearch (const void *key, void **vrootp, __compar_fn_t compar)
-{
- node q;
- node *parentp = NULL, *gparentp = NULL;
- node *rootp = (node *) vrootp;
- node *nextp;
- int r = 0, p_r = 0, gp_r = 0; /* No they might not, Mr Compiler. */
-
- if (rootp == NULL)
- return NULL;
-
- /* This saves some additional tests below. */
- if (*rootp != NULL)
- (*rootp)->red = 0;
-
- CHECK_TREE (*rootp);
-
- nextp = rootp;
- while (*nextp != NULL)
- {
- node root = *rootp;
- r = (*compar) (key, root->key);
- if (r == 0)
- return root;
-
- maybe_split_for_insert (rootp, parentp, gparentp, p_r, gp_r, 0);
- /* If that did any rotations, parentp and gparentp are now garbage.
- That doesn't matter, because the values they contain are never
- used again in that case. */
-
- nextp = r < 0 ? &root->left : &root->right;
- if (*nextp == NULL)
- break;
-
- gparentp = parentp;
- parentp = rootp;
- rootp = nextp;
-
- gp_r = p_r;
- p_r = r;
- }
-
- q = (struct node_t *) malloc (sizeof (struct node_t));
- if (q != NULL)
- {
- *nextp = q; /* link new node to old */
- q->key = key; /* initialize new node */
- q->red = 1;
- q->left = q->right = NULL;
-
- if (nextp != rootp)
- /* There may be two red edges in a row now, which we must avoid by
- rotating the tree. */
- maybe_split_for_insert (nextp, rootp, parentp, r, p_r, 1);
- }
-
- return q;
-}
-#ifdef weak_alias
-weak_alias (__tsearch, tsearch)
-#endif
-
-
-/* Find datum in search tree.
- KEY is the key to be located, ROOTP is the address of tree root,
- COMPAR the ordering function. */
-void *
-__tfind (key, vrootp, compar)
- const void *key;
- void *const *vrootp;
- __compar_fn_t compar;
-{
- node *rootp = (node *) vrootp;
-
- if (rootp == NULL)
- return NULL;
-
- CHECK_TREE (*rootp);
-
- while (*rootp != NULL)
- {
- node root = *rootp;
- int r;
-
- r = (*compar) (key, root->key);
- if (r == 0)
- return root;
-
- rootp = r < 0 ? &root->left : &root->right;
- }
- return NULL;
-}
-#ifdef weak_alias
-weak_alias (__tfind, tfind)
-#endif
-
-
-/* Delete node with given key.
- KEY is the key to be deleted, ROOTP is the address of the root of tree,
- COMPAR the comparison function. */
-void *
-__tdelete (const void *key, void **vrootp, __compar_fn_t compar)
-{
- node p, q, r, retval;
- int cmp;
- node *rootp = (node *) vrootp;
- node root, unchained;
- /* Stack of nodes so we remember the parents without recursion. It's
- _very_ unlikely that there are paths longer than 40 nodes. The tree
- would need to have around 250.000 nodes. */
- int stacksize = 100;
- int sp = 0;
- node *nodestack[100];
-
- if (rootp == NULL)
- return NULL;
- p = *rootp;
- if (p == NULL)
- return NULL;
-
- CHECK_TREE (p);
-
- while ((cmp = (*compar) (key, (*rootp)->key)) != 0)
- {
- if (sp == stacksize)
- abort ();
-
- nodestack[sp++] = rootp;
- p = *rootp;
- rootp = ((cmp < 0)
- ? &(*rootp)->left
- : &(*rootp)->right);
- if (*rootp == NULL)
- return NULL;
- }
-
- /* This is bogus if the node to be deleted is the root... this routine
- really should return an integer with 0 for success, -1 for failure
- and errno = ESRCH or something. */
- retval = p;
-
- /* We don't unchain the node we want to delete. Instead, we overwrite
- it with its successor and unchain the successor. If there is no
- successor, we really unchain the node to be deleted. */
-
- root = *rootp;
-
- r = root->right;
- q = root->left;
-
- if (q == NULL || r == NULL)
- unchained = root;
- else
- {
- node *parent = rootp, *up = &root->right;
- for (;;)
- {
- if (sp == stacksize)
- abort ();
- nodestack[sp++] = parent;
- parent = up;
- if ((*up)->left == NULL)
- break;
- up = &(*up)->left;
- }
- unchained = *up;
- }
-
- /* We know that either the left or right successor of UNCHAINED is NULL.
- R becomes the other one, it is chained into the parent of UNCHAINED. */
- r = unchained->left;
- if (r == NULL)
- r = unchained->right;
- if (sp == 0)
- *rootp = r;
- else
- {
- q = *nodestack[sp-1];
- if (unchained == q->right)
- q->right = r;
- else
- q->left = r;
- }
-
- if (unchained != root)
- root->key = unchained->key;
- if (!unchained->red)
- {
- /* Now we lost a black edge, which means that the number of black
- edges on every path is no longer constant. We must balance the
- tree. */
- /* NODESTACK now contains all parents of R. R is likely to be NULL
- in the first iteration. */
- /* NULL nodes are considered black throughout - this is necessary for
- correctness. */
- while (sp > 0 && (r == NULL || !r->red))
- {
- node *pp = nodestack[sp - 1];
- p = *pp;
- /* Two symmetric cases. */
- if (r == p->left)
- {
- /* Q is R's brother, P is R's parent. The subtree with root
- R has one black edge less than the subtree with root Q. */
- q = p->right;
- if (q->red)
- {
- /* If Q is red, we know that P is black. We rotate P left
- so that Q becomes the top node in the tree, with P below
- it. P is colored red, Q is colored black.
- This action does not change the black edge count for any
- leaf in the tree, but we will be able to recognize one
- of the following situations, which all require that Q
- is black. */
- q->red = 0;
- p->red = 1;
- /* Left rotate p. */
- p->right = q->left;
- q->left = p;
- *pp = q;
- /* Make sure pp is right if the case below tries to use
- it. */
- nodestack[sp++] = pp = &q->left;
- q = p->right;
- }
- /* We know that Q can't be NULL here. We also know that Q is
- black. */
- if ((q->left == NULL || !q->left->red)
- && (q->right == NULL || !q->right->red))
- {
- /* Q has two black successors. We can simply color Q red.
- The whole subtree with root P is now missing one black
- edge. Note that this action can temporarily make the
- tree invalid (if P is red). But we will exit the loop
- in that case and set P black, which both makes the tree
- valid and also makes the black edge count come out
- right. If P is black, we are at least one step closer
- to the root and we'll try again the next iteration. */
- q->red = 1;
- r = p;
- }
- else
- {
- /* Q is black, one of Q's successors is red. We can
- repair the tree with one operation and will exit the
- loop afterwards. */
- if (q->right == NULL || !q->right->red)
- {
- /* The left one is red. We perform the same action as
- in maybe_split_for_insert where two red edges are
- adjacent but point in different directions:
- Q's left successor (let's call it Q2) becomes the
- top of the subtree we are looking at, its parent (Q)
- and grandparent (P) become its successors. The former
- successors of Q2 are placed below P and Q.
- P becomes black, and Q2 gets the color that P had.
- This changes the black edge count only for node R and
- its successors. */
- node q2 = q->left;
- q2->red = p->red;
- p->right = q2->left;
- q->left = q2->right;
- q2->right = q;
- q2->left = p;
- *pp = q2;
- p->red = 0;
- }
- else
- {
- /* It's the right one. Rotate P left. P becomes black,
- and Q gets the color that P had. Q's right successor
- also becomes black. This changes the black edge
- count only for node R and its successors. */
- q->red = p->red;
- p->red = 0;
-
- q->right->red = 0;
-
- /* left rotate p */
- p->right = q->left;
- q->left = p;
- *pp = q;
- }
-
- /* We're done. */
- sp = 1;
- r = NULL;
- }
- }
- else
- {
- /* Comments: see above. */
- q = p->left;
- if (q->red)
- {
- q->red = 0;
- p->red = 1;
- p->left = q->right;
- q->right = p;
- *pp = q;
- nodestack[sp++] = pp = &q->right;
- q = p->left;
- }
- if ((q->right == NULL || !q->right->red)
- && (q->left == NULL || !q->left->red))
- {
- q->red = 1;
- r = p;
- }
- else
- {
- if (q->left == NULL || !q->left->red)
- {
- node q2 = q->right;
- q2->red = p->red;
- p->left = q2->right;
- q->right = q2->left;
- q2->left = q;
- q2->right = p;
- *pp = q2;
- p->red = 0;
- }
- else
- {
- q->red = p->red;
- p->red = 0;
- q->left->red = 0;
- p->left = q->right;
- q->right = p;
- *pp = q;
- }
- sp = 1;
- r = NULL;
- }
- }
- --sp;
- }
- if (r != NULL)
- r->red = 0;
- }
-
- free (unchained);
- return retval;
-}
-#ifdef weak_alias
-weak_alias (__tdelete, tdelete)
-#endif
-
-
-/* Walk the nodes of a tree.
- ROOT is the root of the tree to be walked, ACTION the function to be
- called at each node. LEVEL is the level of ROOT in the whole tree. */
-static void
-internal_function
-trecurse (const void *vroot, __action_fn_t action, int level)
-{
- const_node root = (const_node) vroot;
-
- if (root->left == NULL && root->right == NULL)
- (*action) (root, leaf, level);
- else
- {
- (*action) (root, preorder, level);
- if (root->left != NULL)
- trecurse (root->left, action, level + 1);
- (*action) (root, postorder, level);
- if (root->right != NULL)
- trecurse (root->right, action, level + 1);
- (*action) (root, endorder, level);
- }
-}
-
-
-/* Walk the nodes of a tree.
- ROOT is the root of the tree to be walked, ACTION the function to be
- called at each node. */
-void
-__twalk (const void *vroot, __action_fn_t action)
-{
- const_node root = (const_node) vroot;
-
- CHECK_TREE (root);
-
- if (root != NULL && action != NULL)
- trecurse (root, action, 0);
-}
-#ifdef weak_alias
-weak_alias (__twalk, twalk)
-#endif
-
-
-#ifdef _LIBC
-
-/* The standardized functions miss an important functionality: the
- tree cannot be removed easily. We provide a function to do this. */
-static void
-internal_function
-tdestroy_recurse (node root, __free_fn_t freefct)
-{
- if (root->left != NULL)
- tdestroy_recurse (root->left, freefct);
- if (root->right != NULL)
- tdestroy_recurse (root->right, freefct);
- (*freefct) ((void *) root->key);
- /* Free the node itself. */
- free (root);
-}
-
-void
-__tdestroy (void *vroot, __free_fn_t freefct)
-{
- node root = (node) vroot;
-
- CHECK_TREE (root);
-
- if (root != NULL)
- tdestroy_recurse (root, freefct);
-}
-weak_alias (__tdestroy, tdestroy)
-
-#endif /* _LIBC */
+++ /dev/null
-/* Binary tree data structure.
- Copyright (C) 2006 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-#ifndef _TSEARCH_H
-#define _TSEARCH_H
-
-#if HAVE_TSEARCH
-
-/* Get tseach(), tfind(), tdelete(), twalk() declarations. */
-#include <search.h>
-
-#else
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* See <http://www.opengroup.org/susv3xbd/search.h.html>,
- <http://www.opengroup.org/susv3xsh/tsearch.html>
- for details. */
-
-typedef enum
-{
- preorder,
- postorder,
- endorder,
- leaf
-}
-VISIT;
-
-/* Searches an element in the tree *VROOTP that compares equal to KEY.
- If one is found, it is returned. Otherwise, a new element equal to KEY
- is inserted in the tree and is returned. */
-extern void * tsearch (const void *key, void **vrootp,
- int (*compar) (const void *, const void *));
-
-/* Searches an element in the tree *VROOTP that compares equal to KEY.
- If one is found, it is returned. Otherwise, NULL is returned. */
-extern void * tfind (const void *key, void *const *vrootp,
- int (*compar) (const void *, const void *));
-
-/* Searches an element in the tree *VROOTP that compares equal to KEY.
- If one is found, it is removed from the tree, and its parent node is
- returned. Otherwise, NULL is returned. */
-extern void * tdelete (const void *key, void **vrootp,
- int (*compar) (const void *, const void *));
-
-/* Perform a depth-first, left-to-right traversal of the tree VROOT.
- The ACTION function is called:
- - for non-leaf nodes: 3 times, before the left subtree traversal,
- after the left subtree traversal but before the right subtree traversal,
- and after the right subtree traversal,
- - for leaf nodes: once.
- The arguments passed to ACTION are:
- 1. the node; it can be casted to a 'const void * const *', i.e. into a
- pointer to the key,
- 2. an indicator which visit of the node this is,
- 3. the level of the node in the tree (0 for the root). */
-extern void twalk (const void *vroot,
- void (*action) (const void *, VISIT, int));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-#endif /* _TSEARCH_H */
+++ /dev/null
-/* vsprintf with automatic memory allocation.
- Copyright (C) 1999, 2002-2020 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* This file can be parametrized with the following macros:
- VASNPRINTF The name of the function being defined.
- FCHAR_T The element type of the format string.
- DCHAR_T The element type of the destination (result) string.
- FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
- in the format string are ASCII. MUST be set if
- FCHAR_T and DCHAR_T are not the same type.
- DIRECTIVE Structure denoting a format directive.
- Depends on FCHAR_T.
- DIRECTIVES Structure denoting the set of format directives of a
- format string. Depends on FCHAR_T.
- PRINTF_PARSE Function that parses a format string.
- Depends on FCHAR_T.
- DCHAR_CPY memcpy like function for DCHAR_T[] arrays.
- DCHAR_SET memset like function for DCHAR_T[] arrays.
- DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays.
- SNPRINTF The system's snprintf (or similar) function.
- This may be either snprintf or swprintf.
- TCHAR_T The element type of the argument and result string
- of the said SNPRINTF function. This may be either
- char or wchar_t. The code exploits that
- sizeof (TCHAR_T) | sizeof (DCHAR_T) and
- alignof (TCHAR_T) <= alignof (DCHAR_T).
- DCHAR_IS_TCHAR Set to 1 if DCHAR_T and TCHAR_T are the same type.
- DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[].
- DCHAR_IS_UINT8_T Set to 1 if DCHAR_T is uint8_t.
- DCHAR_IS_UINT16_T Set to 1 if DCHAR_T is uint16_t.
- DCHAR_IS_UINT32_T Set to 1 if DCHAR_T is uint32_t.
- ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions.
- ENABLE_WCHAR_FALLBACK Set to 1 to avoid EILSEQ during conversion of wide
- characters (wchar_t) and wide character strings
- (wchar_t[]) to multibyte sequences. The fallback is the
- hexadecimal escape syntax (\unnnn or \Unnnnnnnn) or,
- if wchar_t is not Unicode encoded, \wnnnn or \Wnnnnnnnn.
- */
-
-/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
- This must come before <config.h> because <config.h> may include
- <features.h>, and once <features.h> has been included, it's too late. */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-
-#ifndef VASNPRINTF
-# include <config.h>
-#endif
-#ifndef IN_LIBINTL
-# include <alloca.h>
-#endif
-
-/* Specification. */
-#ifndef VASNPRINTF
-# if WIDE_CHAR_VERSION
-# include "vasnwprintf.h"
-# else
-# include "vasnprintf.h"
-# endif
-#endif
-
-#include <locale.h> /* localeconv() */
-#include <stdio.h> /* snprintf(), sprintf() */
-#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
-#include <string.h> /* memcpy(), strlen() */
-#include <errno.h> /* errno */
-#include <limits.h> /* CHAR_BIT */
-#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
-#if HAVE_NL_LANGINFO
-# include <langinfo.h>
-#endif
-#ifndef VASNPRINTF
-# if WIDE_CHAR_VERSION
-# include "wprintf-parse.h"
-# else
-# include "printf-parse.h"
-# endif
-#endif
-
-/* Checked size_t computations. */
-#include "xsize.h"
-
-#include "attribute.h"
-#include "verify.h"
-
-#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
-# include <math.h>
-# include "float+.h"
-#endif
-
-#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
-# include <math.h>
-# include "isnand-nolibm.h"
-#endif
-
-#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL
-# include <math.h>
-# include "isnanl-nolibm.h"
-# include "fpucw.h"
-#endif
-
-#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
-# include <math.h>
-# include "isnand-nolibm.h"
-# include "printf-frexp.h"
-#endif
-
-#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
-# include <math.h>
-# include "isnanl-nolibm.h"
-# include "printf-frexpl.h"
-# include "fpucw.h"
-#endif
-
-/* Default parameters. */
-#ifndef VASNPRINTF
-# if WIDE_CHAR_VERSION
-# define VASNPRINTF vasnwprintf
-# define FCHAR_T wchar_t
-# define DCHAR_T wchar_t
-# define TCHAR_T wchar_t
-# define DCHAR_IS_TCHAR 1
-# define DIRECTIVE wchar_t_directive
-# define DIRECTIVES wchar_t_directives
-# define PRINTF_PARSE wprintf_parse
-# define DCHAR_CPY wmemcpy
-# define DCHAR_SET wmemset
-# else
-# define VASNPRINTF vasnprintf
-# define FCHAR_T char
-# define DCHAR_T char
-# define TCHAR_T char
-# define DCHAR_IS_TCHAR 1
-# define DIRECTIVE char_directive
-# define DIRECTIVES char_directives
-# define PRINTF_PARSE printf_parse
-# define DCHAR_CPY memcpy
-# define DCHAR_SET memset
-# endif
-#endif
-#if WIDE_CHAR_VERSION
- /* TCHAR_T is wchar_t. */
-# define USE_SNPRINTF 1
-# if HAVE_DECL__SNWPRINTF
- /* On Windows, the function swprintf() has a different signature than
- on Unix; we use the function _snwprintf() or - on mingw - snwprintf()
- instead. The mingw function snwprintf() has fewer bugs than the
- MSVCRT function _snwprintf(), so prefer that. */
-# if defined __MINGW32__
-# define SNPRINTF snwprintf
-# else
-# define SNPRINTF _snwprintf
-# define USE_MSVC__SNPRINTF 1
-# endif
-# else
- /* Unix. */
-# define SNPRINTF swprintf
-# endif
-#else
- /* TCHAR_T is char. */
- /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
- But don't use it on BeOS, since BeOS snprintf produces no output if the
- size argument is >= 0x3000000.
- Also don't use it on Linux libc5, since there snprintf with size = 1
- writes any output without bounds, like sprintf. */
-# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1)
-# define USE_SNPRINTF 1
-# else
-# define USE_SNPRINTF 0
-# endif
-# if HAVE_DECL__SNPRINTF
- /* Windows. The mingw function snprintf() has fewer bugs than the MSVCRT
- function _snprintf(), so prefer that. */
-# if defined __MINGW32__
-# define SNPRINTF snprintf
- /* Here we need to call the native snprintf, not rpl_snprintf. */
-# undef snprintf
-# else
- /* MSVC versions < 14 did not have snprintf, only _snprintf. */
-# define SNPRINTF _snprintf
-# define USE_MSVC__SNPRINTF 1
-# endif
-# else
- /* Unix. */
-# define SNPRINTF snprintf
- /* Here we need to call the native snprintf, not rpl_snprintf. */
-# undef snprintf
-# endif
-#endif
-/* Here we need to call the native sprintf, not rpl_sprintf. */
-#undef sprintf
-
-/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized"
- warnings in this file. Use -Dlint to suppress them. */
-#if defined GCC_LINT || defined lint
-# define IF_LINT(Code) Code
-#else
-# define IF_LINT(Code) /* empty */
-#endif
-
-/* Avoid some warnings from "gcc -Wshadow".
- This file doesn't use the exp() and remainder() functions. */
-#undef exp
-#define exp expo
-#undef remainder
-#define remainder rem
-
-#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && !WIDE_CHAR_VERSION
-# if (HAVE_STRNLEN && !defined _AIX)
-# define local_strnlen strnlen
-# else
-# ifndef local_strnlen_defined
-# define local_strnlen_defined 1
-static size_t
-local_strnlen (const char *string, size_t maxlen)
-{
- const char *end = memchr (string, '\0', maxlen);
- return end ? (size_t) (end - string) : maxlen;
-}
-# endif
-# endif
-#endif
-
-#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T
-# if HAVE_WCSLEN
-# define local_wcslen wcslen
-# else
- /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
- a dependency towards this library, here is a local substitute.
- Define this substitute only once, even if this file is included
- twice in the same compilation unit. */
-# ifndef local_wcslen_defined
-# define local_wcslen_defined 1
-static size_t
-local_wcslen (const wchar_t *s)
-{
- const wchar_t *ptr;
-
- for (ptr = s; *ptr != (wchar_t) 0; ptr++)
- ;
- return ptr - s;
-}
-# endif
-# endif
-#endif
-
-#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && HAVE_WCHAR_T && WIDE_CHAR_VERSION
-# if HAVE_WCSNLEN
-# define local_wcsnlen wcsnlen
-# else
-# ifndef local_wcsnlen_defined
-# define local_wcsnlen_defined 1
-static size_t
-local_wcsnlen (const wchar_t *s, size_t maxlen)
-{
- const wchar_t *ptr;
-
- for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--)
- ;
- return ptr - s;
-}
-# endif
-# endif
-#endif
-
-#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL) || ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T) || (ENABLE_WCHAR_FALLBACK && HAVE_WINT_T)) && !WIDE_CHAR_VERSION
-# if ENABLE_WCHAR_FALLBACK
-static size_t
-wctomb_fallback (char *s, wchar_t wc)
-{
- static char hex[16] = "0123456789ABCDEF";
-
- s[0] = '\\';
- if (sizeof (wchar_t) > 2 && wc > 0xffff)
- {
-# if __STDC_ISO_10646__ || (__GLIBC__ >= 2) || (defined _WIN32 || defined __CYGWIN__)
- s[1] = 'U';
-# else
- s[1] = 'W';
-# endif
- s[2] = hex[(wc & 0xf0000000U) >> 28];
- s[3] = hex[(wc & 0xf000000U) >> 24];
- s[4] = hex[(wc & 0xf00000U) >> 20];
- s[5] = hex[(wc & 0xf0000U) >> 16];
- s[6] = hex[(wc & 0xf000U) >> 12];
- s[7] = hex[(wc & 0xf00U) >> 8];
- s[8] = hex[(wc & 0xf0U) >> 4];
- s[9] = hex[wc & 0xfU];
- return 10;
- }
- else
- {
-# if __STDC_ISO_10646__ || (__GLIBC__ >= 2) || (defined _WIN32 || defined __CYGWIN__)
- s[1] = 'u';
-# else
- s[1] = 'w';
-# endif
- s[2] = hex[(wc & 0xf000U) >> 12];
- s[3] = hex[(wc & 0xf00U) >> 8];
- s[4] = hex[(wc & 0xf0U) >> 4];
- s[5] = hex[wc & 0xfU];
- return 6;
- }
-}
-# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
-static size_t
-local_wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
-{
- size_t count = wcrtomb (s, wc, ps);
- if (count == (size_t)(-1))
- count = wctomb_fallback (s, wc);
- return count;
-}
-# else
-static int
-local_wctomb (char *s, wchar_t wc)
-{
- int count = wctomb (s, wc);
- if (count < 0)
- count = wctomb_fallback (s, wc);
- return count;
-}
-# define local_wcrtomb(S, WC, PS) local_wctomb ((S), (WC))
-# endif
-# else
-# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
-# define local_wcrtomb(S, WC, PS) wcrtomb ((S), (WC), (PS))
-# else
-# define local_wcrtomb(S, WC, PS) wctomb ((S), (WC))
-# endif
-# endif
-#endif
-
-#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
-/* Determine the decimal-point character according to the current locale. */
-# ifndef decimal_point_char_defined
-# define decimal_point_char_defined 1
-static char
-decimal_point_char (void)
-{
- const char *point;
- /* Determine it in a multithread-safe way. We know nl_langinfo is
- multithread-safe on glibc systems and Mac OS X systems, but is not required
- to be multithread-safe by POSIX. sprintf(), however, is multithread-safe.
- localeconv() is rarely multithread-safe. */
-# if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__))
- point = nl_langinfo (RADIXCHAR);
-# elif 1
- char pointbuf[5];
- sprintf (pointbuf, "%#.0f", 1.0);
- point = &pointbuf[1];
-# else
- point = localeconv () -> decimal_point;
-# endif
- /* The decimal point is always a single byte: either '.' or ','. */
- return (point[0] != '\0' ? point[0] : '.');
-}
-# endif
-#endif
-
-#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL
-
-/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
-static int
-is_infinite_or_zero (double x)
-{
- return isnand (x) || x + x == x;
-}
-
-#endif
-
-#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
-
-/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
-static int
-is_infinite_or_zerol (long double x)
-{
- return isnanl (x) || x + x == x;
-}
-
-#endif
-
-#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
-
-/* Converting 'long double' to decimal without rare rounding bugs requires
- real bignums. We use the naming conventions of GNU gmp, but vastly simpler
- (and slower) algorithms. */
-
-typedef unsigned int mp_limb_t;
-# define GMP_LIMB_BITS 32
-verify (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS);
-
-typedef unsigned long long mp_twolimb_t;
-# define GMP_TWOLIMB_BITS 64
-verify (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS);
-
-/* Representation of a bignum >= 0. */
-typedef struct
-{
- size_t nlimbs;
- mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc(). */
-} mpn_t;
-
-/* Compute the product of two bignums >= 0.
- Return the allocated memory in case of success, NULL in case of memory
- allocation failure. */
-static void *
-multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
-{
- const mp_limb_t *p1;
- const mp_limb_t *p2;
- size_t len1;
- size_t len2;
-
- if (src1.nlimbs <= src2.nlimbs)
- {
- len1 = src1.nlimbs;
- p1 = src1.limbs;
- len2 = src2.nlimbs;
- p2 = src2.limbs;
- }
- else
- {
- len1 = src2.nlimbs;
- p1 = src2.limbs;
- len2 = src1.nlimbs;
- p2 = src1.limbs;
- }
- /* Now 0 <= len1 <= len2. */
- if (len1 == 0)
- {
- /* src1 or src2 is zero. */
- dest->nlimbs = 0;
- dest->limbs = (mp_limb_t *) malloc (1);
- }
- else
- {
- /* Here 1 <= len1 <= len2. */
- size_t dlen;
- mp_limb_t *dp;
- size_t k, i, j;
-
- dlen = len1 + len2;
- dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
- if (dp == NULL)
- return NULL;
- for (k = len2; k > 0; )
- dp[--k] = 0;
- for (i = 0; i < len1; i++)
- {
- mp_limb_t digit1 = p1[i];
- mp_twolimb_t carry = 0;
- for (j = 0; j < len2; j++)
- {
- mp_limb_t digit2 = p2[j];
- carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
- carry += dp[i + j];
- dp[i + j] = (mp_limb_t) carry;
- carry = carry >> GMP_LIMB_BITS;
- }
- dp[i + len2] = (mp_limb_t) carry;
- }
- /* Normalise. */
- while (dlen > 0 && dp[dlen - 1] == 0)
- dlen--;
- dest->nlimbs = dlen;
- dest->limbs = dp;
- }
- return dest->limbs;
-}
-
-/* Compute the quotient of a bignum a >= 0 and a bignum b > 0.
- a is written as a = q * b + r with 0 <= r < b. q is the quotient, r
- the remainder.
- Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
- q is incremented.
- Return the allocated memory in case of success, NULL in case of memory
- allocation failure. */
-static void *
-divide (mpn_t a, mpn_t b, mpn_t *q)
-{
- /* Algorithm:
- First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
- with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS).
- If m<n, then q:=0 and r:=a.
- If m>=n=1, perform a single-precision division:
- r:=0, j:=m,
- while j>0 do
- {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
- = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}
- j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
- Normalise [q[m-1],...,q[0]], yields q.
- If m>=n>1, perform a multiple-precision division:
- We have a/b < beta^(m-n+1).
- s:=intDsize-1-(highest bit in b[n-1]), 0<=s<intDsize.
- Shift a and b left by s bits, copying them. r:=a.
- r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2.
- For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}
- Compute q* :
- q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
- In case of overflow (q* >= beta) set q* := beta-1.
- Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
- and c3 := b[n-2] * q*.
- {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow
- occurred. Furthermore 0 <= c3 < beta^2.
- If there was overflow and
- r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2,
- the next test can be skipped.}
- While c3 > c2, {Here 0 <= c2 < c3 < beta^2}
- Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
- If q* > 0:
- Put r := r - b * q* * beta^j. In detail:
- [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
- hence: u:=0, for i:=0 to n-1 do
- u := u + q* * b[i],
- r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry),
- u:=u div beta (+ 1, if carry in subtraction)
- r[n+j]:=r[n+j]-u.
- {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
- < q* + 1 <= beta,
- the carry u does not overflow.}
- If a negative carry occurs, put q* := q* - 1
- and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
- Set q[j] := q*.
- Normalise [q[m-n],..,q[0]]; this yields the quotient q.
- Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the
- rest r.
- The room for q[j] can be allocated at the memory location of r[n+j].
- Finally, round-to-even:
- Shift r left by 1 bit.
- If r > b or if r = b and q[0] is odd, q := q+1.
- */
- const mp_limb_t *a_ptr = a.limbs;
- size_t a_len = a.nlimbs;
- const mp_limb_t *b_ptr = b.limbs;
- size_t b_len = b.nlimbs;
- mp_limb_t *roomptr;
- mp_limb_t *tmp_roomptr = NULL;
- mp_limb_t *q_ptr;
- size_t q_len;
- mp_limb_t *r_ptr;
- size_t r_len;
-
- /* Allocate room for a_len+2 digits.
- (Need a_len+1 digits for the real division and 1 more digit for the
- final rounding of q.) */
- roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
- if (roomptr == NULL)
- return NULL;
-
- /* Normalise a. */
- while (a_len > 0 && a_ptr[a_len - 1] == 0)
- a_len--;
-
- /* Normalise b. */
- for (;;)
- {
- if (b_len == 0)
- /* Division by zero. */
- abort ();
- if (b_ptr[b_len - 1] == 0)
- b_len--;
- else
- break;
- }
-
- /* Here m = a_len >= 0 and n = b_len > 0. */
-
- if (a_len < b_len)
- {
- /* m<n: trivial case. q=0, r := copy of a. */
- r_ptr = roomptr;
- r_len = a_len;
- memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
- q_ptr = roomptr + a_len;
- q_len = 0;
- }
- else if (b_len == 1)
- {
- /* n=1: single precision division.
- beta^(m-1) <= a < beta^m ==> beta^(m-2) <= a/b < beta^m */
- r_ptr = roomptr;
- q_ptr = roomptr + 1;
- {
- mp_limb_t den = b_ptr[0];
- mp_limb_t remainder = 0;
- const mp_limb_t *sourceptr = a_ptr + a_len;
- mp_limb_t *destptr = q_ptr + a_len;
- size_t count;
- for (count = a_len; count > 0; count--)
- {
- mp_twolimb_t num =
- ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;
- *--destptr = num / den;
- remainder = num % den;
- }
- /* Normalise and store r. */
- if (remainder > 0)
- {
- r_ptr[0] = remainder;
- r_len = 1;
- }
- else
- r_len = 0;
- /* Normalise q. */
- q_len = a_len;
- if (q_ptr[q_len - 1] == 0)
- q_len--;
- }
- }
- else
- {
- /* n>1: multiple precision division.
- beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==>
- beta^(m-n-1) <= a/b < beta^(m-n+1). */
- /* Determine s. */
- size_t s;
- {
- mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */
- /* Determine s = GMP_LIMB_BITS - integer_length (msd).
- Code copied from gnulib's integer_length.c. */
-# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \
- || (__clang_major__ >= 4)
- s = __builtin_clz (msd);
-# else
-# if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
- if (GMP_LIMB_BITS <= DBL_MANT_BIT)
- {
- /* Use 'double' operations.
- Assumes an IEEE 754 'double' implementation. */
-# define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7)
-# define DBL_EXP_BIAS (DBL_EXP_MASK / 2 - 1)
-# define NWORDS \
- ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
- union { double value; unsigned int word[NWORDS]; } m;
-
- /* Use a single integer to floating-point conversion. */
- m.value = msd;
-
- s = GMP_LIMB_BITS
- - (((m.word[DBL_EXPBIT0_WORD] >> DBL_EXPBIT0_BIT) & DBL_EXP_MASK)
- - DBL_EXP_BIAS);
- }
- else
-# undef NWORDS
-# endif
- {
- s = 31;
- if (msd >= 0x10000)
- {
- msd = msd >> 16;
- s -= 16;
- }
- if (msd >= 0x100)
- {
- msd = msd >> 8;
- s -= 8;
- }
- if (msd >= 0x10)
- {
- msd = msd >> 4;
- s -= 4;
- }
- if (msd >= 0x4)
- {
- msd = msd >> 2;
- s -= 2;
- }
- if (msd >= 0x2)
- {
- msd = msd >> 1;
- s -= 1;
- }
- }
-# endif
- }
- /* 0 <= s < GMP_LIMB_BITS.
- Copy b, shifting it left by s bits. */
- if (s > 0)
- {
- tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t));
- if (tmp_roomptr == NULL)
- {
- free (roomptr);
- return NULL;
- }
- {
- const mp_limb_t *sourceptr = b_ptr;
- mp_limb_t *destptr = tmp_roomptr;
- mp_twolimb_t accu = 0;
- size_t count;
- for (count = b_len; count > 0; count--)
- {
- accu += (mp_twolimb_t) *sourceptr++ << s;
- *destptr++ = (mp_limb_t) accu;
- accu = accu >> GMP_LIMB_BITS;
- }
- /* accu must be zero, since that was how s was determined. */
- if (accu != 0)
- abort ();
- }
- b_ptr = tmp_roomptr;
- }
- /* Copy a, shifting it left by s bits, yields r.
- Memory layout:
- At the beginning: r = roomptr[0..a_len],
- at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len] */
- r_ptr = roomptr;
- if (s == 0)
- {
- memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
- r_ptr[a_len] = 0;
- }
- else
- {
- const mp_limb_t *sourceptr = a_ptr;
- mp_limb_t *destptr = r_ptr;
- mp_twolimb_t accu = 0;
- size_t count;
- for (count = a_len; count > 0; count--)
- {
- accu += (mp_twolimb_t) *sourceptr++ << s;
- *destptr++ = (mp_limb_t) accu;
- accu = accu >> GMP_LIMB_BITS;
- }
- *destptr++ = (mp_limb_t) accu;
- }
- q_ptr = roomptr + b_len;
- q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */
- {
- size_t j = a_len - b_len; /* m-n */
- mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */
- mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */
- mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */
- ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd;
- /* Division loop, traversed m-n+1 times.
- j counts down, b is unchanged, beta/2 <= b[n-1] < beta. */
- for (;;)
- {
- mp_limb_t q_star;
- mp_limb_t c1;
- if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */
- {
- /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow. */
- mp_twolimb_t num =
- ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS)
- | r_ptr[j + b_len - 1];
- q_star = num / b_msd;
- c1 = num % b_msd;
- }
- else
- {
- /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1]. */
- q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */
- /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
- <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
- <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta)
- {<= beta !}.
- If yes, jump directly to the subtraction loop.
- (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
- <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */
- if (r_ptr[j + b_len] > b_msd
- || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd)
- /* r[j+n] >= b[n-1]+1 or
- r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a
- carry. */
- goto subtract;
- }
- /* q_star = q*,
- c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta). */
- {
- mp_twolimb_t c2 = /* c1*beta+r[j+n-2] */
- ((mp_twolimb_t) c1 << GMP_LIMB_BITS) | r_ptr[j + b_len - 2];
- mp_twolimb_t c3 = /* b[n-2] * q* */
- (mp_twolimb_t) b_2msd * (mp_twolimb_t) q_star;
- /* While c2 < c3, increase c2 and decrease c3.
- Consider c3-c2. While it is > 0, decrease it by
- b[n-1]*beta+b[n-2]. Because of b[n-1]*beta+b[n-2] >= beta^2/2
- this can happen only twice. */
- if (c3 > c2)
- {
- q_star = q_star - 1; /* q* := q* - 1 */
- if (c3 - c2 > b_msdd)
- q_star = q_star - 1; /* q* := q* - 1 */
- }
- }
- if (q_star > 0)
- subtract:
- {
- /* Subtract r := r - b * q* * beta^j. */
- mp_limb_t cr;
- {
- const mp_limb_t *sourceptr = b_ptr;
- mp_limb_t *destptr = r_ptr + j;
- mp_twolimb_t carry = 0;
- size_t count;
- for (count = b_len; count > 0; count--)
- {
- /* Here 0 <= carry <= q*. */
- carry =
- carry
- + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++
- + (mp_limb_t) ~(*destptr);
- /* Here 0 <= carry <= beta*q* + beta-1. */
- *destptr++ = ~(mp_limb_t) carry;
- carry = carry >> GMP_LIMB_BITS; /* <= q* */
- }
- cr = (mp_limb_t) carry;
- }
- /* Subtract cr from r_ptr[j + b_len], then forget about
- r_ptr[j + b_len]. */
- if (cr > r_ptr[j + b_len])
- {
- /* Subtraction gave a carry. */
- q_star = q_star - 1; /* q* := q* - 1 */
- /* Add b back. */
- {
- const mp_limb_t *sourceptr = b_ptr;
- mp_limb_t *destptr = r_ptr + j;
- mp_limb_t carry = 0;
- size_t count;
- for (count = b_len; count > 0; count--)
- {
- mp_limb_t source1 = *sourceptr++;
- mp_limb_t source2 = *destptr;
- *destptr++ = source1 + source2 + carry;
- carry =
- (carry
- ? source1 >= (mp_limb_t) ~source2
- : source1 > (mp_limb_t) ~source2);
- }
- }
- /* Forget about the carry and about r[j+n]. */
- }
- }
- /* q* is determined. Store it as q[j]. */
- q_ptr[j] = q_star;
- if (j == 0)
- break;
- j--;
- }
- }
- r_len = b_len;
- /* Normalise q. */
- if (q_ptr[q_len - 1] == 0)
- q_len--;
-# if 0 /* Not needed here, since we need r only to compare it with b/2, and
- b is shifted left by s bits. */
- /* Shift r right by s bits. */
- if (s > 0)
- {
- mp_limb_t ptr = r_ptr + r_len;
- mp_twolimb_t accu = 0;
- size_t count;
- for (count = r_len; count > 0; count--)
- {
- accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS;
- accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s);
- *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS);
- }
- }
-# endif
- /* Normalise r. */
- while (r_len > 0 && r_ptr[r_len - 1] == 0)
- r_len--;
- }
- /* Compare r << 1 with b. */
- if (r_len > b_len)
- goto increment_q;
- {
- size_t i;
- for (i = b_len;;)
- {
- mp_limb_t r_i =
- (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0)
- | (i < r_len ? r_ptr[i] << 1 : 0);
- mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0);
- if (r_i > b_i)
- goto increment_q;
- if (r_i < b_i)
- goto keep_q;
- if (i == 0)
- break;
- i--;
- }
- }
- if (q_len > 0 && ((q_ptr[0] & 1) != 0))
- /* q is odd. */
- increment_q:
- {
- size_t i;
- for (i = 0; i < q_len; i++)
- if (++(q_ptr[i]) != 0)
- goto keep_q;
- q_ptr[q_len++] = 1;
- }
- keep_q:
- if (tmp_roomptr != NULL)
- free (tmp_roomptr);
- q->limbs = q_ptr;
- q->nlimbs = q_len;
- return roomptr;
-}
-
-/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal
- representation.
- Destroys the contents of a.
- Return the allocated memory - containing the decimal digits in low-to-high
- order, terminated with a NUL character - in case of success, NULL in case
- of memory allocation failure. */
-static char *
-convert_to_decimal (mpn_t a, size_t extra_zeroes)
-{
- mp_limb_t *a_ptr = a.limbs;
- size_t a_len = a.nlimbs;
- /* 0.03345 is slightly larger than log(2)/(9*log(10)). */
- size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1);
- /* We need extra_zeroes bytes for zeroes, followed by c_len bytes for the
- digits of a, followed by 1 byte for the terminating NUL. */
- char *c_ptr = (char *) malloc (xsum (xsum (extra_zeroes, c_len), 1));
- if (c_ptr != NULL)
- {
- char *d_ptr = c_ptr;
- for (; extra_zeroes > 0; extra_zeroes--)
- *d_ptr++ = '0';
- while (a_len > 0)
- {
- /* Divide a by 10^9, in-place. */
- mp_limb_t remainder = 0;
- mp_limb_t *ptr = a_ptr + a_len;
- size_t count;
- for (count = a_len; count > 0; count--)
- {
- mp_twolimb_t num =
- ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr;
- *ptr = num / 1000000000;
- remainder = num % 1000000000;
- }
- /* Store the remainder as 9 decimal digits. */
- for (count = 9; count > 0; count--)
- {
- *d_ptr++ = '0' + (remainder % 10);
- remainder = remainder / 10;
- }
- /* Normalize a. */
- if (a_ptr[a_len - 1] == 0)
- a_len--;
- }
- /* Remove leading zeroes. */
- while (d_ptr > c_ptr && d_ptr[-1] == '0')
- d_ptr--;
- /* But keep at least one zero. */
- if (d_ptr == c_ptr)
- *d_ptr++ = '0';
- /* Terminate the string. */
- *d_ptr = '\0';
- }
- return c_ptr;
-}
-
-# if NEED_PRINTF_LONG_DOUBLE
-
-/* Assuming x is finite and >= 0:
- write x as x = 2^e * m, where m is a bignum.
- Return the allocated memory in case of success, NULL in case of memory
- allocation failure. */
-static void *
-decode_long_double (long double x, int *ep, mpn_t *mp)
-{
- mpn_t m;
- int exp;
- long double y;
- size_t i;
-
- /* Allocate memory for result. */
- m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
- m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
- if (m.limbs == NULL)
- return NULL;
- /* Split into exponential part and mantissa. */
- y = frexpl (x, &exp);
- if (!(y >= 0.0L && y < 1.0L))
- abort ();
- /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the
- latter is an integer. */
- /* Convert the mantissa (y * 2^LDBL_MANT_BIT) to a sequence of limbs.
- I'm not sure whether it's safe to cast a 'long double' value between
- 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
- 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
- doesn't matter). */
-# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
-# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
- {
- mp_limb_t hi, lo;
- y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2));
- hi = (int) y;
- y -= hi;
- if (!(y >= 0.0L && y < 1.0L))
- abort ();
- y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
- lo = (int) y;
- y -= lo;
- if (!(y >= 0.0L && y < 1.0L))
- abort ();
- m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
- }
-# else
- {
- mp_limb_t d;
- y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS);
- d = (int) y;
- y -= d;
- if (!(y >= 0.0L && y < 1.0L))
- abort ();
- m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d;
- }
-# endif
-# endif
- for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
- {
- mp_limb_t hi, lo;
- y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
- hi = (int) y;
- y -= hi;
- if (!(y >= 0.0L && y < 1.0L))
- abort ();
- y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
- lo = (int) y;
- y -= lo;
- if (!(y >= 0.0L && y < 1.0L))
- abort ();
- m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
- }
-# if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess
- precision. */
- if (!(y == 0.0L))
- abort ();
-# endif
- /* Normalise. */
- while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
- m.nlimbs--;
- *mp = m;
- *ep = exp - LDBL_MANT_BIT;
- return m.limbs;
-}
-
-# endif
-
-# if NEED_PRINTF_DOUBLE
-
-/* Assuming x is finite and >= 0:
- write x as x = 2^e * m, where m is a bignum.
- Return the allocated memory in case of success, NULL in case of memory
- allocation failure. */
-static void *
-decode_double (double x, int *ep, mpn_t *mp)
-{
- mpn_t m;
- int exp;
- double y;
- size_t i;
-
- /* Allocate memory for result. */
- m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
- m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
- if (m.limbs == NULL)
- return NULL;
- /* Split into exponential part and mantissa. */
- y = frexp (x, &exp);
- if (!(y >= 0.0 && y < 1.0))
- abort ();
- /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * 2^DBL_MANT_BIT), and the
- latter is an integer. */
- /* Convert the mantissa (y * 2^DBL_MANT_BIT) to a sequence of limbs.
- I'm not sure whether it's safe to cast a 'double' value between
- 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
- 'double' values between 0 and 2^16 (to 'unsigned int' or 'int',
- doesn't matter). */
-# if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0
-# if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
- {
- mp_limb_t hi, lo;
- y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2));
- hi = (int) y;
- y -= hi;
- if (!(y >= 0.0 && y < 1.0))
- abort ();
- y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
- lo = (int) y;
- y -= lo;
- if (!(y >= 0.0 && y < 1.0))
- abort ();
- m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
- }
-# else
- {
- mp_limb_t d;
- y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS);
- d = (int) y;
- y -= d;
- if (!(y >= 0.0 && y < 1.0))
- abort ();
- m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d;
- }
-# endif
-# endif
- for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
- {
- mp_limb_t hi, lo;
- y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
- hi = (int) y;
- y -= hi;
- if (!(y >= 0.0 && y < 1.0))
- abort ();
- y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
- lo = (int) y;
- y -= lo;
- if (!(y >= 0.0 && y < 1.0))
- abort ();
- m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
- }
- if (!(y == 0.0))
- abort ();
- /* Normalise. */
- while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
- m.nlimbs--;
- *mp = m;
- *ep = exp - DBL_MANT_BIT;
- return m.limbs;
-}
-
-# endif
-
-/* Assuming x = 2^e * m is finite and >= 0, and n is an integer:
- Returns the decimal representation of round (x * 10^n).
- Return the allocated memory - containing the decimal digits in low-to-high
- order, terminated with a NUL character - in case of success, NULL in case
- of memory allocation failure. */
-static char *
-scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
-{
- int s;
- size_t extra_zeroes;
- unsigned int abs_n;
- unsigned int abs_s;
- mp_limb_t *pow5_ptr;
- size_t pow5_len;
- unsigned int s_limbs;
- unsigned int s_bits;
- mpn_t pow5;
- mpn_t z;
- void *z_memory;
- char *digits;
-
- if (memory == NULL)
- return NULL;
- /* x = 2^e * m, hence
- y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
- = round (2^s * 5^n * m). */
- s = e + n;
- extra_zeroes = 0;
- /* Factor out a common power of 10 if possible. */
- if (s > 0 && n > 0)
- {
- extra_zeroes = (s < n ? s : n);
- s -= extra_zeroes;
- n -= extra_zeroes;
- }
- /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes.
- Before converting to decimal, we need to compute
- z = round (2^s * 5^n * m). */
- /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same
- sign. 2.322 is slightly larger than log(5)/log(2). */
- abs_n = (n >= 0 ? n : -n);
- abs_s = (s >= 0 ? s : -s);
- pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1
- + abs_s / GMP_LIMB_BITS + 1)
- * sizeof (mp_limb_t));
- if (pow5_ptr == NULL)
- {
- free (memory);
- return NULL;
- }
- /* Initialize with 1. */
- pow5_ptr[0] = 1;
- pow5_len = 1;
- /* Multiply with 5^|n|. */
- if (abs_n > 0)
- {
- static mp_limb_t const small_pow5[13 + 1] =
- {
- 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
- 48828125, 244140625, 1220703125
- };
- unsigned int n13;
- for (n13 = 0; n13 <= abs_n; n13 += 13)
- {
- mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13];
- size_t j;
- mp_twolimb_t carry = 0;
- for (j = 0; j < pow5_len; j++)
- {
- mp_limb_t digit2 = pow5_ptr[j];
- carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
- pow5_ptr[j] = (mp_limb_t) carry;
- carry = carry >> GMP_LIMB_BITS;
- }
- if (carry > 0)
- pow5_ptr[pow5_len++] = (mp_limb_t) carry;
- }
- }
- s_limbs = abs_s / GMP_LIMB_BITS;
- s_bits = abs_s % GMP_LIMB_BITS;
- if (n >= 0 ? s >= 0 : s <= 0)
- {
- /* Multiply with 2^|s|. */
- if (s_bits > 0)
- {
- mp_limb_t *ptr = pow5_ptr;
- mp_twolimb_t accu = 0;
- size_t count;
- for (count = pow5_len; count > 0; count--)
- {
- accu += (mp_twolimb_t) *ptr << s_bits;
- *ptr++ = (mp_limb_t) accu;
- accu = accu >> GMP_LIMB_BITS;
- }
- if (accu > 0)
- {
- *ptr = (mp_limb_t) accu;
- pow5_len++;
- }
- }
- if (s_limbs > 0)
- {
- size_t count;
- for (count = pow5_len; count > 0;)
- {
- count--;
- pow5_ptr[s_limbs + count] = pow5_ptr[count];
- }
- for (count = s_limbs; count > 0;)
- {
- count--;
- pow5_ptr[count] = 0;
- }
- pow5_len += s_limbs;
- }
- pow5.limbs = pow5_ptr;
- pow5.nlimbs = pow5_len;
- if (n >= 0)
- {
- /* Multiply m with pow5. No division needed. */
- z_memory = multiply (m, pow5, &z);
- }
- else
- {
- /* Divide m by pow5 and round. */
- z_memory = divide (m, pow5, &z);
- }
- }
- else
- {
- pow5.limbs = pow5_ptr;
- pow5.nlimbs = pow5_len;
- if (n >= 0)
- {
- /* n >= 0, s < 0.
- Multiply m with pow5, then divide by 2^|s|. */
- mpn_t numerator;
- mpn_t denominator;
- void *tmp_memory;
- tmp_memory = multiply (m, pow5, &numerator);
- if (tmp_memory == NULL)
- {
- free (pow5_ptr);
- free (memory);
- return NULL;
- }
- /* Construct 2^|s|. */
- {
- mp_limb_t *ptr = pow5_ptr + pow5_len;
- size_t i;
- for (i = 0; i < s_limbs; i++)
- ptr[i] = 0;
- ptr[s_limbs] = (mp_limb_t) 1 << s_bits;
- denominator.limbs = ptr;
- denominator.nlimbs = s_limbs + 1;
- }
- z_memory = divide (numerator, denominator, &z);
- free (tmp_memory);
- }
- else
- {
- /* n < 0, s > 0.
- Multiply m with 2^s, then divide by pow5. */
- mpn_t numerator;
- mp_limb_t *num_ptr;
- num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1)
- * sizeof (mp_limb_t));
- if (num_ptr == NULL)
- {
- free (pow5_ptr);
- free (memory);
- return NULL;
- }
- {
- mp_limb_t *destptr = num_ptr;
- {
- size_t i;
- for (i = 0; i < s_limbs; i++)
- *destptr++ = 0;
- }
- if (s_bits > 0)
- {
- const mp_limb_t *sourceptr = m.limbs;
- mp_twolimb_t accu = 0;
- size_t count;
- for (count = m.nlimbs; count > 0; count--)
- {
- accu += (mp_twolimb_t) *sourceptr++ << s_bits;
- *destptr++ = (mp_limb_t) accu;
- accu = accu >> GMP_LIMB_BITS;
- }
- if (accu > 0)
- *destptr++ = (mp_limb_t) accu;
- }
- else
- {
- const mp_limb_t *sourceptr = m.limbs;
- size_t count;
- for (count = m.nlimbs; count > 0; count--)
- *destptr++ = *sourceptr++;
- }
- numerator.limbs = num_ptr;
- numerator.nlimbs = destptr - num_ptr;
- }
- z_memory = divide (numerator, pow5, &z);
- free (num_ptr);
- }
- }
- free (pow5_ptr);
- free (memory);
-
- /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */
-
- if (z_memory == NULL)
- return NULL;
- digits = convert_to_decimal (z, extra_zeroes);
- free (z_memory);
- return digits;
-}
-
-# if NEED_PRINTF_LONG_DOUBLE
-
-/* Assuming x is finite and >= 0, and n is an integer:
- Returns the decimal representation of round (x * 10^n).
- Return the allocated memory - containing the decimal digits in low-to-high
- order, terminated with a NUL character - in case of success, NULL in case
- of memory allocation failure. */
-static char *
-scale10_round_decimal_long_double (long double x, int n)
-{
- int e IF_LINT(= 0);
- mpn_t m;
- void *memory = decode_long_double (x, &e, &m);
- return scale10_round_decimal_decoded (e, m, memory, n);
-}
-
-# endif
-
-# if NEED_PRINTF_DOUBLE
-
-/* Assuming x is finite and >= 0, and n is an integer:
- Returns the decimal representation of round (x * 10^n).
- Return the allocated memory - containing the decimal digits in low-to-high
- order, terminated with a NUL character - in case of success, NULL in case
- of memory allocation failure. */
-static char *
-scale10_round_decimal_double (double x, int n)
-{
- int e IF_LINT(= 0);
- mpn_t m;
- void *memory = decode_double (x, &e, &m);
- return scale10_round_decimal_decoded (e, m, memory, n);
-}
-
-# endif
-
-# if NEED_PRINTF_LONG_DOUBLE
-
-/* Assuming x is finite and > 0:
- Return an approximation for n with 10^n <= x < 10^(n+1).
- The approximation is usually the right n, but may be off by 1 sometimes. */
-static int
-floorlog10l (long double x)
-{
- int exp;
- long double y;
- double z;
- double l;
-
- /* Split into exponential part and mantissa. */
- y = frexpl (x, &exp);
- if (!(y >= 0.0L && y < 1.0L))
- abort ();
- if (y == 0.0L)
- return INT_MIN;
- if (y < 0.5L)
- {
- while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
- {
- y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
- exp -= GMP_LIMB_BITS;
- }
- if (y < (1.0L / (1 << 16)))
- {
- y *= 1.0L * (1 << 16);
- exp -= 16;
- }
- if (y < (1.0L / (1 << 8)))
- {
- y *= 1.0L * (1 << 8);
- exp -= 8;
- }
- if (y < (1.0L / (1 << 4)))
- {
- y *= 1.0L * (1 << 4);
- exp -= 4;
- }
- if (y < (1.0L / (1 << 2)))
- {
- y *= 1.0L * (1 << 2);
- exp -= 2;
- }
- if (y < (1.0L / (1 << 1)))
- {
- y *= 1.0L * (1 << 1);
- exp -= 1;
- }
- }
- if (!(y >= 0.5L && y < 1.0L))
- abort ();
- /* Compute an approximation for l = log2(x) = exp + log2(y). */
- l = exp;
- z = y;
- if (z < 0.70710678118654752444)
- {
- z *= 1.4142135623730950488;
- l -= 0.5;
- }
- if (z < 0.8408964152537145431)
- {
- z *= 1.1892071150027210667;
- l -= 0.25;
- }
- if (z < 0.91700404320467123175)
- {
- z *= 1.0905077326652576592;
- l -= 0.125;
- }
- if (z < 0.9576032806985736469)
- {
- z *= 1.0442737824274138403;
- l -= 0.0625;
- }
- /* Now 0.95 <= z <= 1.01. */
- z = 1 - z;
- /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
- Four terms are enough to get an approximation with error < 10^-7. */
- l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
- /* Finally multiply with log(2)/log(10), yields an approximation for
- log10(x). */
- l *= 0.30102999566398119523;
- /* Round down to the next integer. */
- return (int) l + (l < 0 ? -1 : 0);
-}
-
-# endif
-
-# if NEED_PRINTF_DOUBLE
-
-/* Assuming x is finite and > 0:
- Return an approximation for n with 10^n <= x < 10^(n+1).
- The approximation is usually the right n, but may be off by 1 sometimes. */
-static int
-floorlog10 (double x)
-{
- int exp;
- double y;
- double z;
- double l;
-
- /* Split into exponential part and mantissa. */
- y = frexp (x, &exp);
- if (!(y >= 0.0 && y < 1.0))
- abort ();
- if (y == 0.0)
- return INT_MIN;
- if (y < 0.5)
- {
- while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
- {
- y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
- exp -= GMP_LIMB_BITS;
- }
- if (y < (1.0 / (1 << 16)))
- {
- y *= 1.0 * (1 << 16);
- exp -= 16;
- }
- if (y < (1.0 / (1 << 8)))
- {
- y *= 1.0 * (1 << 8);
- exp -= 8;
- }
- if (y < (1.0 / (1 << 4)))
- {
- y *= 1.0 * (1 << 4);
- exp -= 4;
- }
- if (y < (1.0 / (1 << 2)))
- {
- y *= 1.0 * (1 << 2);
- exp -= 2;
- }
- if (y < (1.0 / (1 << 1)))
- {
- y *= 1.0 * (1 << 1);
- exp -= 1;
- }
- }
- if (!(y >= 0.5 && y < 1.0))
- abort ();
- /* Compute an approximation for l = log2(x) = exp + log2(y). */
- l = exp;
- z = y;
- if (z < 0.70710678118654752444)
- {
- z *= 1.4142135623730950488;
- l -= 0.5;
- }
- if (z < 0.8408964152537145431)
- {
- z *= 1.1892071150027210667;
- l -= 0.25;
- }
- if (z < 0.91700404320467123175)
- {
- z *= 1.0905077326652576592;
- l -= 0.125;
- }
- if (z < 0.9576032806985736469)
- {
- z *= 1.0442737824274138403;
- l -= 0.0625;
- }
- /* Now 0.95 <= z <= 1.01. */
- z = 1 - z;
- /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
- Four terms are enough to get an approximation with error < 10^-7. */
- l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
- /* Finally multiply with log(2)/log(10), yields an approximation for
- log10(x). */
- l *= 0.30102999566398119523;
- /* Round down to the next integer. */
- return (int) l + (l < 0 ? -1 : 0);
-}
-
-# endif
-
-/* Tests whether a string of digits consists of exactly PRECISION zeroes and
- a single '1' digit. */
-static int
-is_borderline (const char *digits, size_t precision)
-{
- for (; precision > 0; precision--, digits++)
- if (*digits != '0')
- return 0;
- if (*digits != '1')
- return 0;
- digits++;
- return *digits == '\0';
-}
-
-#endif
-
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF
-
-/* Use a different function name, to make it possible that the 'wchar_t'
- parametrization and the 'char' parametrization get compiled in the same
- translation unit. */
-# if WIDE_CHAR_VERSION
-# define MAX_ROOM_NEEDED wmax_room_needed
-# else
-# define MAX_ROOM_NEEDED max_room_needed
-# endif
-
-/* Returns the number of TCHAR_T units needed as temporary space for the result
- of sprintf or SNPRINTF of a single conversion directive. */
-static size_t
-MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
- arg_type type, int flags, size_t width, int has_precision,
- size_t precision, int pad_ourselves)
-{
- size_t tmp_length;
-
- switch (conversion)
- {
- case 'd': case 'i': case 'u':
- if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
- tmp_length =
- (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
- * 0.30103 /* binary -> decimal */
- )
- + 1; /* turn floor into ceil */
- else if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
- tmp_length =
- (unsigned int) (sizeof (unsigned long) * CHAR_BIT
- * 0.30103 /* binary -> decimal */
- )
- + 1; /* turn floor into ceil */
- else
- tmp_length =
- (unsigned int) (sizeof (unsigned int) * CHAR_BIT
- * 0.30103 /* binary -> decimal */
- )
- + 1; /* turn floor into ceil */
- if (tmp_length < precision)
- tmp_length = precision;
- /* Multiply by 2, as an estimate for FLAG_GROUP. */
- tmp_length = xsum (tmp_length, tmp_length);
- /* Add 1, to account for a leading sign. */
- tmp_length = xsum (tmp_length, 1);
- break;
-
- case 'o':
- if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
- tmp_length =
- (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
- * 0.333334 /* binary -> octal */
- )
- + 1; /* turn floor into ceil */
- else if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
- tmp_length =
- (unsigned int) (sizeof (unsigned long) * CHAR_BIT
- * 0.333334 /* binary -> octal */
- )
- + 1; /* turn floor into ceil */
- else
- tmp_length =
- (unsigned int) (sizeof (unsigned int) * CHAR_BIT
- * 0.333334 /* binary -> octal */
- )
- + 1; /* turn floor into ceil */
- if (tmp_length < precision)
- tmp_length = precision;
- /* Add 1, to account for a leading sign. */
- tmp_length = xsum (tmp_length, 1);
- break;
-
- case 'x': case 'X':
- if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
- tmp_length =
- (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
- * 0.25 /* binary -> hexadecimal */
- )
- + 1; /* turn floor into ceil */
- else if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
- tmp_length =
- (unsigned int) (sizeof (unsigned long) * CHAR_BIT
- * 0.25 /* binary -> hexadecimal */
- )
- + 1; /* turn floor into ceil */
- else
- tmp_length =
- (unsigned int) (sizeof (unsigned int) * CHAR_BIT
- * 0.25 /* binary -> hexadecimal */
- )
- + 1; /* turn floor into ceil */
- if (tmp_length < precision)
- tmp_length = precision;
- /* Add 2, to account for a leading sign or alternate form. */
- tmp_length = xsum (tmp_length, 2);
- break;
-
- case 'f': case 'F':
- if (type == TYPE_LONGDOUBLE)
- tmp_length =
- (unsigned int) (LDBL_MAX_EXP
- * 0.30103 /* binary -> decimal */
- * 2 /* estimate for FLAG_GROUP */
- )
- + 1 /* turn floor into ceil */
- + 10; /* sign, decimal point etc. */
- else
- tmp_length =
- (unsigned int) (DBL_MAX_EXP
- * 0.30103 /* binary -> decimal */
- * 2 /* estimate for FLAG_GROUP */
- )
- + 1 /* turn floor into ceil */
- + 10; /* sign, decimal point etc. */
- tmp_length = xsum (tmp_length, precision);
- break;
-
- case 'e': case 'E': case 'g': case 'G':
- tmp_length =
- 12; /* sign, decimal point, exponent etc. */
- tmp_length = xsum (tmp_length, precision);
- break;
-
- case 'a': case 'A':
- if (type == TYPE_LONGDOUBLE)
- tmp_length =
- (unsigned int) (LDBL_DIG
- * 0.831 /* decimal -> hexadecimal */
- )
- + 1; /* turn floor into ceil */
- else
- tmp_length =
- (unsigned int) (DBL_DIG
- * 0.831 /* decimal -> hexadecimal */
- )
- + 1; /* turn floor into ceil */
- if (tmp_length < precision)
- tmp_length = precision;
- /* Account for sign, decimal point etc. */
- tmp_length = xsum (tmp_length, 12);
- break;
-
- case 'c':
-# if HAVE_WINT_T && !WIDE_CHAR_VERSION
- if (type == TYPE_WIDE_CHAR)
- {
- tmp_length = MB_CUR_MAX;
-# if ENABLE_WCHAR_FALLBACK
- if (tmp_length < (sizeof (wchar_t) > 2 ? 10 : 6))
- tmp_length = (sizeof (wchar_t) > 2 ? 10 : 6);
-# endif
- }
- else
-# endif
- tmp_length = 1;
- break;
-
- case 's':
-# if HAVE_WCHAR_T
- if (type == TYPE_WIDE_STRING)
- {
-# if WIDE_CHAR_VERSION
- /* ISO C says about %ls in fwprintf:
- "If the precision is not specified or is greater than the size
- of the array, the array shall contain a null wide character."
- So if there is a precision, we must not use wcslen. */
- const wchar_t *arg = ap->arg[arg_index].a.a_wide_string;
-
- if (has_precision)
- tmp_length = local_wcsnlen (arg, precision);
- else
- tmp_length = local_wcslen (arg);
-# else
- /* ISO C says about %ls in fprintf:
- "If a precision is specified, no more than that many bytes are
- written (including shift sequences, if any), and the array
- shall contain a null wide character if, to equal the multibyte
- character sequence length given by the precision, the function
- would need to access a wide character one past the end of the
- array."
- So if there is a precision, we must not use wcslen. */
- /* This case has already been handled separately in VASNPRINTF. */
- abort ();
-# endif
- }
- else
-# endif
- {
-# if WIDE_CHAR_VERSION
- /* ISO C says about %s in fwprintf:
- "If the precision is not specified or is greater than the size
- of the converted array, the converted array shall contain a
- null wide character."
- So if there is a precision, we must not use strlen. */
- /* This case has already been handled separately in VASNPRINTF. */
- abort ();
-# else
- /* ISO C says about %s in fprintf:
- "If the precision is not specified or greater than the size of
- the array, the array shall contain a null character."
- So if there is a precision, we must not use strlen. */
- const char *arg = ap->arg[arg_index].a.a_string;
-
- if (has_precision)
- tmp_length = local_strnlen (arg, precision);
- else
- tmp_length = strlen (arg);
-# endif
- }
- break;
-
- case 'p':
- tmp_length =
- (unsigned int) (sizeof (void *) * CHAR_BIT
- * 0.25 /* binary -> hexadecimal */
- )
- + 1 /* turn floor into ceil */
- + 2; /* account for leading 0x */
- break;
-
- default:
- abort ();
- }
-
- if (!pad_ourselves)
- {
-# if ENABLE_UNISTDIO
- /* Padding considers the number of characters, therefore the number of
- elements after padding may be
- > max (tmp_length, width)
- but is certainly
- <= tmp_length + width. */
- tmp_length = xsum (tmp_length, width);
-# else
- /* Padding considers the number of elements, says POSIX. */
- if (tmp_length < width)
- tmp_length = width;
-# endif
- }
-
- tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
-
- return tmp_length;
-}
-
-#endif
-
-DCHAR_T *
-VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
- const FCHAR_T *format, va_list args)
-{
- DIRECTIVES d;
- arguments a;
-
- if (PRINTF_PARSE (format, &d, &a) < 0)
- /* errno is already set. */
- return NULL;
-
-#define CLEANUP() \
- if (d.dir != d.direct_alloc_dir) \
- free (d.dir); \
- if (a.arg != a.direct_alloc_arg) \
- free (a.arg);
-
- if (PRINTF_FETCHARGS (args, &a) < 0)
- {
- CLEANUP ();
- errno = EINVAL;
- return NULL;
- }
-
- {
- size_t buf_neededlength;
- TCHAR_T *buf;
- TCHAR_T *buf_malloced;
- const FCHAR_T *cp;
- size_t i;
- DIRECTIVE *dp;
- /* Output string accumulator. */
- DCHAR_T *result;
- size_t allocated;
- size_t length;
-
- /* Allocate a small buffer that will hold a directive passed to
- sprintf or snprintf. */
- buf_neededlength =
- xsum4 (7, d.max_width_length, d.max_precision_length, 6);
-#if HAVE_ALLOCA
- if (buf_neededlength < 4000 / sizeof (TCHAR_T))
- {
- buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T));
- buf_malloced = NULL;
- }
- else
-#endif
- {
- size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T));
- if (size_overflow_p (buf_memsize))
- goto out_of_memory_1;
- buf = (TCHAR_T *) malloc (buf_memsize);
- if (buf == NULL)
- goto out_of_memory_1;
- buf_malloced = buf;
- }
-
- if (resultbuf != NULL)
- {
- result = resultbuf;
- allocated = *lengthp;
- }
- else
- {
- result = NULL;
- allocated = 0;
- }
- length = 0;
- /* Invariants:
- result is either == resultbuf or == NULL or malloc-allocated.
- If length > 0, then result != NULL. */
-
- /* Ensures that allocated >= needed. Aborts through a jump to
- out_of_memory if needed is SIZE_MAX or otherwise too big. */
-#define ENSURE_ALLOCATION(needed) \
- if ((needed) > allocated) \
- { \
- size_t memory_size; \
- DCHAR_T *memory; \
- \
- allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
- if ((needed) > allocated) \
- allocated = (needed); \
- memory_size = xtimes (allocated, sizeof (DCHAR_T)); \
- if (size_overflow_p (memory_size)) \
- goto out_of_memory; \
- if (result == resultbuf || result == NULL) \
- memory = (DCHAR_T *) malloc (memory_size); \
- else \
- memory = (DCHAR_T *) realloc (result, memory_size); \
- if (memory == NULL) \
- goto out_of_memory; \
- if (result == resultbuf && length > 0) \
- DCHAR_CPY (memory, result, length); \
- result = memory; \
- }
-
- for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
- {
- if (cp != dp->dir_start)
- {
- size_t n = dp->dir_start - cp;
- size_t augmented_length = xsum (length, n);
-
- ENSURE_ALLOCATION (augmented_length);
- /* This copies a piece of FCHAR_T[] into a DCHAR_T[]. Here we
- need that the format string contains only ASCII characters
- if FCHAR_T and DCHAR_T are not the same type. */
- if (sizeof (FCHAR_T) == sizeof (DCHAR_T))
- {
- DCHAR_CPY (result + length, (const DCHAR_T *) cp, n);
- length = augmented_length;
- }
- else
- {
- do
- result[length++] = *cp++;
- while (--n > 0);
- }
- }
- if (i == d.count)
- break;
-
- /* Execute a single directive. */
- if (dp->conversion == '%')
- {
- size_t augmented_length;
-
- if (!(dp->arg_index == ARG_NONE))
- abort ();
- augmented_length = xsum (length, 1);
- ENSURE_ALLOCATION (augmented_length);
- result[length] = '%';
- length = augmented_length;
- }
- else
- {
- if (!(dp->arg_index != ARG_NONE))
- abort ();
-
- if (dp->conversion == 'n')
- {
- switch (a.arg[dp->arg_index].type)
- {
- case TYPE_COUNT_SCHAR_POINTER:
- *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
- break;
- case TYPE_COUNT_SHORT_POINTER:
- *a.arg[dp->arg_index].a.a_count_short_pointer = length;
- break;
- case TYPE_COUNT_INT_POINTER:
- *a.arg[dp->arg_index].a.a_count_int_pointer = length;
- break;
- case TYPE_COUNT_LONGINT_POINTER:
- *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
- break;
- case TYPE_COUNT_LONGLONGINT_POINTER:
- *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
- break;
- default:
- abort ();
- }
- }
-#if ENABLE_UNISTDIO
- /* The unistdio extensions. */
- else if (dp->conversion == 'U')
- {
- arg_type type = a.arg[dp->arg_index].type;
- int flags = dp->flags;
- int has_width;
- size_t width;
- int has_precision;
- size_t precision;
-
- has_width = 0;
- width = 0;
- if (dp->width_start != dp->width_end)
- {
- if (dp->width_arg_index != ARG_NONE)
- {
- int arg;
-
- if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
- abort ();
- arg = a.arg[dp->width_arg_index].a.a_int;
- width = arg;
- if (arg < 0)
- {
- /* "A negative field width is taken as a '-' flag
- followed by a positive field width." */
- flags |= FLAG_LEFT;
- width = -width;
- }
- }
- else
- {
- const FCHAR_T *digitp = dp->width_start;
-
- do
- width = xsum (xtimes (width, 10), *digitp++ - '0');
- while (digitp != dp->width_end);
- }
- has_width = 1;
- }
-
- has_precision = 0;
- precision = 0;
- if (dp->precision_start != dp->precision_end)
- {
- if (dp->precision_arg_index != ARG_NONE)
- {
- int arg;
-
- if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
- abort ();
- arg = a.arg[dp->precision_arg_index].a.a_int;
- /* "A negative precision is taken as if the precision
- were omitted." */
- if (arg >= 0)
- {
- precision = arg;
- has_precision = 1;
- }
- }
- else
- {
- const FCHAR_T *digitp = dp->precision_start + 1;
-
- precision = 0;
- while (digitp != dp->precision_end)
- precision = xsum (xtimes (precision, 10), *digitp++ - '0');
- has_precision = 1;
- }
- }
-
- switch (type)
- {
- case TYPE_U8_STRING:
- {
- const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string;
- const uint8_t *arg_end;
- size_t characters;
-
- if (has_precision)
- {
- /* Use only PRECISION characters, from the left. */
- arg_end = arg;
- characters = 0;
- for (; precision > 0; precision--)
- {
- int count = u8_strmblen (arg_end);
- if (count == 0)
- break;
- if (count < 0)
- {
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EILSEQ;
- return NULL;
- }
- arg_end += count;
- characters++;
- }
- }
- else if (has_width)
- {
- /* Use the entire string, and count the number of
- characters. */
- arg_end = arg;
- characters = 0;
- for (;;)
- {
- int count = u8_strmblen (arg_end);
- if (count == 0)
- break;
- if (count < 0)
- {
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EILSEQ;
- return NULL;
- }
- arg_end += count;
- characters++;
- }
- }
- else
- {
- /* Use the entire string. */
- arg_end = arg + u8_strlen (arg);
- /* The number of characters doesn't matter. */
- characters = 0;
- }
-
- if (characters < width && !(dp->flags & FLAG_LEFT))
- {
- size_t n = width - characters;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
-
-# if DCHAR_IS_UINT8_T
- {
- size_t n = arg_end - arg;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_CPY (result + length, arg, n);
- length += n;
- }
-# else
- { /* Convert. */
- DCHAR_T *converted = result + length;
- size_t converted_len = allocated - length;
-# if DCHAR_IS_TCHAR
- /* Convert from UTF-8 to locale encoding. */
- converted =
- u8_conv_to_encoding (locale_charset (),
- iconveh_question_mark,
- arg, arg_end - arg, NULL,
- converted, &converted_len);
-# else
- /* Convert from UTF-8 to UTF-16/UTF-32. */
- converted =
- U8_TO_DCHAR (arg, arg_end - arg,
- converted, &converted_len);
-# endif
- if (converted == NULL)
- {
- int saved_errno = errno;
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = saved_errno;
- return NULL;
- }
- if (converted != result + length)
- {
- ENSURE_ALLOCATION (xsum (length, converted_len));
- DCHAR_CPY (result + length, converted, converted_len);
- free (converted);
- }
- length += converted_len;
- }
-# endif
-
- if (characters < width && (dp->flags & FLAG_LEFT))
- {
- size_t n = width - characters;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
- }
- break;
-
- case TYPE_U16_STRING:
- {
- const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string;
- const uint16_t *arg_end;
- size_t characters;
-
- if (has_precision)
- {
- /* Use only PRECISION characters, from the left. */
- arg_end = arg;
- characters = 0;
- for (; precision > 0; precision--)
- {
- int count = u16_strmblen (arg_end);
- if (count == 0)
- break;
- if (count < 0)
- {
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EILSEQ;
- return NULL;
- }
- arg_end += count;
- characters++;
- }
- }
- else if (has_width)
- {
- /* Use the entire string, and count the number of
- characters. */
- arg_end = arg;
- characters = 0;
- for (;;)
- {
- int count = u16_strmblen (arg_end);
- if (count == 0)
- break;
- if (count < 0)
- {
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EILSEQ;
- return NULL;
- }
- arg_end += count;
- characters++;
- }
- }
- else
- {
- /* Use the entire string. */
- arg_end = arg + u16_strlen (arg);
- /* The number of characters doesn't matter. */
- characters = 0;
- }
-
- if (characters < width && !(dp->flags & FLAG_LEFT))
- {
- size_t n = width - characters;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
-
-# if DCHAR_IS_UINT16_T
- {
- size_t n = arg_end - arg;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_CPY (result + length, arg, n);
- length += n;
- }
-# else
- { /* Convert. */
- DCHAR_T *converted = result + length;
- size_t converted_len = allocated - length;
-# if DCHAR_IS_TCHAR
- /* Convert from UTF-16 to locale encoding. */
- converted =
- u16_conv_to_encoding (locale_charset (),
- iconveh_question_mark,
- arg, arg_end - arg, NULL,
- converted, &converted_len);
-# else
- /* Convert from UTF-16 to UTF-8/UTF-32. */
- converted =
- U16_TO_DCHAR (arg, arg_end - arg,
- converted, &converted_len);
-# endif
- if (converted == NULL)
- {
- int saved_errno = errno;
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = saved_errno;
- return NULL;
- }
- if (converted != result + length)
- {
- ENSURE_ALLOCATION (xsum (length, converted_len));
- DCHAR_CPY (result + length, converted, converted_len);
- free (converted);
- }
- length += converted_len;
- }
-# endif
-
- if (characters < width && (dp->flags & FLAG_LEFT))
- {
- size_t n = width - characters;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
- }
- break;
-
- case TYPE_U32_STRING:
- {
- const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string;
- const uint32_t *arg_end;
- size_t characters;
-
- if (has_precision)
- {
- /* Use only PRECISION characters, from the left. */
- arg_end = arg;
- characters = 0;
- for (; precision > 0; precision--)
- {
- int count = u32_strmblen (arg_end);
- if (count == 0)
- break;
- if (count < 0)
- {
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EILSEQ;
- return NULL;
- }
- arg_end += count;
- characters++;
- }
- }
- else if (has_width)
- {
- /* Use the entire string, and count the number of
- characters. */
- arg_end = arg;
- characters = 0;
- for (;;)
- {
- int count = u32_strmblen (arg_end);
- if (count == 0)
- break;
- if (count < 0)
- {
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EILSEQ;
- return NULL;
- }
- arg_end += count;
- characters++;
- }
- }
- else
- {
- /* Use the entire string. */
- arg_end = arg + u32_strlen (arg);
- /* The number of characters doesn't matter. */
- characters = 0;
- }
-
- if (characters < width && !(dp->flags & FLAG_LEFT))
- {
- size_t n = width - characters;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
-
-# if DCHAR_IS_UINT32_T
- {
- size_t n = arg_end - arg;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_CPY (result + length, arg, n);
- length += n;
- }
-# else
- { /* Convert. */
- DCHAR_T *converted = result + length;
- size_t converted_len = allocated - length;
-# if DCHAR_IS_TCHAR
- /* Convert from UTF-32 to locale encoding. */
- converted =
- u32_conv_to_encoding (locale_charset (),
- iconveh_question_mark,
- arg, arg_end - arg, NULL,
- converted, &converted_len);
-# else
- /* Convert from UTF-32 to UTF-8/UTF-16. */
- converted =
- U32_TO_DCHAR (arg, arg_end - arg,
- converted, &converted_len);
-# endif
- if (converted == NULL)
- {
- int saved_errno = errno;
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = saved_errno;
- return NULL;
- }
- if (converted != result + length)
- {
- ENSURE_ALLOCATION (xsum (length, converted_len));
- DCHAR_CPY (result + length, converted, converted_len);
- free (converted);
- }
- length += converted_len;
- }
-# endif
-
- if (characters < width && (dp->flags & FLAG_LEFT))
- {
- size_t n = width - characters;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
- }
- break;
-
- default:
- abort ();
- }
- }
-#endif
-#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL) || ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T
- else if (dp->conversion == 's'
-# if WIDE_CHAR_VERSION
- && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
-# else
- && a.arg[dp->arg_index].type == TYPE_WIDE_STRING
-# endif
- )
- {
- /* The normal handling of the 's' directive below requires
- allocating a temporary buffer. The determination of its
- length (tmp_length), in the case when a precision is
- specified, below requires a conversion between a char[]
- string and a wchar_t[] wide string. It could be done, but
- we have no guarantee that the implementation of sprintf will
- use the exactly same algorithm. Without this guarantee, it
- is possible to have buffer overrun bugs. In order to avoid
- such bugs, we implement the entire processing of the 's'
- directive ourselves. */
- int flags = dp->flags;
- int has_width;
- size_t width;
- int has_precision;
- size_t precision;
-
- has_width = 0;
- width = 0;
- if (dp->width_start != dp->width_end)
- {
- if (dp->width_arg_index != ARG_NONE)
- {
- int arg;
-
- if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
- abort ();
- arg = a.arg[dp->width_arg_index].a.a_int;
- width = arg;
- if (arg < 0)
- {
- /* "A negative field width is taken as a '-' flag
- followed by a positive field width." */
- flags |= FLAG_LEFT;
- width = -width;
- }
- }
- else
- {
- const FCHAR_T *digitp = dp->width_start;
-
- do
- width = xsum (xtimes (width, 10), *digitp++ - '0');
- while (digitp != dp->width_end);
- }
- has_width = 1;
- }
-
- has_precision = 0;
- precision = 6;
- if (dp->precision_start != dp->precision_end)
- {
- if (dp->precision_arg_index != ARG_NONE)
- {
- int arg;
-
- if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
- abort ();
- arg = a.arg[dp->precision_arg_index].a.a_int;
- /* "A negative precision is taken as if the precision
- were omitted." */
- if (arg >= 0)
- {
- precision = arg;
- has_precision = 1;
- }
- }
- else
- {
- const FCHAR_T *digitp = dp->precision_start + 1;
-
- precision = 0;
- while (digitp != dp->precision_end)
- precision = xsum (xtimes (precision, 10), *digitp++ - '0');
- has_precision = 1;
- }
- }
-
-# if WIDE_CHAR_VERSION
- /* %s in vasnwprintf. See the specification of fwprintf. */
- {
- const char *arg = a.arg[dp->arg_index].a.a_string;
- const char *arg_end;
- size_t characters;
-
- if (has_precision)
- {
- /* Use only as many bytes as needed to produce PRECISION
- wide characters, from the left. */
-# if HAVE_MBRTOWC
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
- arg_end = arg;
- characters = 0;
- for (; precision > 0; precision--)
- {
- int count;
-# if HAVE_MBRTOWC
- count = mbrlen (arg_end, MB_CUR_MAX, &state);
-# else
- count = mblen (arg_end, MB_CUR_MAX);
-# endif
- if (count == 0)
- /* Found the terminating NUL. */
- break;
- if (count < 0)
- {
- /* Invalid or incomplete multibyte character. */
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EILSEQ;
- return NULL;
- }
- arg_end += count;
- characters++;
- }
- }
- else if (has_width)
- {
- /* Use the entire string, and count the number of wide
- characters. */
-# if HAVE_MBRTOWC
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
- arg_end = arg;
- characters = 0;
- for (;;)
- {
- int count;
-# if HAVE_MBRTOWC
- count = mbrlen (arg_end, MB_CUR_MAX, &state);
-# else
- count = mblen (arg_end, MB_CUR_MAX);
-# endif
- if (count == 0)
- /* Found the terminating NUL. */
- break;
- if (count < 0)
- {
- /* Invalid or incomplete multibyte character. */
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EILSEQ;
- return NULL;
- }
- arg_end += count;
- characters++;
- }
- }
- else
- {
- /* Use the entire string. */
- arg_end = arg + strlen (arg);
- /* The number of characters doesn't matter. */
- characters = 0;
- }
-
- if (characters < width && !(dp->flags & FLAG_LEFT))
- {
- size_t n = width - characters;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
-
- if (has_precision || has_width)
- {
- /* We know the number of wide characters in advance. */
- size_t remaining;
-# if HAVE_MBRTOWC
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
- ENSURE_ALLOCATION (xsum (length, characters));
- for (remaining = characters; remaining > 0; remaining--)
- {
- wchar_t wc;
- int count;
-# if HAVE_MBRTOWC
- count = mbrtowc (&wc, arg, arg_end - arg, &state);
-# else
- count = mbtowc (&wc, arg, arg_end - arg);
-# endif
- if (count <= 0)
- /* mbrtowc not consistent with mbrlen, or mbtowc
- not consistent with mblen. */
- abort ();
- result[length++] = wc;
- arg += count;
- }
- if (!(arg == arg_end))
- abort ();
- }
- else
- {
-# if HAVE_MBRTOWC
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
- while (arg < arg_end)
- {
- wchar_t wc;
- int count;
-# if HAVE_MBRTOWC
- count = mbrtowc (&wc, arg, arg_end - arg, &state);
-# else
- count = mbtowc (&wc, arg, arg_end - arg);
-# endif
- if (count <= 0)
- /* mbrtowc not consistent with mbrlen, or mbtowc
- not consistent with mblen. */
- abort ();
- ENSURE_ALLOCATION (xsum (length, 1));
- result[length++] = wc;
- arg += count;
- }
- }
-
- if (characters < width && (dp->flags & FLAG_LEFT))
- {
- size_t n = width - characters;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
- }
-# else
- /* %ls in vasnprintf. See the specification of fprintf. */
- {
- const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
- const wchar_t *arg_end;
- size_t characters;
-# if !DCHAR_IS_TCHAR
- /* This code assumes that TCHAR_T is 'char'. */
- verify (sizeof (TCHAR_T) == 1);
- TCHAR_T *tmpsrc;
- DCHAR_T *tmpdst;
- size_t tmpdst_len;
-# endif
- size_t w;
-
- if (has_precision)
- {
- /* Use only as many wide characters as needed to produce
- at most PRECISION bytes, from the left. */
-# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
- arg_end = arg;
- characters = 0;
- while (precision > 0)
- {
- char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
- int count;
-
- if (*arg_end == 0)
- /* Found the terminating null wide character. */
- break;
- count = local_wcrtomb (cbuf, *arg_end, &state);
- if (count < 0)
- {
- /* Cannot convert. */
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EILSEQ;
- return NULL;
- }
- if (precision < (unsigned int) count)
- break;
- arg_end++;
- characters += count;
- precision -= count;
- }
- }
-# if DCHAR_IS_TCHAR
- else if (has_width)
-# else
- else
-# endif
- {
- /* Use the entire string, and count the number of
- bytes. */
-# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
- arg_end = arg;
- characters = 0;
- for (;;)
- {
- char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
- int count;
-
- if (*arg_end == 0)
- /* Found the terminating null wide character. */
- break;
- count = local_wcrtomb (cbuf, *arg_end, &state);
- if (count < 0)
- {
- /* Cannot convert. */
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EILSEQ;
- return NULL;
- }
- arg_end++;
- characters += count;
- }
- }
-# if DCHAR_IS_TCHAR
- else
- {
- /* Use the entire string. */
- arg_end = arg + local_wcslen (arg);
- /* The number of bytes doesn't matter. */
- characters = 0;
- }
-# endif
-
-# if !DCHAR_IS_TCHAR
- /* Convert the string into a piece of temporary memory. */
- tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
- if (tmpsrc == NULL)
- goto out_of_memory;
- {
- TCHAR_T *tmpptr = tmpsrc;
- size_t remaining;
-# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
- for (remaining = characters; remaining > 0; )
- {
- char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
- int count;
-
- if (*arg == 0)
- abort ();
- count = local_wcrtomb (cbuf, *arg, &state);
- if (count <= 0)
- /* Inconsistency. */
- abort ();
- memcpy (tmpptr, cbuf, count);
- tmpptr += count;
- arg++;
- remaining -= count;
- }
- if (!(arg == arg_end))
- abort ();
- }
-
- /* Convert from TCHAR_T[] to DCHAR_T[]. */
- tmpdst =
- DCHAR_CONV_FROM_ENCODING (locale_charset (),
- iconveh_question_mark,
- tmpsrc, characters,
- NULL,
- NULL, &tmpdst_len);
- if (tmpdst == NULL)
- {
- int saved_errno = errno;
- free (tmpsrc);
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = saved_errno;
- return NULL;
- }
- free (tmpsrc);
-# endif
-
- if (has_width)
- {
-# if ENABLE_UNISTDIO
- /* Outside POSIX, it's preferable to compare the width
- against the number of _characters_ of the converted
- value. */
- w = DCHAR_MBSNLEN (result + length, characters);
-# else
- /* The width is compared against the number of _bytes_
- of the converted value, says POSIX. */
- w = characters;
-# endif
- }
- else
- /* w doesn't matter. */
- w = 0;
-
- if (w < width && !(dp->flags & FLAG_LEFT))
- {
- size_t n = width - w;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
-
-# if DCHAR_IS_TCHAR
- if (has_precision || has_width)
- {
- /* We know the number of bytes in advance. */
- size_t remaining;
-# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
- ENSURE_ALLOCATION (xsum (length, characters));
- for (remaining = characters; remaining > 0; )
- {
- char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
- int count;
-
- if (*arg == 0)
- abort ();
- count = local_wcrtomb (cbuf, *arg, &state);
- if (count <= 0)
- /* Inconsistency. */
- abort ();
- memcpy (result + length, cbuf, count);
- length += count;
- arg++;
- remaining -= count;
- }
- if (!(arg == arg_end))
- abort ();
- }
- else
- {
-# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
- while (arg < arg_end)
- {
- char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
- int count;
-
- if (*arg == 0)
- abort ();
- count = local_wcrtomb (cbuf, *arg, &state);
- if (count <= 0)
- {
- /* Cannot convert. */
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EILSEQ;
- return NULL;
- }
- ENSURE_ALLOCATION (xsum (length, count));
- memcpy (result + length, cbuf, count);
- length += count;
- arg++;
- }
- }
-# else
- ENSURE_ALLOCATION (xsum (length, tmpdst_len));
- DCHAR_CPY (result + length, tmpdst, tmpdst_len);
- free (tmpdst);
- length += tmpdst_len;
-# endif
-
- if (w < width && (dp->flags & FLAG_LEFT))
- {
- size_t n = width - w;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
- }
-# endif
- }
-#endif
-#if ENABLE_WCHAR_FALLBACK && HAVE_WINT_T && !WIDE_CHAR_VERSION
- else if (dp->conversion == 'c'
- && a.arg[dp->arg_index].type == TYPE_WIDE_CHAR)
- {
- /* Implement the 'lc' directive ourselves, in order to provide
- the fallback that avoids EILSEQ. */
- int flags = dp->flags;
- int has_width;
- size_t width;
-
- has_width = 0;
- width = 0;
- if (dp->width_start != dp->width_end)
- {
- if (dp->width_arg_index != ARG_NONE)
- {
- int arg;
-
- if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
- abort ();
- arg = a.arg[dp->width_arg_index].a.a_int;
- width = arg;
- if (arg < 0)
- {
- /* "A negative field width is taken as a '-' flag
- followed by a positive field width." */
- flags |= FLAG_LEFT;
- width = -width;
- }
- }
- else
- {
- const FCHAR_T *digitp = dp->width_start;
-
- do
- width = xsum (xtimes (width, 10), *digitp++ - '0');
- while (digitp != dp->width_end);
- }
- has_width = 1;
- }
-
- /* %lc in vasnprintf. See the specification of fprintf. */
- {
- wchar_t arg = (wchar_t) a.arg[dp->arg_index].a.a_wide_char;
- size_t characters;
-# if !DCHAR_IS_TCHAR
- /* This code assumes that TCHAR_T is 'char'. */
- verify (sizeof (TCHAR_T) == 1);
- TCHAR_T tmpsrc[64]; /* Assume MB_CUR_MAX <= 64. */
- DCHAR_T *tmpdst;
- size_t tmpdst_len;
-# endif
- size_t w;
-
-# if DCHAR_IS_TCHAR
- if (has_width)
-# endif
- {
- /* Count the number of bytes. */
- characters = 0;
- if (arg != 0)
- {
- char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
- int count;
-# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
-
- count = local_wcrtomb (cbuf, arg, &state);
- if (count < 0)
- /* Inconsistency. */
- abort ();
- characters = count;
- }
- }
-# if DCHAR_IS_TCHAR
- else
- {
- /* The number of bytes doesn't matter. */
- characters = 0;
- }
-# endif
-
-# if !DCHAR_IS_TCHAR
- /* Convert the string into a piece of temporary memory. */
- if (characters > 0) /* implies arg != 0 */
- {
- char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
- int count;
-# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
-
- count = local_wcrtomb (cbuf, arg, &state);
- if (count <= 0)
- /* Inconsistency. */
- abort ();
- memcpy (tmpsrc, cbuf, count);
- }
-
- /* Convert from TCHAR_T[] to DCHAR_T[]. */
- tmpdst =
- DCHAR_CONV_FROM_ENCODING (locale_charset (),
- iconveh_question_mark,
- tmpsrc, characters,
- NULL,
- NULL, &tmpdst_len);
- if (tmpdst == NULL)
- {
- int saved_errno = errno;
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = saved_errno;
- return NULL;
- }
-# endif
-
- if (has_width)
- {
-# if ENABLE_UNISTDIO
- /* Outside POSIX, it's preferable to compare the width
- against the number of _characters_ of the converted
- value. */
- w = DCHAR_MBSNLEN (result + length, characters);
-# else
- /* The width is compared against the number of _bytes_
- of the converted value, says POSIX. */
- w = characters;
-# endif
- }
- else
- /* w doesn't matter. */
- w = 0;
-
- if (w < width && !(dp->flags & FLAG_LEFT))
- {
- size_t n = width - w;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
-
-# if DCHAR_IS_TCHAR
- if (has_width)
- {
- /* We know the number of bytes in advance. */
- ENSURE_ALLOCATION (xsum (length, characters));
- if (characters > 0) /* implies arg != 0 */
- {
- int count;
-# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
-
- count = local_wcrtomb (result + length, arg, &state);
- if (count <= 0)
- /* Inconsistency. */
- abort ();
- length += count;
- }
- }
- else
- {
- if (arg != 0)
- {
- char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
- int count;
-# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
- mbstate_t state;
- memset (&state, '\0', sizeof (mbstate_t));
-# endif
-
- count = local_wcrtomb (cbuf, arg, &state);
- if (count <= 0)
- /* Inconsistency. */
- abort ();
- ENSURE_ALLOCATION (xsum (length, count));
- memcpy (result + length, cbuf, count);
- length += count;
- }
- }
-# else
- ENSURE_ALLOCATION (xsum (length, tmpdst_len));
- DCHAR_CPY (result + length, tmpdst, tmpdst_len);
- free (tmpdst);
- length += tmpdst_len;
-# endif
-
- if (w < width && (dp->flags & FLAG_LEFT))
- {
- size_t n = width - w;
- ENSURE_ALLOCATION (xsum (length, n));
- DCHAR_SET (result + length, ' ', n);
- length += n;
- }
- }
- }
-#endif
-#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
- else if ((dp->conversion == 'a' || dp->conversion == 'A')
-# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
- && (0
-# if NEED_PRINTF_DOUBLE
- || a.arg[dp->arg_index].type == TYPE_DOUBLE
-# endif
-# if NEED_PRINTF_LONG_DOUBLE
- || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
-# endif
- )
-# endif
- )
- {
- arg_type type = a.arg[dp->arg_index].type;
- int flags = dp->flags;
- size_t width;
- int has_precision;
- size_t precision;
- size_t tmp_length;
- size_t count;
- DCHAR_T tmpbuf[700];
- DCHAR_T *tmp;
- DCHAR_T *pad_ptr;
- DCHAR_T *p;
-
- width = 0;
- if (dp->width_start != dp->width_end)
- {
- if (dp->width_arg_index != ARG_NONE)
- {
- int arg;
-
- if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
- abort ();
- arg = a.arg[dp->width_arg_index].a.a_int;
- width = arg;
- if (arg < 0)
- {
- /* "A negative field width is taken as a '-' flag
- followed by a positive field width." */
- flags |= FLAG_LEFT;
- width = -width;
- }
- }
- else
- {
- const FCHAR_T *digitp = dp->width_start;
-
- do
- width = xsum (xtimes (width, 10), *digitp++ - '0');
- while (digitp != dp->width_end);
- }
- }
-
- has_precision = 0;
- precision = 0;
- if (dp->precision_start != dp->precision_end)
- {
- if (dp->precision_arg_index != ARG_NONE)
- {
- int arg;
-
- if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
- abort ();
- arg = a.arg[dp->precision_arg_index].a.a_int;
- /* "A negative precision is taken as if the precision
- were omitted." */
- if (arg >= 0)
- {
- precision = arg;
- has_precision = 1;
- }
- }
- else
- {
- const FCHAR_T *digitp = dp->precision_start + 1;
-
- precision = 0;
- while (digitp != dp->precision_end)
- precision = xsum (xtimes (precision, 10), *digitp++ - '0');
- has_precision = 1;
- }
- }
-
- /* Allocate a temporary buffer of sufficient size. */
- if (type == TYPE_LONGDOUBLE)
- tmp_length =
- (unsigned int) ((LDBL_DIG + 1)
- * 0.831 /* decimal -> hexadecimal */
- )
- + 1; /* turn floor into ceil */
- else
- tmp_length =
- (unsigned int) ((DBL_DIG + 1)
- * 0.831 /* decimal -> hexadecimal */
- )
- + 1; /* turn floor into ceil */
- if (tmp_length < precision)
- tmp_length = precision;
- /* Account for sign, decimal point etc. */
- tmp_length = xsum (tmp_length, 12);
-
- if (tmp_length < width)
- tmp_length = width;
-
- tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
-
- if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
- tmp = tmpbuf;
- else
- {
- size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
-
- if (size_overflow_p (tmp_memsize))
- /* Overflow, would lead to out of memory. */
- goto out_of_memory;
- tmp = (DCHAR_T *) malloc (tmp_memsize);
- if (tmp == NULL)
- /* Out of memory. */
- goto out_of_memory;
- }
-
- pad_ptr = NULL;
- p = tmp;
- if (type == TYPE_LONGDOUBLE)
- {
-# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE
- long double arg = a.arg[dp->arg_index].a.a_longdouble;
-
- if (isnanl (arg))
- {
- if (dp->conversion == 'A')
- {
- *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
- }
- else
- {
- *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
- }
- }
- else
- {
- int sign = 0;
- DECL_LONG_DOUBLE_ROUNDING
-
- BEGIN_LONG_DOUBLE_ROUNDING ();
-
- if (signbit (arg)) /* arg < 0.0L or negative zero */
- {
- sign = -1;
- arg = -arg;
- }
-
- if (sign < 0)
- *p++ = '-';
- else if (flags & FLAG_SHOWSIGN)
- *p++ = '+';
- else if (flags & FLAG_SPACE)
- *p++ = ' ';
-
- if (arg > 0.0L && arg + arg == arg)
- {
- if (dp->conversion == 'A')
- {
- *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
- }
- else
- {
- *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
- }
- }
- else
- {
- int exponent;
- long double mantissa;
-
- if (arg > 0.0L)
- mantissa = printf_frexpl (arg, &exponent);
- else
- {
- exponent = 0;
- mantissa = 0.0L;
- }
-
- if (has_precision
- && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
- {
- /* Round the mantissa. */
- long double tail = mantissa;
- size_t q;
-
- for (q = precision; ; q--)
- {
- int digit = (int) tail;
- tail -= digit;
- if (q == 0)
- {
- if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
- tail = 1 - tail;
- else
- tail = - tail;
- break;
- }
- tail *= 16.0L;
- }
- if (tail != 0.0L)
- for (q = precision; q > 0; q--)
- tail *= 0.0625L;
- mantissa += tail;
- }
-
- *p++ = '0';
- *p++ = dp->conversion - 'A' + 'X';
- pad_ptr = p;
- {
- int digit;
-
- digit = (int) mantissa;
- mantissa -= digit;
- *p++ = '0' + digit;
- if ((flags & FLAG_ALT)
- || mantissa > 0.0L || precision > 0)
- {
- *p++ = decimal_point_char ();
- /* This loop terminates because we assume
- that FLT_RADIX is a power of 2. */
- while (mantissa > 0.0L)
- {
- mantissa *= 16.0L;
- digit = (int) mantissa;
- mantissa -= digit;
- *p++ = digit
- + (digit < 10
- ? '0'
- : dp->conversion - 10);
- if (precision > 0)
- precision--;
- }
- while (precision > 0)
- {
- *p++ = '0';
- precision--;
- }
- }
- }
- *p++ = dp->conversion - 'A' + 'P';
-# if WIDE_CHAR_VERSION
- {
- static const wchar_t decimal_format[] =
- { '%', '+', 'd', '\0' };
- SNPRINTF (p, 6 + 1, decimal_format, exponent);
- }
- while (*p != '\0')
- p++;
-# else
- if (sizeof (DCHAR_T) == 1)
- {
- sprintf ((char *) p, "%+d", exponent);
- while (*p != '\0')
- p++;
- }
- else
- {
- char expbuf[6 + 1];
- const char *ep;
- sprintf (expbuf, "%+d", exponent);
- for (ep = expbuf; (*p = *ep) != '\0'; ep++)
- p++;
- }
-# endif
- }
-
- END_LONG_DOUBLE_ROUNDING ();
- }
-# else
- abort ();
-# endif
- }
- else
- {
-# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
- double arg = a.arg[dp->arg_index].a.a_double;
-
- if (isnand (arg))
- {
- if (dp->conversion == 'A')
- {
- *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
- }
- else
- {
- *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
- }
- }
- else
- {
- int sign = 0;
-
- if (signbit (arg)) /* arg < 0.0 or negative zero */
- {
- sign = -1;
- arg = -arg;
- }
-
- if (sign < 0)
- *p++ = '-';
- else if (flags & FLAG_SHOWSIGN)
- *p++ = '+';
- else if (flags & FLAG_SPACE)
- *p++ = ' ';
-
- if (arg > 0.0 && arg + arg == arg)
- {
- if (dp->conversion == 'A')
- {
- *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
- }
- else
- {
- *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
- }
- }
- else
- {
- int exponent;
- double mantissa;
-
- if (arg > 0.0)
- mantissa = printf_frexp (arg, &exponent);
- else
- {
- exponent = 0;
- mantissa = 0.0;
- }
-
- if (has_precision
- && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
- {
- /* Round the mantissa. */
- double tail = mantissa;
- size_t q;
-
- for (q = precision; ; q--)
- {
- int digit = (int) tail;
- tail -= digit;
- if (q == 0)
- {
- if (digit & 1 ? tail >= 0.5 : tail > 0.5)
- tail = 1 - tail;
- else
- tail = - tail;
- break;
- }
- tail *= 16.0;
- }
- if (tail != 0.0)
- for (q = precision; q > 0; q--)
- tail *= 0.0625;
- mantissa += tail;
- }
-
- *p++ = '0';
- *p++ = dp->conversion - 'A' + 'X';
- pad_ptr = p;
- {
- int digit;
-
- digit = (int) mantissa;
- mantissa -= digit;
- *p++ = '0' + digit;
- if ((flags & FLAG_ALT)
- || mantissa > 0.0 || precision > 0)
- {
- *p++ = decimal_point_char ();
- /* This loop terminates because we assume
- that FLT_RADIX is a power of 2. */
- while (mantissa > 0.0)
- {
- mantissa *= 16.0;
- digit = (int) mantissa;
- mantissa -= digit;
- *p++ = digit
- + (digit < 10
- ? '0'
- : dp->conversion - 10);
- if (precision > 0)
- precision--;
- }
- while (precision > 0)
- {
- *p++ = '0';
- precision--;
- }
- }
- }
- *p++ = dp->conversion - 'A' + 'P';
-# if WIDE_CHAR_VERSION
- {
- static const wchar_t decimal_format[] =
- { '%', '+', 'd', '\0' };
- SNPRINTF (p, 6 + 1, decimal_format, exponent);
- }
- while (*p != '\0')
- p++;
-# else
- if (sizeof (DCHAR_T) == 1)
- {
- sprintf ((char *) p, "%+d", exponent);
- while (*p != '\0')
- p++;
- }
- else
- {
- char expbuf[6 + 1];
- const char *ep;
- sprintf (expbuf, "%+d", exponent);
- for (ep = expbuf; (*p = *ep) != '\0'; ep++)
- p++;
- }
-# endif
- }
- }
-# else
- abort ();
-# endif
- }
-
- /* The generated string now extends from tmp to p, with the
- zero padding insertion point being at pad_ptr. */
- count = p - tmp;
-
- if (count < width)
- {
- size_t pad = width - count;
- DCHAR_T *end = p + pad;
-
- if (flags & FLAG_LEFT)
- {
- /* Pad with spaces on the right. */
- for (; pad > 0; pad--)
- *p++ = ' ';
- }
- else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
- {
- /* Pad with zeroes. */
- DCHAR_T *q = end;
-
- while (p > pad_ptr)
- *--q = *--p;
- for (; pad > 0; pad--)
- *p++ = '0';
- }
- else
- {
- /* Pad with spaces on the left. */
- DCHAR_T *q = end;
-
- while (p > tmp)
- *--q = *--p;
- for (; pad > 0; pad--)
- *p++ = ' ';
- }
-
- p = end;
- }
-
- count = p - tmp;
-
- if (count >= tmp_length)
- /* tmp_length was incorrectly calculated - fix the
- code above! */
- abort ();
-
- /* Make room for the result. */
- if (count >= allocated - length)
- {
- size_t n = xsum (length, count);
-
- ENSURE_ALLOCATION (n);
- }
-
- /* Append the result. */
- memcpy (result + length, tmp, count * sizeof (DCHAR_T));
- if (tmp != tmpbuf)
- free (tmp);
- length += count;
- }
-#endif
-#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
- else if ((dp->conversion == 'f' || dp->conversion == 'F'
- || dp->conversion == 'e' || dp->conversion == 'E'
- || dp->conversion == 'g' || dp->conversion == 'G'
- || dp->conversion == 'a' || dp->conversion == 'A')
- && (0
-# if NEED_PRINTF_DOUBLE
- || a.arg[dp->arg_index].type == TYPE_DOUBLE
-# elif NEED_PRINTF_INFINITE_DOUBLE
- || (a.arg[dp->arg_index].type == TYPE_DOUBLE
- /* The systems (mingw) which produce wrong output
- for Inf, -Inf, and NaN also do so for -0.0.
- Therefore we treat this case here as well. */
- && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double))
-# endif
-# if NEED_PRINTF_LONG_DOUBLE
- || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
-# elif NEED_PRINTF_INFINITE_LONG_DOUBLE
- || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
- /* Some systems produce wrong output for Inf,
- -Inf, and NaN. Some systems in this category
- (IRIX 5.3) also do so for -0.0. Therefore we
- treat this case here as well. */
- && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble))
-# endif
- ))
- {
-# if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
- arg_type type = a.arg[dp->arg_index].type;
-# endif
- int flags = dp->flags;
- size_t width;
- size_t count;
- int has_precision;
- size_t precision;
- size_t tmp_length;
- DCHAR_T tmpbuf[700];
- DCHAR_T *tmp;
- DCHAR_T *pad_ptr;
- DCHAR_T *p;
-
- width = 0;
- if (dp->width_start != dp->width_end)
- {
- if (dp->width_arg_index != ARG_NONE)
- {
- int arg;
-
- if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
- abort ();
- arg = a.arg[dp->width_arg_index].a.a_int;
- width = arg;
- if (arg < 0)
- {
- /* "A negative field width is taken as a '-' flag
- followed by a positive field width." */
- flags |= FLAG_LEFT;
- width = -width;
- }
- }
- else
- {
- const FCHAR_T *digitp = dp->width_start;
-
- do
- width = xsum (xtimes (width, 10), *digitp++ - '0');
- while (digitp != dp->width_end);
- }
- }
-
- has_precision = 0;
- precision = 0;
- if (dp->precision_start != dp->precision_end)
- {
- if (dp->precision_arg_index != ARG_NONE)
- {
- int arg;
-
- if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
- abort ();
- arg = a.arg[dp->precision_arg_index].a.a_int;
- /* "A negative precision is taken as if the precision
- were omitted." */
- if (arg >= 0)
- {
- precision = arg;
- has_precision = 1;
- }
- }
- else
- {
- const FCHAR_T *digitp = dp->precision_start + 1;
-
- precision = 0;
- while (digitp != dp->precision_end)
- precision = xsum (xtimes (precision, 10), *digitp++ - '0');
- has_precision = 1;
- }
- }
-
- /* POSIX specifies the default precision to be 6 for %f, %F,
- %e, %E, but not for %g, %G. Implementations appear to use
- the same default precision also for %g, %G. But for %a, %A,
- the default precision is 0. */
- if (!has_precision)
- if (!(dp->conversion == 'a' || dp->conversion == 'A'))
- precision = 6;
-
- /* Allocate a temporary buffer of sufficient size. */
-# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
- tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1);
-# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
- tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
-# elif NEED_PRINTF_LONG_DOUBLE
- tmp_length = LDBL_DIG + 1;
-# elif NEED_PRINTF_DOUBLE
- tmp_length = DBL_DIG + 1;
-# else
- tmp_length = 0;
-# endif
- if (tmp_length < precision)
- tmp_length = precision;
-# if NEED_PRINTF_LONG_DOUBLE
-# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
- if (type == TYPE_LONGDOUBLE)
-# endif
- if (dp->conversion == 'f' || dp->conversion == 'F')
- {
- long double arg = a.arg[dp->arg_index].a.a_longdouble;
- if (!(isnanl (arg) || arg + arg == arg))
- {
- /* arg is finite and nonzero. */
- int exponent = floorlog10l (arg < 0 ? -arg : arg);
- if (exponent >= 0 && tmp_length < exponent + precision)
- tmp_length = exponent + precision;
- }
- }
-# endif
-# if NEED_PRINTF_DOUBLE
-# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
- if (type == TYPE_DOUBLE)
-# endif
- if (dp->conversion == 'f' || dp->conversion == 'F')
- {
- double arg = a.arg[dp->arg_index].a.a_double;
- if (!(isnand (arg) || arg + arg == arg))
- {
- /* arg is finite and nonzero. */
- int exponent = floorlog10 (arg < 0 ? -arg : arg);
- if (exponent >= 0 && tmp_length < exponent + precision)
- tmp_length = exponent + precision;
- }
- }
-# endif
- /* Account for sign, decimal point etc. */
- tmp_length = xsum (tmp_length, 12);
-
- if (tmp_length < width)
- tmp_length = width;
-
- tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
-
- if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
- tmp = tmpbuf;
- else
- {
- size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
-
- if (size_overflow_p (tmp_memsize))
- /* Overflow, would lead to out of memory. */
- goto out_of_memory;
- tmp = (DCHAR_T *) malloc (tmp_memsize);
- if (tmp == NULL)
- /* Out of memory. */
- goto out_of_memory;
- }
-
- pad_ptr = NULL;
- p = tmp;
-
-# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
-# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
- if (type == TYPE_LONGDOUBLE)
-# endif
- {
- long double arg = a.arg[dp->arg_index].a.a_longdouble;
-
- if (isnanl (arg))
- {
- if (dp->conversion >= 'A' && dp->conversion <= 'Z')
- {
- *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
- }
- else
- {
- *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
- }
- }
- else
- {
- int sign = 0;
- DECL_LONG_DOUBLE_ROUNDING
-
- BEGIN_LONG_DOUBLE_ROUNDING ();
-
- if (signbit (arg)) /* arg < 0.0L or negative zero */
- {
- sign = -1;
- arg = -arg;
- }
-
- if (sign < 0)
- *p++ = '-';
- else if (flags & FLAG_SHOWSIGN)
- *p++ = '+';
- else if (flags & FLAG_SPACE)
- *p++ = ' ';
-
- if (arg > 0.0L && arg + arg == arg)
- {
- if (dp->conversion >= 'A' && dp->conversion <= 'Z')
- {
- *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
- }
- else
- {
- *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
- }
- }
- else
- {
-# if NEED_PRINTF_LONG_DOUBLE
- pad_ptr = p;
-
- if (dp->conversion == 'f' || dp->conversion == 'F')
- {
- char *digits;
- size_t ndigits;
-
- digits =
- scale10_round_decimal_long_double (arg, precision);
- if (digits == NULL)
- {
- END_LONG_DOUBLE_ROUNDING ();
- goto out_of_memory;
- }
- ndigits = strlen (digits);
-
- if (ndigits > precision)
- do
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- while (ndigits > precision);
- else
- *p++ = '0';
- /* Here ndigits <= precision. */
- if ((flags & FLAG_ALT) || precision > 0)
- {
- *p++ = decimal_point_char ();
- for (; precision > ndigits; precision--)
- *p++ = '0';
- while (ndigits > 0)
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- }
-
- free (digits);
- }
- else if (dp->conversion == 'e' || dp->conversion == 'E')
- {
- int exponent;
-
- if (arg == 0.0L)
- {
- exponent = 0;
- *p++ = '0';
- if ((flags & FLAG_ALT) || precision > 0)
- {
- *p++ = decimal_point_char ();
- for (; precision > 0; precision--)
- *p++ = '0';
- }
- }
- else
- {
- /* arg > 0.0L. */
- int adjusted;
- char *digits;
- size_t ndigits;
-
- exponent = floorlog10l (arg);
- adjusted = 0;
- for (;;)
- {
- digits =
- scale10_round_decimal_long_double (arg,
- (int)precision - exponent);
- if (digits == NULL)
- {
- END_LONG_DOUBLE_ROUNDING ();
- goto out_of_memory;
- }
- ndigits = strlen (digits);
-
- if (ndigits == precision + 1)
- break;
- if (ndigits < precision
- || ndigits > precision + 2)
- /* The exponent was not guessed
- precisely enough. */
- abort ();
- if (adjusted)
- /* None of two values of exponent is
- the right one. Prevent an endless
- loop. */
- abort ();
- free (digits);
- if (ndigits == precision)
- exponent -= 1;
- else
- exponent += 1;
- adjusted = 1;
- }
- /* Here ndigits = precision+1. */
- if (is_borderline (digits, precision))
- {
- /* Maybe the exponent guess was too high
- and a smaller exponent can be reached
- by turning a 10...0 into 9...9x. */
- char *digits2 =
- scale10_round_decimal_long_double (arg,
- (int)precision - exponent + 1);
- if (digits2 == NULL)
- {
- free (digits);
- END_LONG_DOUBLE_ROUNDING ();
- goto out_of_memory;
- }
- if (strlen (digits2) == precision + 1)
- {
- free (digits);
- digits = digits2;
- exponent -= 1;
- }
- else
- free (digits2);
- }
- /* Here ndigits = precision+1. */
-
- *p++ = digits[--ndigits];
- if ((flags & FLAG_ALT) || precision > 0)
- {
- *p++ = decimal_point_char ();
- while (ndigits > 0)
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- }
-
- free (digits);
- }
-
- *p++ = dp->conversion; /* 'e' or 'E' */
-# if WIDE_CHAR_VERSION
- {
- static const wchar_t decimal_format[] =
- { '%', '+', '.', '2', 'd', '\0' };
- SNPRINTF (p, 6 + 1, decimal_format, exponent);
- }
- while (*p != '\0')
- p++;
-# else
- if (sizeof (DCHAR_T) == 1)
- {
- sprintf ((char *) p, "%+.2d", exponent);
- while (*p != '\0')
- p++;
- }
- else
- {
- char expbuf[6 + 1];
- const char *ep;
- sprintf (expbuf, "%+.2d", exponent);
- for (ep = expbuf; (*p = *ep) != '\0'; ep++)
- p++;
- }
-# endif
- }
- else if (dp->conversion == 'g' || dp->conversion == 'G')
- {
- if (precision == 0)
- precision = 1;
- /* precision >= 1. */
-
- if (arg == 0.0L)
- /* The exponent is 0, >= -4, < precision.
- Use fixed-point notation. */
- {
- size_t ndigits = precision;
- /* Number of trailing zeroes that have to be
- dropped. */
- size_t nzeroes =
- (flags & FLAG_ALT ? 0 : precision - 1);
-
- --ndigits;
- *p++ = '0';
- if ((flags & FLAG_ALT) || ndigits > nzeroes)
- {
- *p++ = decimal_point_char ();
- while (ndigits > nzeroes)
- {
- --ndigits;
- *p++ = '0';
- }
- }
- }
- else
- {
- /* arg > 0.0L. */
- int exponent;
- int adjusted;
- char *digits;
- size_t ndigits;
- size_t nzeroes;
-
- exponent = floorlog10l (arg);
- adjusted = 0;
- for (;;)
- {
- digits =
- scale10_round_decimal_long_double (arg,
- (int)(precision - 1) - exponent);
- if (digits == NULL)
- {
- END_LONG_DOUBLE_ROUNDING ();
- goto out_of_memory;
- }
- ndigits = strlen (digits);
-
- if (ndigits == precision)
- break;
- if (ndigits < precision - 1
- || ndigits > precision + 1)
- /* The exponent was not guessed
- precisely enough. */
- abort ();
- if (adjusted)
- /* None of two values of exponent is
- the right one. Prevent an endless
- loop. */
- abort ();
- free (digits);
- if (ndigits < precision)
- exponent -= 1;
- else
- exponent += 1;
- adjusted = 1;
- }
- /* Here ndigits = precision. */
- if (is_borderline (digits, precision - 1))
- {
- /* Maybe the exponent guess was too high
- and a smaller exponent can be reached
- by turning a 10...0 into 9...9x. */
- char *digits2 =
- scale10_round_decimal_long_double (arg,
- (int)(precision - 1) - exponent + 1);
- if (digits2 == NULL)
- {
- free (digits);
- END_LONG_DOUBLE_ROUNDING ();
- goto out_of_memory;
- }
- if (strlen (digits2) == precision)
- {
- free (digits);
- digits = digits2;
- exponent -= 1;
- }
- else
- free (digits2);
- }
- /* Here ndigits = precision. */
-
- /* Determine the number of trailing zeroes
- that have to be dropped. */
- nzeroes = 0;
- if ((flags & FLAG_ALT) == 0)
- while (nzeroes < ndigits
- && digits[nzeroes] == '0')
- nzeroes++;
-
- /* The exponent is now determined. */
- if (exponent >= -4
- && exponent < (long)precision)
- {
- /* Fixed-point notation:
- max(exponent,0)+1 digits, then the
- decimal point, then the remaining
- digits without trailing zeroes. */
- if (exponent >= 0)
- {
- size_t ecount = exponent + 1;
- /* Note: count <= precision = ndigits. */
- for (; ecount > 0; ecount--)
- *p++ = digits[--ndigits];
- if ((flags & FLAG_ALT) || ndigits > nzeroes)
- {
- *p++ = decimal_point_char ();
- while (ndigits > nzeroes)
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- }
- }
- else
- {
- size_t ecount = -exponent - 1;
- *p++ = '0';
- *p++ = decimal_point_char ();
- for (; ecount > 0; ecount--)
- *p++ = '0';
- while (ndigits > nzeroes)
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- }
- }
- else
- {
- /* Exponential notation. */
- *p++ = digits[--ndigits];
- if ((flags & FLAG_ALT) || ndigits > nzeroes)
- {
- *p++ = decimal_point_char ();
- while (ndigits > nzeroes)
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- }
- *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
-# if WIDE_CHAR_VERSION
- {
- static const wchar_t decimal_format[] =
- { '%', '+', '.', '2', 'd', '\0' };
- SNPRINTF (p, 6 + 1, decimal_format, exponent);
- }
- while (*p != '\0')
- p++;
-# else
- if (sizeof (DCHAR_T) == 1)
- {
- sprintf ((char *) p, "%+.2d", exponent);
- while (*p != '\0')
- p++;
- }
- else
- {
- char expbuf[6 + 1];
- const char *ep;
- sprintf (expbuf, "%+.2d", exponent);
- for (ep = expbuf; (*p = *ep) != '\0'; ep++)
- p++;
- }
-# endif
- }
-
- free (digits);
- }
- }
- else
- abort ();
-# else
- /* arg is finite. */
- if (!(arg == 0.0L))
- abort ();
-
- pad_ptr = p;
-
- if (dp->conversion == 'f' || dp->conversion == 'F')
- {
- *p++ = '0';
- if ((flags & FLAG_ALT) || precision > 0)
- {
- *p++ = decimal_point_char ();
- for (; precision > 0; precision--)
- *p++ = '0';
- }
- }
- else if (dp->conversion == 'e' || dp->conversion == 'E')
- {
- *p++ = '0';
- if ((flags & FLAG_ALT) || precision > 0)
- {
- *p++ = decimal_point_char ();
- for (; precision > 0; precision--)
- *p++ = '0';
- }
- *p++ = dp->conversion; /* 'e' or 'E' */
- *p++ = '+';
- *p++ = '0';
- *p++ = '0';
- }
- else if (dp->conversion == 'g' || dp->conversion == 'G')
- {
- *p++ = '0';
- if (flags & FLAG_ALT)
- {
- size_t ndigits =
- (precision > 0 ? precision - 1 : 0);
- *p++ = decimal_point_char ();
- for (; ndigits > 0; --ndigits)
- *p++ = '0';
- }
- }
- else if (dp->conversion == 'a' || dp->conversion == 'A')
- {
- *p++ = '0';
- *p++ = dp->conversion - 'A' + 'X';
- pad_ptr = p;
- *p++ = '0';
- if ((flags & FLAG_ALT) || precision > 0)
- {
- *p++ = decimal_point_char ();
- for (; precision > 0; precision--)
- *p++ = '0';
- }
- *p++ = dp->conversion - 'A' + 'P';
- *p++ = '+';
- *p++ = '0';
- }
- else
- abort ();
-# endif
- }
-
- END_LONG_DOUBLE_ROUNDING ();
- }
- }
-# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
- else
-# endif
-# endif
-# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
- {
- double arg = a.arg[dp->arg_index].a.a_double;
-
- if (isnand (arg))
- {
- if (dp->conversion >= 'A' && dp->conversion <= 'Z')
- {
- *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
- }
- else
- {
- *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
- }
- }
- else
- {
- int sign = 0;
-
- if (signbit (arg)) /* arg < 0.0 or negative zero */
- {
- sign = -1;
- arg = -arg;
- }
-
- if (sign < 0)
- *p++ = '-';
- else if (flags & FLAG_SHOWSIGN)
- *p++ = '+';
- else if (flags & FLAG_SPACE)
- *p++ = ' ';
-
- if (arg > 0.0 && arg + arg == arg)
- {
- if (dp->conversion >= 'A' && dp->conversion <= 'Z')
- {
- *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
- }
- else
- {
- *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
- }
- }
- else
- {
-# if NEED_PRINTF_DOUBLE
- pad_ptr = p;
-
- if (dp->conversion == 'f' || dp->conversion == 'F')
- {
- char *digits;
- size_t ndigits;
-
- digits =
- scale10_round_decimal_double (arg, precision);
- if (digits == NULL)
- goto out_of_memory;
- ndigits = strlen (digits);
-
- if (ndigits > precision)
- do
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- while (ndigits > precision);
- else
- *p++ = '0';
- /* Here ndigits <= precision. */
- if ((flags & FLAG_ALT) || precision > 0)
- {
- *p++ = decimal_point_char ();
- for (; precision > ndigits; precision--)
- *p++ = '0';
- while (ndigits > 0)
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- }
-
- free (digits);
- }
- else if (dp->conversion == 'e' || dp->conversion == 'E')
- {
- int exponent;
-
- if (arg == 0.0)
- {
- exponent = 0;
- *p++ = '0';
- if ((flags & FLAG_ALT) || precision > 0)
- {
- *p++ = decimal_point_char ();
- for (; precision > 0; precision--)
- *p++ = '0';
- }
- }
- else
- {
- /* arg > 0.0. */
- int adjusted;
- char *digits;
- size_t ndigits;
-
- exponent = floorlog10 (arg);
- adjusted = 0;
- for (;;)
- {
- digits =
- scale10_round_decimal_double (arg,
- (int)precision - exponent);
- if (digits == NULL)
- goto out_of_memory;
- ndigits = strlen (digits);
-
- if (ndigits == precision + 1)
- break;
- if (ndigits < precision
- || ndigits > precision + 2)
- /* The exponent was not guessed
- precisely enough. */
- abort ();
- if (adjusted)
- /* None of two values of exponent is
- the right one. Prevent an endless
- loop. */
- abort ();
- free (digits);
- if (ndigits == precision)
- exponent -= 1;
- else
- exponent += 1;
- adjusted = 1;
- }
- /* Here ndigits = precision+1. */
- if (is_borderline (digits, precision))
- {
- /* Maybe the exponent guess was too high
- and a smaller exponent can be reached
- by turning a 10...0 into 9...9x. */
- char *digits2 =
- scale10_round_decimal_double (arg,
- (int)precision - exponent + 1);
- if (digits2 == NULL)
- {
- free (digits);
- goto out_of_memory;
- }
- if (strlen (digits2) == precision + 1)
- {
- free (digits);
- digits = digits2;
- exponent -= 1;
- }
- else
- free (digits2);
- }
- /* Here ndigits = precision+1. */
-
- *p++ = digits[--ndigits];
- if ((flags & FLAG_ALT) || precision > 0)
- {
- *p++ = decimal_point_char ();
- while (ndigits > 0)
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- }
-
- free (digits);
- }
-
- *p++ = dp->conversion; /* 'e' or 'E' */
-# if WIDE_CHAR_VERSION
- {
- static const wchar_t decimal_format[] =
- /* Produce the same number of exponent digits
- as the native printf implementation. */
-# if defined _WIN32 && ! defined __CYGWIN__
- { '%', '+', '.', '3', 'd', '\0' };
-# else
- { '%', '+', '.', '2', 'd', '\0' };
-# endif
- SNPRINTF (p, 6 + 1, decimal_format, exponent);
- }
- while (*p != '\0')
- p++;
-# else
- {
- static const char decimal_format[] =
- /* Produce the same number of exponent digits
- as the native printf implementation. */
-# if defined _WIN32 && ! defined __CYGWIN__
- "%+.3d";
-# else
- "%+.2d";
-# endif
- if (sizeof (DCHAR_T) == 1)
- {
- sprintf ((char *) p, decimal_format, exponent);
- while (*p != '\0')
- p++;
- }
- else
- {
- char expbuf[6 + 1];
- const char *ep;
- sprintf (expbuf, decimal_format, exponent);
- for (ep = expbuf; (*p = *ep) != '\0'; ep++)
- p++;
- }
- }
-# endif
- }
- else if (dp->conversion == 'g' || dp->conversion == 'G')
- {
- if (precision == 0)
- precision = 1;
- /* precision >= 1. */
-
- if (arg == 0.0)
- /* The exponent is 0, >= -4, < precision.
- Use fixed-point notation. */
- {
- size_t ndigits = precision;
- /* Number of trailing zeroes that have to be
- dropped. */
- size_t nzeroes =
- (flags & FLAG_ALT ? 0 : precision - 1);
-
- --ndigits;
- *p++ = '0';
- if ((flags & FLAG_ALT) || ndigits > nzeroes)
- {
- *p++ = decimal_point_char ();
- while (ndigits > nzeroes)
- {
- --ndigits;
- *p++ = '0';
- }
- }
- }
- else
- {
- /* arg > 0.0. */
- int exponent;
- int adjusted;
- char *digits;
- size_t ndigits;
- size_t nzeroes;
-
- exponent = floorlog10 (arg);
- adjusted = 0;
- for (;;)
- {
- digits =
- scale10_round_decimal_double (arg,
- (int)(precision - 1) - exponent);
- if (digits == NULL)
- goto out_of_memory;
- ndigits = strlen (digits);
-
- if (ndigits == precision)
- break;
- if (ndigits < precision - 1
- || ndigits > precision + 1)
- /* The exponent was not guessed
- precisely enough. */
- abort ();
- if (adjusted)
- /* None of two values of exponent is
- the right one. Prevent an endless
- loop. */
- abort ();
- free (digits);
- if (ndigits < precision)
- exponent -= 1;
- else
- exponent += 1;
- adjusted = 1;
- }
- /* Here ndigits = precision. */
- if (is_borderline (digits, precision - 1))
- {
- /* Maybe the exponent guess was too high
- and a smaller exponent can be reached
- by turning a 10...0 into 9...9x. */
- char *digits2 =
- scale10_round_decimal_double (arg,
- (int)(precision - 1) - exponent + 1);
- if (digits2 == NULL)
- {
- free (digits);
- goto out_of_memory;
- }
- if (strlen (digits2) == precision)
- {
- free (digits);
- digits = digits2;
- exponent -= 1;
- }
- else
- free (digits2);
- }
- /* Here ndigits = precision. */
-
- /* Determine the number of trailing zeroes
- that have to be dropped. */
- nzeroes = 0;
- if ((flags & FLAG_ALT) == 0)
- while (nzeroes < ndigits
- && digits[nzeroes] == '0')
- nzeroes++;
-
- /* The exponent is now determined. */
- if (exponent >= -4
- && exponent < (long)precision)
- {
- /* Fixed-point notation:
- max(exponent,0)+1 digits, then the
- decimal point, then the remaining
- digits without trailing zeroes. */
- if (exponent >= 0)
- {
- size_t ecount = exponent + 1;
- /* Note: ecount <= precision = ndigits. */
- for (; ecount > 0; ecount--)
- *p++ = digits[--ndigits];
- if ((flags & FLAG_ALT) || ndigits > nzeroes)
- {
- *p++ = decimal_point_char ();
- while (ndigits > nzeroes)
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- }
- }
- else
- {
- size_t ecount = -exponent - 1;
- *p++ = '0';
- *p++ = decimal_point_char ();
- for (; ecount > 0; ecount--)
- *p++ = '0';
- while (ndigits > nzeroes)
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- }
- }
- else
- {
- /* Exponential notation. */
- *p++ = digits[--ndigits];
- if ((flags & FLAG_ALT) || ndigits > nzeroes)
- {
- *p++ = decimal_point_char ();
- while (ndigits > nzeroes)
- {
- --ndigits;
- *p++ = digits[ndigits];
- }
- }
- *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
-# if WIDE_CHAR_VERSION
- {
- static const wchar_t decimal_format[] =
- /* Produce the same number of exponent digits
- as the native printf implementation. */
-# if defined _WIN32 && ! defined __CYGWIN__
- { '%', '+', '.', '3', 'd', '\0' };
-# else
- { '%', '+', '.', '2', 'd', '\0' };
-# endif
- SNPRINTF (p, 6 + 1, decimal_format, exponent);
- }
- while (*p != '\0')
- p++;
-# else
- {
- static const char decimal_format[] =
- /* Produce the same number of exponent digits
- as the native printf implementation. */
-# if defined _WIN32 && ! defined __CYGWIN__
- "%+.3d";
-# else
- "%+.2d";
-# endif
- if (sizeof (DCHAR_T) == 1)
- {
- sprintf ((char *) p, decimal_format, exponent);
- while (*p != '\0')
- p++;
- }
- else
- {
- char expbuf[6 + 1];
- const char *ep;
- sprintf (expbuf, decimal_format, exponent);
- for (ep = expbuf; (*p = *ep) != '\0'; ep++)
- p++;
- }
- }
-# endif
- }
-
- free (digits);
- }
- }
- else
- abort ();
-# else
- /* arg is finite. */
- if (!(arg == 0.0))
- abort ();
-
- pad_ptr = p;
-
- if (dp->conversion == 'f' || dp->conversion == 'F')
- {
- *p++ = '0';
- if ((flags & FLAG_ALT) || precision > 0)
- {
- *p++ = decimal_point_char ();
- for (; precision > 0; precision--)
- *p++ = '0';
- }
- }
- else if (dp->conversion == 'e' || dp->conversion == 'E')
- {
- *p++ = '0';
- if ((flags & FLAG_ALT) || precision > 0)
- {
- *p++ = decimal_point_char ();
- for (; precision > 0; precision--)
- *p++ = '0';
- }
- *p++ = dp->conversion; /* 'e' or 'E' */
- *p++ = '+';
- /* Produce the same number of exponent digits as
- the native printf implementation. */
-# if defined _WIN32 && ! defined __CYGWIN__
- *p++ = '0';
-# endif
- *p++ = '0';
- *p++ = '0';
- }
- else if (dp->conversion == 'g' || dp->conversion == 'G')
- {
- *p++ = '0';
- if (flags & FLAG_ALT)
- {
- size_t ndigits =
- (precision > 0 ? precision - 1 : 0);
- *p++ = decimal_point_char ();
- for (; ndigits > 0; --ndigits)
- *p++ = '0';
- }
- }
- else
- abort ();
-# endif
- }
- }
- }
-# endif
-
- /* The generated string now extends from tmp to p, with the
- zero padding insertion point being at pad_ptr. */
- count = p - tmp;
-
- if (count < width)
- {
- size_t pad = width - count;
- DCHAR_T *end = p + pad;
-
- if (flags & FLAG_LEFT)
- {
- /* Pad with spaces on the right. */
- for (; pad > 0; pad--)
- *p++ = ' ';
- }
- else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
- {
- /* Pad with zeroes. */
- DCHAR_T *q = end;
-
- while (p > pad_ptr)
- *--q = *--p;
- for (; pad > 0; pad--)
- *p++ = '0';
- }
- else
- {
- /* Pad with spaces on the left. */
- DCHAR_T *q = end;
-
- while (p > tmp)
- *--q = *--p;
- for (; pad > 0; pad--)
- *p++ = ' ';
- }
-
- p = end;
- }
-
- count = p - tmp;
-
- if (count >= tmp_length)
- /* tmp_length was incorrectly calculated - fix the
- code above! */
- abort ();
-
- /* Make room for the result. */
- if (count >= allocated - length)
- {
- size_t n = xsum (length, count);
-
- ENSURE_ALLOCATION (n);
- }
-
- /* Append the result. */
- memcpy (result + length, tmp, count * sizeof (DCHAR_T));
- if (tmp != tmpbuf)
- free (tmp);
- length += count;
- }
-#endif
- else
- {
- arg_type type = a.arg[dp->arg_index].type;
- int flags = dp->flags;
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
- int has_width;
-#endif
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
- size_t width;
-#endif
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION
- int has_precision;
- size_t precision;
-#endif
-#if NEED_PRINTF_UNBOUNDED_PRECISION
- int prec_ourselves;
-#else
-# define prec_ourselves 0
-#endif
-#if NEED_PRINTF_FLAG_LEFTADJUST
-# define pad_ourselves 1
-#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
- int pad_ourselves;
-#else
-# define pad_ourselves 0
-#endif
- TCHAR_T *fbp;
- unsigned int prefix_count;
- int prefixes[2] IF_LINT (= { 0 });
- int orig_errno;
-#if !USE_SNPRINTF
- size_t tmp_length;
- TCHAR_T tmpbuf[700];
- TCHAR_T *tmp;
-#endif
-
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
- has_width = 0;
-#endif
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
- width = 0;
- if (dp->width_start != dp->width_end)
- {
- if (dp->width_arg_index != ARG_NONE)
- {
- int arg;
-
- if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
- abort ();
- arg = a.arg[dp->width_arg_index].a.a_int;
- width = arg;
- if (arg < 0)
- {
- /* "A negative field width is taken as a '-' flag
- followed by a positive field width." */
- flags |= FLAG_LEFT;
- width = -width;
- }
- }
- else
- {
- const FCHAR_T *digitp = dp->width_start;
-
- do
- width = xsum (xtimes (width, 10), *digitp++ - '0');
- while (digitp != dp->width_end);
- }
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
- has_width = 1;
-#endif
- }
-#endif
-
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION
- has_precision = 0;
- precision = 6;
- if (dp->precision_start != dp->precision_end)
- {
- if (dp->precision_arg_index != ARG_NONE)
- {
- int arg;
-
- if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
- abort ();
- arg = a.arg[dp->precision_arg_index].a.a_int;
- /* "A negative precision is taken as if the precision
- were omitted." */
- if (arg >= 0)
- {
- precision = arg;
- has_precision = 1;
- }
- }
- else
- {
- const FCHAR_T *digitp = dp->precision_start + 1;
-
- precision = 0;
- while (digitp != dp->precision_end)
- precision = xsum (xtimes (precision, 10), *digitp++ - '0');
- has_precision = 1;
- }
- }
-#endif
-
- /* Decide whether to handle the precision ourselves. */
-#if NEED_PRINTF_UNBOUNDED_PRECISION
- switch (dp->conversion)
- {
- case 'd': case 'i': case 'u':
- case 'o':
- case 'x': case 'X': case 'p':
- prec_ourselves = has_precision && (precision > 0);
- break;
- default:
- prec_ourselves = 0;
- break;
- }
-#endif
-
- /* Decide whether to perform the padding ourselves. */
-#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
- switch (dp->conversion)
- {
-# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
- /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
- to perform the padding after this conversion. Functions
- with unistdio extensions perform the padding based on
- character count rather than element count. */
- case 'c': case 's':
-# endif
-# if NEED_PRINTF_FLAG_ZERO
- case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
- case 'a': case 'A':
-# endif
- pad_ourselves = 1;
- break;
- default:
- pad_ourselves = prec_ourselves;
- break;
- }
-#endif
-
-#if !USE_SNPRINTF
- /* Allocate a temporary buffer of sufficient size for calling
- sprintf. */
- tmp_length =
- MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type,
- flags, width, has_precision, precision,
- pad_ourselves);
-
- if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T))
- tmp = tmpbuf;
- else
- {
- size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T));
-
- if (size_overflow_p (tmp_memsize))
- /* Overflow, would lead to out of memory. */
- goto out_of_memory;
- tmp = (TCHAR_T *) malloc (tmp_memsize);
- if (tmp == NULL)
- /* Out of memory. */
- goto out_of_memory;
- }
-#endif
-
- /* Construct the format string for calling snprintf or
- sprintf. */
- fbp = buf;
- *fbp++ = '%';
-#if NEED_PRINTF_FLAG_GROUPING
- /* The underlying implementation doesn't support the ' flag.
- Produce no grouping characters in this case; this is
- acceptable because the grouping is locale dependent. */
-#else
- if (flags & FLAG_GROUP)
- *fbp++ = '\'';
-#endif
- if (flags & FLAG_LEFT)
- *fbp++ = '-';
- if (flags & FLAG_SHOWSIGN)
- *fbp++ = '+';
- if (flags & FLAG_SPACE)
- *fbp++ = ' ';
- if (flags & FLAG_ALT)
- *fbp++ = '#';
-#if __GLIBC__ >= 2 && !defined __UCLIBC__
- if (flags & FLAG_LOCALIZED)
- *fbp++ = 'I';
-#endif
- if (!pad_ourselves)
- {
- if (flags & FLAG_ZERO)
- *fbp++ = '0';
- if (dp->width_start != dp->width_end)
- {
- size_t n = dp->width_end - dp->width_start;
- /* The width specification is known to consist only
- of standard ASCII characters. */
- if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
- {
- memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T));
- fbp += n;
- }
- else
- {
- const FCHAR_T *mp = dp->width_start;
- do
- *fbp++ = *mp++;
- while (--n > 0);
- }
- }
- }
- if (!prec_ourselves)
- {
- if (dp->precision_start != dp->precision_end)
- {
- size_t n = dp->precision_end - dp->precision_start;
- /* The precision specification is known to consist only
- of standard ASCII characters. */
- if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
- {
- memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T));
- fbp += n;
- }
- else
- {
- const FCHAR_T *mp = dp->precision_start;
- do
- *fbp++ = *mp++;
- while (--n > 0);
- }
- }
- }
-
- switch (type)
- {
- case TYPE_LONGLONGINT:
- case TYPE_ULONGLONGINT:
-#if defined _WIN32 && ! defined __CYGWIN__
- *fbp++ = 'I';
- *fbp++ = '6';
- *fbp++ = '4';
- break;
-#else
- *fbp++ = 'l';
-#endif
- FALLTHROUGH;
- case TYPE_LONGINT:
- case TYPE_ULONGINT:
-#if HAVE_WINT_T
- case TYPE_WIDE_CHAR:
-#endif
-#if HAVE_WCHAR_T
- case TYPE_WIDE_STRING:
-#endif
- *fbp++ = 'l';
- break;
- case TYPE_LONGDOUBLE:
- *fbp++ = 'L';
- break;
- default:
- break;
- }
-#if NEED_PRINTF_DIRECTIVE_F
- if (dp->conversion == 'F')
- *fbp = 'f';
- else
-#endif
- *fbp = dp->conversion;
-#if USE_SNPRINTF
-# if ((HAVE_SNPRINTF_RETVAL_C99 && HAVE_SNPRINTF_TRUNCATION_C99) \
- || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) \
- && !defined __UCLIBC__) \
- || (defined __APPLE__ && defined __MACH__) \
- || defined __ANDROID__ \
- || (defined _WIN32 && ! defined __CYGWIN__))
- /* On systems where we know that snprintf's return value
- conforms to ISO C 99 (HAVE_SNPRINTF_RETVAL_C99) and that
- snprintf always produces NUL-terminated strings
- (HAVE_SNPRINTF_TRUNCATION_C99), it is possible to avoid
- using %n. And it is desirable to do so, because more and
- more platforms no longer support %n, for "security reasons".
- In particular, the following platforms:
- - On glibc2 systems from 2004-10-18 or newer, the use of
- %n in format strings in writable memory may crash the
- program (if compiled with _FORTIFY_SOURCE=2).
- - On Mac OS X 10.13 or newer, the use of %n in format
- strings in writable memory by default crashes the
- program.
- - On Android, starting on 2018-03-07, the use of %n in
- format strings produces a fatal error (see
- <https://android.googlesource.com/platform/bionic/+/41398d03b7e8e0dfb951660ae713e682e9fc0336>).
- On these platforms, HAVE_SNPRINTF_RETVAL_C99 and
- HAVE_SNPRINTF_TRUNCATION_C99 are 1. We have listed them
- explicitly in the condition above, in case of cross-
- compilation (just to be sure). */
- /* On native Windows systems (such as mingw), we can avoid using
- %n because:
- - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
- snprintf does not write more than the specified number
- of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes
- '4', '5', '6' into buf, not '4', '5', '\0'.)
- - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
- allows us to recognize the case of an insufficient
- buffer size: it returns -1 in this case.
- On native Windows systems (such as mingw) where the OS is
- Windows Vista, the use of %n in format strings by default
- crashes the program. See
- <https://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
- <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/set-printf-count-output>
- So we should avoid %n in this situation. */
- fbp[1] = '\0';
-# else /* AIX <= 5.1, HP-UX, IRIX, OSF/1, Solaris <= 9, BeOS */
- fbp[1] = '%';
- fbp[2] = 'n';
- fbp[3] = '\0';
-# endif
-#else
- fbp[1] = '\0';
-#endif
-
- /* Construct the arguments for calling snprintf or sprintf. */
- prefix_count = 0;
- if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
- {
- if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
- abort ();
- prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
- }
- if (!prec_ourselves && dp->precision_arg_index != ARG_NONE)
- {
- if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
- abort ();
- prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
- }
-
-#if USE_SNPRINTF
- /* The SNPRINTF result is appended after result[0..length].
- The latter is an array of DCHAR_T; SNPRINTF appends an
- array of TCHAR_T to it. This is possible because
- sizeof (TCHAR_T) divides sizeof (DCHAR_T) and
- alignof (TCHAR_T) <= alignof (DCHAR_T). */
-# define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T))
- /* Ensure that maxlen below will be >= 2. Needed on BeOS,
- where an snprintf() with maxlen==1 acts like sprintf(). */
- ENSURE_ALLOCATION (xsum (length,
- (2 + TCHARS_PER_DCHAR - 1)
- / TCHARS_PER_DCHAR));
- /* Prepare checking whether snprintf returns the count
- via %n. */
- *(TCHAR_T *) (result + length) = '\0';
-#endif
-
- orig_errno = errno;
-
- for (;;)
- {
- int count = -1;
-
-#if USE_SNPRINTF
- int retcount = 0;
- size_t maxlen = allocated - length;
- /* SNPRINTF can fail if its second argument is
- > INT_MAX. */
- if (maxlen > INT_MAX / TCHARS_PER_DCHAR)
- maxlen = INT_MAX / TCHARS_PER_DCHAR;
- maxlen = maxlen * TCHARS_PER_DCHAR;
-# define SNPRINTF_BUF(arg) \
- switch (prefix_count) \
- { \
- case 0: \
- retcount = SNPRINTF ((TCHAR_T *) (result + length), \
- maxlen, buf, \
- arg, &count); \
- break; \
- case 1: \
- retcount = SNPRINTF ((TCHAR_T *) (result + length), \
- maxlen, buf, \
- prefixes[0], arg, &count); \
- break; \
- case 2: \
- retcount = SNPRINTF ((TCHAR_T *) (result + length), \
- maxlen, buf, \
- prefixes[0], prefixes[1], arg, \
- &count); \
- break; \
- default: \
- abort (); \
- }
-#else
-# define SNPRINTF_BUF(arg) \
- switch (prefix_count) \
- { \
- case 0: \
- count = sprintf (tmp, buf, arg); \
- break; \
- case 1: \
- count = sprintf (tmp, buf, prefixes[0], arg); \
- break; \
- case 2: \
- count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
- arg); \
- break; \
- default: \
- abort (); \
- }
-#endif
-
- errno = 0;
- switch (type)
- {
- case TYPE_SCHAR:
- {
- int arg = a.arg[dp->arg_index].a.a_schar;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_UCHAR:
- {
- unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_SHORT:
- {
- int arg = a.arg[dp->arg_index].a.a_short;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_USHORT:
- {
- unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_INT:
- {
- int arg = a.arg[dp->arg_index].a.a_int;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_UINT:
- {
- unsigned int arg = a.arg[dp->arg_index].a.a_uint;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_LONGINT:
- {
- long int arg = a.arg[dp->arg_index].a.a_longint;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_ULONGINT:
- {
- unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_LONGLONGINT:
- {
- long long int arg = a.arg[dp->arg_index].a.a_longlongint;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_ULONGLONGINT:
- {
- unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_DOUBLE:
- {
- double arg = a.arg[dp->arg_index].a.a_double;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_LONGDOUBLE:
- {
- long double arg = a.arg[dp->arg_index].a.a_longdouble;
- SNPRINTF_BUF (arg);
- }
- break;
- case TYPE_CHAR:
- {
- int arg = a.arg[dp->arg_index].a.a_char;
- SNPRINTF_BUF (arg);
- }
- break;
-#if HAVE_WINT_T
- case TYPE_WIDE_CHAR:
- {
- wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
- SNPRINTF_BUF (arg);
- }
- break;
-#endif
- case TYPE_STRING:
- {
- const char *arg = a.arg[dp->arg_index].a.a_string;
- SNPRINTF_BUF (arg);
- }
- break;
-#if HAVE_WCHAR_T
- case TYPE_WIDE_STRING:
- {
- const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
- SNPRINTF_BUF (arg);
- }
- break;
-#endif
- case TYPE_POINTER:
- {
- void *arg = a.arg[dp->arg_index].a.a_pointer;
- SNPRINTF_BUF (arg);
- }
- break;
- default:
- abort ();
- }
-
-#if USE_SNPRINTF
- /* Portability: Not all implementations of snprintf()
- are ISO C 99 compliant. Determine the number of
- bytes that snprintf() has produced or would have
- produced. */
- if (count >= 0)
- {
- /* Verify that snprintf() has NUL-terminated its
- result. */
- if ((unsigned int) count < maxlen
- && ((TCHAR_T *) (result + length)) [count] != '\0')
- abort ();
- /* Portability hack. */
- if (retcount > count)
- count = retcount;
- }
- else
- {
- /* snprintf() doesn't understand the '%n'
- directive. */
- if (fbp[1] != '\0')
- {
- /* Don't use the '%n' directive; instead, look
- at the snprintf() return value. */
- fbp[1] = '\0';
- continue;
- }
- else
- {
- /* Look at the snprintf() return value. */
- if (retcount < 0)
- {
-# if !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF
- /* HP-UX 10.20 snprintf() is doubly deficient:
- It doesn't understand the '%n' directive,
- *and* it returns -1 (rather than the length
- that would have been required) when the
- buffer is too small.
- But a failure at this point can also come
- from other reasons than a too small buffer,
- such as an invalid wide string argument to
- the %ls directive, or possibly an invalid
- floating-point argument. */
- size_t tmp_length =
- MAX_ROOM_NEEDED (&a, dp->arg_index,
- dp->conversion, type, flags,
- width,
- has_precision,
- precision, pad_ourselves);
-
- if (maxlen < tmp_length)
- {
- /* Make more room. But try to do through
- this reallocation only once. */
- size_t bigger_need =
- xsum (length,
- xsum (tmp_length,
- TCHARS_PER_DCHAR - 1)
- / TCHARS_PER_DCHAR);
- /* And always grow proportionally.
- (There may be several arguments, each
- needing a little more room than the
- previous one.) */
- size_t bigger_need2 =
- xsum (xtimes (allocated, 2), 12);
- if (bigger_need < bigger_need2)
- bigger_need = bigger_need2;
- ENSURE_ALLOCATION (bigger_need);
- continue;
- }
-# endif
- }
- else
- count = retcount;
- }
- }
-#endif
-
- /* Attempt to handle failure. */
- if (count < 0)
- {
- /* SNPRINTF or sprintf failed. Save and use the errno
- that it has set, if any. */
- int saved_errno = errno;
- if (saved_errno == 0)
- {
- if (dp->conversion == 'c' || dp->conversion == 's')
- saved_errno = EILSEQ;
- else
- saved_errno = EINVAL;
- }
-
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
-
- errno = saved_errno;
- return NULL;
- }
-
-#if USE_SNPRINTF
- /* Handle overflow of the allocated buffer.
- If such an overflow occurs, a C99 compliant snprintf()
- returns a count >= maxlen. However, a non-compliant
- snprintf() function returns only count = maxlen - 1. To
- cover both cases, test whether count >= maxlen - 1. */
- if ((unsigned int) count + 1 >= maxlen)
- {
- /* If maxlen already has attained its allowed maximum,
- allocating more memory will not increase maxlen.
- Instead of looping, bail out. */
- if (maxlen == INT_MAX / TCHARS_PER_DCHAR)
- goto overflow;
- else
- {
- /* Need at least (count + 1) * sizeof (TCHAR_T)
- bytes. (The +1 is for the trailing NUL.)
- But ask for (count + 2) * sizeof (TCHAR_T)
- bytes, so that in the next round, we likely get
- maxlen > (unsigned int) count + 1
- and so we don't get here again.
- And allocate proportionally, to avoid looping
- eternally if snprintf() reports a too small
- count. */
- size_t n =
- xmax (xsum (length,
- ((unsigned int) count + 2
- + TCHARS_PER_DCHAR - 1)
- / TCHARS_PER_DCHAR),
- xtimes (allocated, 2));
-
- ENSURE_ALLOCATION (n);
- continue;
- }
- }
-#endif
-
-#if NEED_PRINTF_UNBOUNDED_PRECISION
- if (prec_ourselves)
- {
- /* Handle the precision. */
- TCHAR_T *prec_ptr =
-# if USE_SNPRINTF
- (TCHAR_T *) (result + length);
-# else
- tmp;
-# endif
- size_t prefix_count;
- size_t move;
-
- prefix_count = 0;
- /* Put the additional zeroes after the sign. */
- if (count >= 1
- && (*prec_ptr == '-' || *prec_ptr == '+'
- || *prec_ptr == ' '))
- prefix_count = 1;
- /* Put the additional zeroes after the 0x prefix if
- (flags & FLAG_ALT) || (dp->conversion == 'p'). */
- else if (count >= 2
- && prec_ptr[0] == '0'
- && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X'))
- prefix_count = 2;
-
- move = count - prefix_count;
- if (precision > move)
- {
- /* Insert zeroes. */
- size_t insert = precision - move;
- TCHAR_T *prec_end;
-
-# if USE_SNPRINTF
- size_t n =
- xsum (length,
- (count + insert + TCHARS_PER_DCHAR - 1)
- / TCHARS_PER_DCHAR);
- length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
- ENSURE_ALLOCATION (n);
- length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
- prec_ptr = (TCHAR_T *) (result + length);
-# endif
-
- prec_end = prec_ptr + count;
- prec_ptr += prefix_count;
-
- while (prec_end > prec_ptr)
- {
- prec_end--;
- prec_end[insert] = prec_end[0];
- }
-
- prec_end += insert;
- do
- *--prec_end = '0';
- while (prec_end > prec_ptr);
-
- count += insert;
- }
- }
-#endif
-
-#if !USE_SNPRINTF
- if (count >= tmp_length)
- /* tmp_length was incorrectly calculated - fix the
- code above! */
- abort ();
-#endif
-
-#if !DCHAR_IS_TCHAR
- /* Convert from TCHAR_T[] to DCHAR_T[]. */
- if (dp->conversion == 'c' || dp->conversion == 's')
- {
- /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING
- TYPE_WIDE_STRING.
- The result string is not certainly ASCII. */
- const TCHAR_T *tmpsrc;
- DCHAR_T *tmpdst;
- size_t tmpdst_len;
- /* This code assumes that TCHAR_T is 'char'. */
- verify (sizeof (TCHAR_T) == 1);
-# if USE_SNPRINTF
- tmpsrc = (TCHAR_T *) (result + length);
-# else
- tmpsrc = tmp;
-# endif
- tmpdst =
- DCHAR_CONV_FROM_ENCODING (locale_charset (),
- iconveh_question_mark,
- tmpsrc, count,
- NULL,
- NULL, &tmpdst_len);
- if (tmpdst == NULL)
- {
- int saved_errno = errno;
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = saved_errno;
- return NULL;
- }
- ENSURE_ALLOCATION (xsum (length, tmpdst_len));
- DCHAR_CPY (result + length, tmpdst, tmpdst_len);
- free (tmpdst);
- count = tmpdst_len;
- }
- else
- {
- /* The result string is ASCII.
- Simple 1:1 conversion. */
-# if USE_SNPRINTF
- /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a
- no-op conversion, in-place on the array starting
- at (result + length). */
- if (sizeof (DCHAR_T) != sizeof (TCHAR_T))
-# endif
- {
- const TCHAR_T *tmpsrc;
- DCHAR_T *tmpdst;
- size_t n;
-
-# if USE_SNPRINTF
- if (result == resultbuf)
- {
- tmpsrc = (TCHAR_T *) (result + length);
- /* ENSURE_ALLOCATION will not move tmpsrc
- (because it's part of resultbuf). */
- ENSURE_ALLOCATION (xsum (length, count));
- }
- else
- {
- /* ENSURE_ALLOCATION will move the array
- (because it uses realloc(). */
- ENSURE_ALLOCATION (xsum (length, count));
- tmpsrc = (TCHAR_T *) (result + length);
- }
-# else
- tmpsrc = tmp;
- ENSURE_ALLOCATION (xsum (length, count));
-# endif
- tmpdst = result + length;
- /* Copy backwards, because of overlapping. */
- tmpsrc += count;
- tmpdst += count;
- for (n = count; n > 0; n--)
- *--tmpdst = *--tmpsrc;
- }
- }
-#endif
-
-#if DCHAR_IS_TCHAR && !USE_SNPRINTF
- /* Make room for the result. */
- if (count > allocated - length)
- {
- /* Need at least count elements. But allocate
- proportionally. */
- size_t n =
- xmax (xsum (length, count), xtimes (allocated, 2));
-
- ENSURE_ALLOCATION (n);
- }
-#endif
-
- /* Here count <= allocated - length. */
-
- /* Perform padding. */
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
- if (pad_ourselves && has_width)
- {
- size_t w;
-# if ENABLE_UNISTDIO
- /* Outside POSIX, it's preferable to compare the width
- against the number of _characters_ of the converted
- value. */
- w = DCHAR_MBSNLEN (result + length, count);
-# else
- /* The width is compared against the number of _bytes_
- of the converted value, says POSIX. */
- w = count;
-# endif
- if (w < width)
- {
- size_t pad = width - w;
-
- /* Make room for the result. */
- if (xsum (count, pad) > allocated - length)
- {
- /* Need at least count + pad elements. But
- allocate proportionally. */
- size_t n =
- xmax (xsum3 (length, count, pad),
- xtimes (allocated, 2));
-
-# if USE_SNPRINTF
- length += count;
- ENSURE_ALLOCATION (n);
- length -= count;
-# else
- ENSURE_ALLOCATION (n);
-# endif
- }
- /* Here count + pad <= allocated - length. */
-
- {
-# if !DCHAR_IS_TCHAR || USE_SNPRINTF
- DCHAR_T * const rp = result + length;
-# else
- DCHAR_T * const rp = tmp;
-# endif
- DCHAR_T *p = rp + count;
- DCHAR_T *end = p + pad;
- DCHAR_T *pad_ptr;
-# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
- if (dp->conversion == 'c'
- || dp->conversion == 's')
- /* No zero-padding for string directives. */
- pad_ptr = NULL;
- else
-# endif
- {
- pad_ptr = (*rp == '-' ? rp + 1 : rp);
- /* No zero-padding of "inf" and "nan". */
- if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
- || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
- pad_ptr = NULL;
- }
- /* The generated string now extends from rp to p,
- with the zero padding insertion point being at
- pad_ptr. */
-
- count = count + pad; /* = end - rp */
-
- if (flags & FLAG_LEFT)
- {
- /* Pad with spaces on the right. */
- for (; pad > 0; pad--)
- *p++ = ' ';
- }
- else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
- {
- /* Pad with zeroes. */
- DCHAR_T *q = end;
-
- while (p > pad_ptr)
- *--q = *--p;
- for (; pad > 0; pad--)
- *p++ = '0';
- }
- else
- {
- /* Pad with spaces on the left. */
- DCHAR_T *q = end;
-
- while (p > rp)
- *--q = *--p;
- for (; pad > 0; pad--)
- *p++ = ' ';
- }
- }
- }
- }
-#endif
-
- /* Here still count <= allocated - length. */
-
-#if !DCHAR_IS_TCHAR || USE_SNPRINTF
- /* The snprintf() result did fit. */
-#else
- /* Append the sprintf() result. */
- memcpy (result + length, tmp, count * sizeof (DCHAR_T));
-#endif
-#if !USE_SNPRINTF
- if (tmp != tmpbuf)
- free (tmp);
-#endif
-
-#if NEED_PRINTF_DIRECTIVE_F
- if (dp->conversion == 'F')
- {
- /* Convert the %f result to upper case for %F. */
- DCHAR_T *rp = result + length;
- size_t rc;
- for (rc = count; rc > 0; rc--, rp++)
- if (*rp >= 'a' && *rp <= 'z')
- *rp = *rp - 'a' + 'A';
- }
-#endif
-
- length += count;
- break;
- }
- errno = orig_errno;
-#undef pad_ourselves
-#undef prec_ourselves
- }
- }
- }
-
- /* Add the final NUL. */
- ENSURE_ALLOCATION (xsum (length, 1));
- result[length] = '\0';
-
- if (result != resultbuf && length + 1 < allocated)
- {
- /* Shrink the allocated memory if possible. */
- DCHAR_T *memory;
-
- memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T));
- if (memory != NULL)
- result = memory;
- }
-
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- *lengthp = length;
- /* Note that we can produce a big string of a length > INT_MAX. POSIX
- says that snprintf() fails with errno = EOVERFLOW in this case, but
- that's only because snprintf() returns an 'int'. This function does
- not have this limitation. */
- return result;
-
-#if USE_SNPRINTF
- overflow:
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- CLEANUP ();
- errno = EOVERFLOW;
- return NULL;
-#endif
-
- out_of_memory:
- if (!(result == resultbuf || result == NULL))
- free (result);
- if (buf_malloced != NULL)
- free (buf_malloced);
- out_of_memory_1:
- CLEANUP ();
- errno = ENOMEM;
- return NULL;
- }
-}
-
-#undef MAX_ROOM_NEEDED
-#undef TCHARS_PER_DCHAR
-#undef SNPRINTF
-#undef USE_SNPRINTF
-#undef DCHAR_SET
-#undef DCHAR_CPY
-#undef PRINTF_PARSE
-#undef DIRECTIVES
-#undef DIRECTIVE
-#undef DCHAR_IS_TCHAR
-#undef TCHAR_T
-#undef DCHAR_T
-#undef FCHAR_T
-#undef VASNPRINTF
+++ /dev/null
-/* Compile-time assert-like macros.
-
- Copyright (C) 2005-2006, 2009-2021 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */
-
-#ifndef _GL_VERIFY_H
-#define _GL_VERIFY_H
-
-
-/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert (R, DIAGNOSTIC)
- works as per C11. This is supported by GCC 4.6.0 and later, in C
- mode, and by clang (also in C++ mode).
-
- Define _GL_HAVE__STATIC_ASSERT1 to 1 if _Static_assert (R) works as
- per C2X. This is supported by GCC 9.1 and later, and by clang in
- C++1z mode.
-
- Define _GL_HAVE_STATIC_ASSERT1 if static_assert (R) works as per
- C++17. This is supported by GCC 9.1 and later, and by clang in
- C++1z mode.
-
- Support compilers claiming conformance to the relevant standard,
- and also support GCC when not pedantic. If we were willing to slow
- 'configure' down we could also use it with other compilers, but
- since this affects only the quality of diagnostics, why bother? */
-#ifndef __cplusplus
-# if (201112L <= __STDC_VERSION__ \
- || (!defined __STRICT_ANSI__ \
- && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 4 <= __clang_major__)))
-# define _GL_HAVE__STATIC_ASSERT 1
-# endif
-# if (202000L <= __STDC_VERSION__ \
- || (!defined __STRICT_ANSI__ && 9 <= __GNUC__))
-# define _GL_HAVE__STATIC_ASSERT1 1
-# endif
-#else
-# if 4 <= __clang_major__
-# define _GL_HAVE__STATIC_ASSERT 1
-# endif
-# if 4 <= __clang_major__ && 201411 <= __cpp_static_assert
-# define _GL_HAVE__STATIC_ASSERT1 1
-# endif
-# if 201703L <= __cplusplus \
- || 9 <= __GNUC__ \
- || (4 <= __clang_major__ && 201411 <= __cpp_static_assert)
-# define _GL_HAVE_STATIC_ASSERT1 1
-# endif
-#endif
-
-/* FreeBSD 9.1 <sys/cdefs.h>, included by <stddef.h> and lots of other
- system headers, defines a conflicting _Static_assert that is no
- better than ours; override it. */
-#ifndef _GL_HAVE__STATIC_ASSERT
-# include <stddef.h>
-# undef _Static_assert
-#endif
-
-/* Each of these macros verifies that its argument R is nonzero. To
- be portable, R should be an integer constant expression. Unlike
- assert (R), there is no run-time overhead.
-
- If _Static_assert works, verify (R) uses it directly. Similarly,
- _GL_VERIFY_TRUE works by packaging a _Static_assert inside a struct
- that is an operand of sizeof.
-
- The code below uses several ideas for C++ compilers, and for C
- compilers that do not support _Static_assert:
-
- * The first step is ((R) ? 1 : -1). Given an expression R, of
- integral or boolean or floating-point type, this yields an
- expression of integral type, whose value is later verified to be
- constant and nonnegative.
-
- * Next this expression W is wrapped in a type
- struct _gl_verify_type {
- unsigned int _gl_verify_error_if_negative: W;
- }.
- If W is negative, this yields a compile-time error. No compiler can
- deal with a bit-field of negative size.
-
- One might think that an array size check would have the same
- effect, that is, that the type struct { unsigned int dummy[W]; }
- would work as well. However, inside a function, some compilers
- (such as C++ compilers and GNU C) allow local parameters and
- variables inside array size expressions. With these compilers,
- an array size check would not properly diagnose this misuse of
- the verify macro:
-
- void function (int n) { verify (n < 0); }
-
- * For the verify macro, the struct _gl_verify_type will need to
- somehow be embedded into a declaration. To be portable, this
- declaration must declare an object, a constant, a function, or a
- typedef name. If the declared entity uses the type directly,
- such as in
-
- struct dummy {...};
- typedef struct {...} dummy;
- extern struct {...} *dummy;
- extern void dummy (struct {...} *);
- extern struct {...} *dummy (void);
-
- two uses of the verify macro would yield colliding declarations
- if the entity names are not disambiguated. A workaround is to
- attach the current line number to the entity name:
-
- #define _GL_CONCAT0(x, y) x##y
- #define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y)
- extern struct {...} * _GL_CONCAT (dummy, __LINE__);
-
- But this has the problem that two invocations of verify from
- within the same macro would collide, since the __LINE__ value
- would be the same for both invocations. (The GCC __COUNTER__
- macro solves this problem, but is not portable.)
-
- A solution is to use the sizeof operator. It yields a number,
- getting rid of the identity of the type. Declarations like
-
- extern int dummy [sizeof (struct {...})];
- extern void dummy (int [sizeof (struct {...})]);
- extern int (*dummy (void)) [sizeof (struct {...})];
-
- can be repeated.
-
- * Should the implementation use a named struct or an unnamed struct?
- Which of the following alternatives can be used?
-
- extern int dummy [sizeof (struct {...})];
- extern int dummy [sizeof (struct _gl_verify_type {...})];
- extern void dummy (int [sizeof (struct {...})]);
- extern void dummy (int [sizeof (struct _gl_verify_type {...})]);
- extern int (*dummy (void)) [sizeof (struct {...})];
- extern int (*dummy (void)) [sizeof (struct _gl_verify_type {...})];
-
- In the second and sixth case, the struct type is exported to the
- outer scope; two such declarations therefore collide. GCC warns
- about the first, third, and fourth cases. So the only remaining
- possibility is the fifth case:
-
- extern int (*dummy (void)) [sizeof (struct {...})];
-
- * GCC warns about duplicate declarations of the dummy function if
- -Wredundant-decls is used. GCC 4.3 and later have a builtin
- __COUNTER__ macro that can let us generate unique identifiers for
- each dummy function, to suppress this warning.
-
- * This implementation exploits the fact that older versions of GCC,
- which do not support _Static_assert, also do not warn about the
- last declaration mentioned above.
-
- * GCC warns if -Wnested-externs is enabled and 'verify' is used
- within a function body; but inside a function, you can always
- arrange to use verify_expr instead.
-
- * In C++, any struct definition inside sizeof is invalid.
- Use a template type to work around the problem. */
-
-/* Concatenate two preprocessor tokens. */
-#define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y)
-#define _GL_CONCAT0(x, y) x##y
-
-/* _GL_COUNTER is an integer, preferably one that changes each time we
- use it. Use __COUNTER__ if it works, falling back on __LINE__
- otherwise. __LINE__ isn't perfect, but it's better than a
- constant. */
-#if defined __COUNTER__ && __COUNTER__ != __COUNTER__
-# define _GL_COUNTER __COUNTER__
-#else
-# define _GL_COUNTER __LINE__
-#endif
-
-/* Generate a symbol with the given prefix, making it unique if
- possible. */
-#define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER)
-
-/* Verify requirement R at compile-time, as an integer constant expression
- that returns 1. If R is false, fail at compile-time, preferably
- with a diagnostic that includes the string-literal DIAGNOSTIC. */
-
-#define _GL_VERIFY_TRUE(R, DIAGNOSTIC) \
- (!!sizeof (_GL_VERIFY_TYPE (R, DIAGNOSTIC)))
-
-#ifdef __cplusplus
-# if !GNULIB_defined_struct__gl_verify_type
-template <int w>
- struct _gl_verify_type {
- unsigned int _gl_verify_error_if_negative: w;
- };
-# define GNULIB_defined_struct__gl_verify_type 1
-# endif
-# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \
- _gl_verify_type<(R) ? 1 : -1>
-#elif defined _GL_HAVE__STATIC_ASSERT
-# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \
- struct { \
- _Static_assert (R, DIAGNOSTIC); \
- int _gl_dummy; \
- }
-#else
-# define _GL_VERIFY_TYPE(R, DIAGNOSTIC) \
- struct { unsigned int _gl_verify_error_if_negative: (R) ? 1 : -1; }
-#endif
-
-/* Verify requirement R at compile-time, as a declaration without a
- trailing ';'. If R is false, fail at compile-time.
-
- This macro requires three or more arguments but uses at most the first
- two, so that the _Static_assert macro optionally defined below supports
- both the C11 two-argument syntax and the C2X one-argument syntax.
-
- Unfortunately, unlike C11, this implementation must appear as an
- ordinary declaration, and cannot appear inside struct { ... }. */
-
-#if defined _GL_HAVE__STATIC_ASSERT
-# define _GL_VERIFY(R, DIAGNOSTIC, ...) _Static_assert (R, DIAGNOSTIC)
-#else
-# define _GL_VERIFY(R, DIAGNOSTIC, ...) \
- extern int (*_GL_GENSYM (_gl_verify_function) (void)) \
- [_GL_VERIFY_TRUE (R, DIAGNOSTIC)]
-#endif
-
-/* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h. */
-#ifdef _GL_STATIC_ASSERT_H
-# if !defined _GL_HAVE__STATIC_ASSERT1 && !defined _Static_assert
-# define _Static_assert(...) \
- _GL_VERIFY (__VA_ARGS__, "static assertion failed", -)
-# endif
-# if !defined _GL_HAVE_STATIC_ASSERT1 && !defined static_assert
-# define static_assert _Static_assert /* C11 requires this #define. */
-# endif
-#endif
-
-/* @assert.h omit start@ */
-
-#if 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__))
-# define _GL_HAS_BUILTIN_TRAP 1
-#elif defined __has_builtin
-# define _GL_HAS_BUILTIN_TRAP __has_builtin (__builtin_trap)
-#else
-# define _GL_HAS_BUILTIN_TRAP 0
-#endif
-
-#if 4 < __GNUC__ + (5 <= __GNUC_MINOR__)
-# define _GL_HAS_BUILTIN_UNREACHABLE 1
-#elif defined __has_builtin
-# define _GL_HAS_BUILTIN_UNREACHABLE __has_builtin (__builtin_unreachable)
-#else
-# define _GL_HAS_BUILTIN_UNREACHABLE 0
-#endif
-
-/* Each of these macros verifies that its argument R is nonzero. To
- be portable, R should be an integer constant expression. Unlike
- assert (R), there is no run-time overhead.
-
- There are two macros, since no single macro can be used in all
- contexts in C. verify_expr (R, E) is for scalar contexts, including
- integer constant expression contexts. verify (R) is for declaration
- contexts, e.g., the top level. */
-
-/* Verify requirement R at compile-time. Return the value of the
- expression E. */
-
-#define verify_expr(R, E) \
- (_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E))
-
-/* Verify requirement R at compile-time, as a declaration without a
- trailing ';'. verify (R) acts like static_assert (R) except that
- it is portable to C11/C++14 and earlier, it can issue better
- diagnostics, and its name is shorter and may be more convenient. */
-
-#ifdef __PGI
-/* PGI barfs if R is long. */
-# define verify(R) _GL_VERIFY (R, "verify (...)", -)
-#else
-# define verify(R) _GL_VERIFY (R, "verify (" #R ")", -)
-#endif
-
-/* Assume that R always holds. Behavior is undefined if R is false,
- fails to evaluate, or has side effects.
-
- 'assume (R)' is a directive from the programmer telling the
- compiler that R is true so the compiler needn't generate code to
- test R. This is why 'assume' is in verify.h: it's related to
- static checking (in this case, static checking done by the
- programmer), not dynamic checking.
-
- 'assume (R)' can affect compilation of all the code, not just code
- that happens to be executed after the assume (R) is "executed".
- For example, if the code mistakenly does 'assert (R); assume (R);'
- the compiler is entitled to optimize away the 'assert (R)'.
-
- Although assuming R can help a compiler generate better code or
- diagnostics, performance can suffer if R uses hard-to-optimize
- features such as function calls not inlined by the compiler.
-
- Avoid Clang's __builtin_assume, as it breaks GNU Emacs master
- as of 2020-08-23T21:09:49Z!eggert@cs.ucla.edu; see
- <https://bugs.gnu.org/43152#71>. It's not known whether this breakage
- is a Clang bug or an Emacs bug; play it safe for now. */
-
-#if _GL_HAS_BUILTIN_UNREACHABLE
-# define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())
-#elif 1200 <= _MSC_VER
-# define assume(R) __assume (R)
-#elif (defined GCC_LINT || defined lint) && _GL_HAS_BUILTIN_TRAP
- /* Doing it this way helps various packages when configured with
- --enable-gcc-warnings, which compiles with -Dlint. It's nicer
- when 'assume' silences warnings even with older GCCs. */
-# define assume(R) ((R) ? (void) 0 : __builtin_trap ())
-#else
- /* Some tools grok NOTREACHED, e.g., Oracle Studio 12.6. */
-# define assume(R) ((R) ? (void) 0 : /*NOTREACHED*/ (void) 0)
-#endif
-
-/* @assert.h omit end@ */
-
-#endif
+++ /dev/null
-/* Init guards, somewhat like spinlocks (native Windows implementation).
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-win32.h. */
-
-#ifndef _WINDOWS_INITGUARD_H
-#define _WINDOWS_INITGUARD_H
-
-#define WIN32_LEAN_AND_MEAN /* avoid including junk */
-#include <windows.h>
-
-typedef struct
- {
- volatile int done;
- volatile LONG started;
- }
- glwthread_initguard_t;
-
-#define GLWTHREAD_INITGUARD_INIT { 0, -1 }
-
-#endif /* _WINDOWS_INITGUARD_H */
+++ /dev/null
-/* Plain mutexes (native Windows implementation).
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-win32.h. */
-
-#include <config.h>
-
-/* Specification. */
-#include "windows-mutex.h"
-
-#include <errno.h>
-
-void
-glwthread_mutex_init (glwthread_mutex_t *mutex)
-{
- InitializeCriticalSection (&mutex->lock);
- mutex->guard.done = 1;
-}
-
-int
-glwthread_mutex_lock (glwthread_mutex_t *mutex)
-{
- if (!mutex->guard.done)
- {
- if (InterlockedIncrement (&mutex->guard.started) == 0)
- /* This thread is the first one to need this mutex. Initialize it. */
- glwthread_mutex_init (mutex);
- else
- {
- /* Don't let mutex->guard.started grow and wrap around. */
- InterlockedDecrement (&mutex->guard.started);
- /* Yield the CPU while waiting for another thread to finish
- initializing this mutex. */
- while (!mutex->guard.done)
- Sleep (0);
- }
- }
- EnterCriticalSection (&mutex->lock);
- return 0;
-}
-
-int
-glwthread_mutex_trylock (glwthread_mutex_t *mutex)
-{
- if (!mutex->guard.done)
- {
- if (InterlockedIncrement (&mutex->guard.started) == 0)
- /* This thread is the first one to need this mutex. Initialize it. */
- glwthread_mutex_init (mutex);
- else
- {
- /* Don't let mutex->guard.started grow and wrap around. */
- InterlockedDecrement (&mutex->guard.started);
- /* Let another thread finish initializing this mutex, and let it also
- lock this mutex. */
- return EBUSY;
- }
- }
- if (!TryEnterCriticalSection (&mutex->lock))
- return EBUSY;
- return 0;
-}
-
-int
-glwthread_mutex_unlock (glwthread_mutex_t *mutex)
-{
- if (!mutex->guard.done)
- return EINVAL;
- LeaveCriticalSection (&mutex->lock);
- return 0;
-}
-
-int
-glwthread_mutex_destroy (glwthread_mutex_t *mutex)
-{
- if (!mutex->guard.done)
- return EINVAL;
- DeleteCriticalSection (&mutex->lock);
- mutex->guard.done = 0;
- return 0;
-}
+++ /dev/null
-/* Plain mutexes (native Windows implementation).
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-win32.h. */
-
-#ifndef _WINDOWS_MUTEX_H
-#define _WINDOWS_MUTEX_H
-
-#define WIN32_LEAN_AND_MEAN /* avoid including junk */
-#include <windows.h>
-
-#include "windows-initguard.h"
-
-typedef struct
- {
- glwthread_initguard_t guard; /* protects the initialization */
- CRITICAL_SECTION lock;
- }
- glwthread_mutex_t;
-
-#define GLWTHREAD_MUTEX_INIT { GLWTHREAD_INITGUARD_INIT }
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void glwthread_mutex_init (glwthread_mutex_t *mutex);
-extern int glwthread_mutex_lock (glwthread_mutex_t *mutex);
-extern int glwthread_mutex_trylock (glwthread_mutex_t *mutex);
-extern int glwthread_mutex_unlock (glwthread_mutex_t *mutex);
-extern int glwthread_mutex_destroy (glwthread_mutex_t *mutex);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _WINDOWS_MUTEX_H */
+++ /dev/null
-/* Once-only control (native Windows implementation).
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-win32.h. */
-
-#include <config.h>
-
-/* Specification. */
-#include "windows-once.h"
-
-#include <stdlib.h>
-
-void
-glwthread_once (glwthread_once_t *once_control, void (*initfunction) (void))
-{
- if (once_control->inited <= 0)
- {
- if (InterlockedIncrement (&once_control->started) == 0)
- {
- /* This thread is the first one to come to this once_control. */
- InitializeCriticalSection (&once_control->lock);
- EnterCriticalSection (&once_control->lock);
- once_control->inited = 0;
- initfunction ();
- once_control->inited = 1;
- LeaveCriticalSection (&once_control->lock);
- }
- else
- {
- /* Don't let once_control->started grow and wrap around. */
- InterlockedDecrement (&once_control->started);
- /* Some other thread has already started the initialization.
- Yield the CPU while waiting for the other thread to finish
- initializing and taking the lock. */
- while (once_control->inited < 0)
- Sleep (0);
- if (once_control->inited <= 0)
- {
- /* Take the lock. This blocks until the other thread has
- finished calling the initfunction. */
- EnterCriticalSection (&once_control->lock);
- LeaveCriticalSection (&once_control->lock);
- if (!(once_control->inited > 0))
- abort ();
- }
- }
- }
-}
+++ /dev/null
-/* Once-only control (native Windows implementation).
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-win32.h. */
-
-#ifndef _WINDOWS_ONCE_H
-#define _WINDOWS_ONCE_H
-
-#define WIN32_LEAN_AND_MEAN /* avoid including junk */
-#include <windows.h>
-
-typedef struct
- {
- volatile int inited;
- volatile LONG started;
- CRITICAL_SECTION lock;
- }
- glwthread_once_t;
-
-#define GLWTHREAD_ONCE_INIT { -1, -1 }
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void glwthread_once (glwthread_once_t *once_control,
- void (*initfunction) (void));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _WINDOWS_ONCE_H */
+++ /dev/null
-/* Plain recursive mutexes (native Windows implementation).
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-win32.h. */
-
-#include <config.h>
-
-/* Specification. */
-#include "windows-recmutex.h"
-
-#include <errno.h>
-
-void
-glwthread_recmutex_init (glwthread_recmutex_t *mutex)
-{
- mutex->owner = 0;
- mutex->depth = 0;
- InitializeCriticalSection (&mutex->lock);
- mutex->guard.done = 1;
-}
-
-int
-glwthread_recmutex_lock (glwthread_recmutex_t *mutex)
-{
- if (!mutex->guard.done)
- {
- if (InterlockedIncrement (&mutex->guard.started) == 0)
- /* This thread is the first one to need this mutex. Initialize it. */
- glwthread_recmutex_init (mutex);
- else
- {
- /* Don't let mutex->guard.started grow and wrap around. */
- InterlockedDecrement (&mutex->guard.started);
- /* Yield the CPU while waiting for another thread to finish
- initializing this mutex. */
- while (!mutex->guard.done)
- Sleep (0);
- }
- }
- {
- DWORD self = GetCurrentThreadId ();
- if (mutex->owner != self)
- {
- EnterCriticalSection (&mutex->lock);
- mutex->owner = self;
- }
- if (++(mutex->depth) == 0) /* wraparound? */
- {
- mutex->depth--;
- return EAGAIN;
- }
- }
- return 0;
-}
-
-int
-glwthread_recmutex_trylock (glwthread_recmutex_t *mutex)
-{
- if (!mutex->guard.done)
- {
- if (InterlockedIncrement (&mutex->guard.started) == 0)
- /* This thread is the first one to need this mutex. Initialize it. */
- glwthread_recmutex_init (mutex);
- else
- {
- /* Don't let mutex->guard.started grow and wrap around. */
- InterlockedDecrement (&mutex->guard.started);
- /* Let another thread finish initializing this mutex, and let it also
- lock this mutex. */
- return EBUSY;
- }
- }
- {
- DWORD self = GetCurrentThreadId ();
- if (mutex->owner != self)
- {
- if (!TryEnterCriticalSection (&mutex->lock))
- return EBUSY;
- mutex->owner = self;
- }
- if (++(mutex->depth) == 0) /* wraparound? */
- {
- mutex->depth--;
- return EAGAIN;
- }
- }
- return 0;
-}
-
-int
-glwthread_recmutex_unlock (glwthread_recmutex_t *mutex)
-{
- if (mutex->owner != GetCurrentThreadId ())
- return EPERM;
- if (mutex->depth == 0)
- return EINVAL;
- if (--(mutex->depth) == 0)
- {
- mutex->owner = 0;
- LeaveCriticalSection (&mutex->lock);
- }
- return 0;
-}
-
-int
-glwthread_recmutex_destroy (glwthread_recmutex_t *mutex)
-{
- if (mutex->owner != 0)
- return EBUSY;
- DeleteCriticalSection (&mutex->lock);
- mutex->guard.done = 0;
- return 0;
-}
+++ /dev/null
-/* Plain recursive mutexes (native Windows implementation).
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-win32.h. */
-
-#ifndef _WINDOWS_RECMUTEX_H
-#define _WINDOWS_RECMUTEX_H
-
-#define WIN32_LEAN_AND_MEAN /* avoid including junk */
-#include <windows.h>
-
-#include "windows-initguard.h"
-
-/* The native Windows documentation says that CRITICAL_SECTION already
- implements a recursive lock. But we need not rely on it: It's easy to
- implement a recursive lock without this assumption. */
-
-typedef struct
- {
- glwthread_initguard_t guard; /* protects the initialization */
- DWORD owner;
- unsigned long depth;
- CRITICAL_SECTION lock;
- }
- glwthread_recmutex_t;
-
-#define GLWTHREAD_RECMUTEX_INIT { GLWTHREAD_INITGUARD_INIT, 0, 0 }
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void glwthread_recmutex_init (glwthread_recmutex_t *mutex);
-extern int glwthread_recmutex_lock (glwthread_recmutex_t *mutex);
-extern int glwthread_recmutex_trylock (glwthread_recmutex_t *mutex);
-extern int glwthread_recmutex_unlock (glwthread_recmutex_t *mutex);
-extern int glwthread_recmutex_destroy (glwthread_recmutex_t *mutex);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _WINDOWS_RECMUTEX_H */
+++ /dev/null
-/* Read-write locks (native Windows implementation).
- Copyright (C) 2005-2020 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-win32.h. */
-
-#include <config.h>
-
-/* Specification. */
-#include "windows-rwlock.h"
-
-#include <errno.h>
-#include <stdlib.h>
-
-/* Don't assume that UNICODE is not defined. */
-#undef CreateEvent
-#define CreateEvent CreateEventA
-
-/* In this file, the waitqueues are implemented as circular arrays. */
-#define glwthread_waitqueue_t glwthread_carray_waitqueue_t
-
-static void
-glwthread_waitqueue_init (glwthread_waitqueue_t *wq)
-{
- wq->array = NULL;
- wq->count = 0;
- wq->alloc = 0;
- wq->offset = 0;
-}
-
-/* Enqueues the current thread, represented by an event, in a wait queue.
- Returns INVALID_HANDLE_VALUE if an allocation failure occurs. */
-static HANDLE
-glwthread_waitqueue_add (glwthread_waitqueue_t *wq)
-{
- HANDLE event;
- unsigned int index;
-
- if (wq->count == wq->alloc)
- {
- unsigned int new_alloc = 2 * wq->alloc + 1;
- HANDLE *new_array =
- (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));
- if (new_array == NULL)
- /* No more memory. */
- return INVALID_HANDLE_VALUE;
- /* Now is a good opportunity to rotate the array so that its contents
- starts at offset 0. */
- if (wq->offset > 0)
- {
- unsigned int old_count = wq->count;
- unsigned int old_alloc = wq->alloc;
- unsigned int old_offset = wq->offset;
- unsigned int i;
- if (old_offset + old_count > old_alloc)
- {
- unsigned int limit = old_offset + old_count - old_alloc;
- for (i = 0; i < limit; i++)
- new_array[old_alloc + i] = new_array[i];
- }
- for (i = 0; i < old_count; i++)
- new_array[i] = new_array[old_offset + i];
- wq->offset = 0;
- }
- wq->array = new_array;
- wq->alloc = new_alloc;
- }
- /* Whether the created event is a manual-reset one or an auto-reset one,
- does not matter, since we will wait on it only once. */
- event = CreateEvent (NULL, TRUE, FALSE, NULL);
- if (event == INVALID_HANDLE_VALUE)
- /* No way to allocate an event. */
- return INVALID_HANDLE_VALUE;
- index = wq->offset + wq->count;
- if (index >= wq->alloc)
- index -= wq->alloc;
- wq->array[index] = event;
- wq->count++;
- return event;
-}
-
-/* Notifies the first thread from a wait queue and dequeues it. */
-static void
-glwthread_waitqueue_notify_first (glwthread_waitqueue_t *wq)
-{
- SetEvent (wq->array[wq->offset + 0]);
- wq->offset++;
- wq->count--;
- if (wq->count == 0 || wq->offset == wq->alloc)
- wq->offset = 0;
-}
-
-/* Notifies all threads from a wait queue and dequeues them all. */
-static void
-glwthread_waitqueue_notify_all (glwthread_waitqueue_t *wq)
-{
- unsigned int i;
-
- for (i = 0; i < wq->count; i++)
- {
- unsigned int index = wq->offset + i;
- if (index >= wq->alloc)
- index -= wq->alloc;
- SetEvent (wq->array[index]);
- }
- wq->count = 0;
- wq->offset = 0;
-}
-
-void
-glwthread_rwlock_init (glwthread_rwlock_t *lock)
-{
- InitializeCriticalSection (&lock->lock);
- glwthread_waitqueue_init (&lock->waiting_readers);
- glwthread_waitqueue_init (&lock->waiting_writers);
- lock->runcount = 0;
- lock->guard.done = 1;
-}
-
-int
-glwthread_rwlock_rdlock (glwthread_rwlock_t *lock)
-{
- if (!lock->guard.done)
- {
- if (InterlockedIncrement (&lock->guard.started) == 0)
- /* This thread is the first one to need this lock. Initialize it. */
- glwthread_rwlock_init (lock);
- else
- {
- /* Don't let lock->guard.started grow and wrap around. */
- InterlockedDecrement (&lock->guard.started);
- /* Yield the CPU while waiting for another thread to finish
- initializing this lock. */
- while (!lock->guard.done)
- Sleep (0);
- }
- }
- EnterCriticalSection (&lock->lock);
- /* Test whether only readers are currently running, and whether the runcount
- field will not overflow, and whether no writer is waiting. The latter
- condition is because POSIX recommends that "write locks shall take
- precedence over read locks", to avoid "writer starvation". */
- if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0))
- {
- /* This thread has to wait for a while. Enqueue it among the
- waiting_readers. */
- HANDLE event = glwthread_waitqueue_add (&lock->waiting_readers);
- if (event != INVALID_HANDLE_VALUE)
- {
- DWORD result;
- LeaveCriticalSection (&lock->lock);
- /* Wait until another thread signals this event. */
- result = WaitForSingleObject (event, INFINITE);
- if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
- abort ();
- CloseHandle (event);
- /* The thread which signalled the event already did the bookkeeping:
- removed us from the waiting_readers, incremented lock->runcount. */
- if (!(lock->runcount > 0))
- abort ();
- return 0;
- }
- else
- {
- /* Allocation failure. Weird. */
- do
- {
- LeaveCriticalSection (&lock->lock);
- Sleep (1);
- EnterCriticalSection (&lock->lock);
- }
- while (!(lock->runcount + 1 > 0));
- }
- }
- lock->runcount++;
- LeaveCriticalSection (&lock->lock);
- return 0;
-}
-
-int
-glwthread_rwlock_wrlock (glwthread_rwlock_t *lock)
-{
- if (!lock->guard.done)
- {
- if (InterlockedIncrement (&lock->guard.started) == 0)
- /* This thread is the first one to need this lock. Initialize it. */
- glwthread_rwlock_init (lock);
- else
- {
- /* Don't let lock->guard.started grow and wrap around. */
- InterlockedDecrement (&lock->guard.started);
- /* Yield the CPU while waiting for another thread to finish
- initializing this lock. */
- while (!lock->guard.done)
- Sleep (0);
- }
- }
- EnterCriticalSection (&lock->lock);
- /* Test whether no readers or writers are currently running. */
- if (!(lock->runcount == 0))
- {
- /* This thread has to wait for a while. Enqueue it among the
- waiting_writers. */
- HANDLE event = glwthread_waitqueue_add (&lock->waiting_writers);
- if (event != INVALID_HANDLE_VALUE)
- {
- DWORD result;
- LeaveCriticalSection (&lock->lock);
- /* Wait until another thread signals this event. */
- result = WaitForSingleObject (event, INFINITE);
- if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
- abort ();
- CloseHandle (event);
- /* The thread which signalled the event already did the bookkeeping:
- removed us from the waiting_writers, set lock->runcount = -1. */
- if (!(lock->runcount == -1))
- abort ();
- return 0;
- }
- else
- {
- /* Allocation failure. Weird. */
- do
- {
- LeaveCriticalSection (&lock->lock);
- Sleep (1);
- EnterCriticalSection (&lock->lock);
- }
- while (!(lock->runcount == 0));
- }
- }
- lock->runcount--; /* runcount becomes -1 */
- LeaveCriticalSection (&lock->lock);
- return 0;
-}
-
-int
-glwthread_rwlock_tryrdlock (glwthread_rwlock_t *lock)
-{
- if (!lock->guard.done)
- {
- if (InterlockedIncrement (&lock->guard.started) == 0)
- /* This thread is the first one to need this lock. Initialize it. */
- glwthread_rwlock_init (lock);
- else
- {
- /* Don't let lock->guard.started grow and wrap around. */
- InterlockedDecrement (&lock->guard.started);
- /* Yield the CPU while waiting for another thread to finish
- initializing this lock. */
- while (!lock->guard.done)
- Sleep (0);
- }
- }
- /* It's OK to wait for this critical section, because it is never taken for a
- long time. */
- EnterCriticalSection (&lock->lock);
- /* Test whether only readers are currently running, and whether the runcount
- field will not overflow, and whether no writer is waiting. The latter
- condition is because POSIX recommends that "write locks shall take
- precedence over read locks", to avoid "writer starvation". */
- if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0))
- {
- /* This thread would have to wait for a while. Return instead. */
- LeaveCriticalSection (&lock->lock);
- return EBUSY;
- }
- lock->runcount++;
- LeaveCriticalSection (&lock->lock);
- return 0;
-}
-
-int
-glwthread_rwlock_trywrlock (glwthread_rwlock_t *lock)
-{
- if (!lock->guard.done)
- {
- if (InterlockedIncrement (&lock->guard.started) == 0)
- /* This thread is the first one to need this lock. Initialize it. */
- glwthread_rwlock_init (lock);
- else
- {
- /* Don't let lock->guard.started grow and wrap around. */
- InterlockedDecrement (&lock->guard.started);
- /* Yield the CPU while waiting for another thread to finish
- initializing this lock. */
- while (!lock->guard.done)
- Sleep (0);
- }
- }
- /* It's OK to wait for this critical section, because it is never taken for a
- long time. */
- EnterCriticalSection (&lock->lock);
- /* Test whether no readers or writers are currently running. */
- if (!(lock->runcount == 0))
- {
- /* This thread would have to wait for a while. Return instead. */
- LeaveCriticalSection (&lock->lock);
- return EBUSY;
- }
- lock->runcount--; /* runcount becomes -1 */
- LeaveCriticalSection (&lock->lock);
- return 0;
-}
-
-int
-glwthread_rwlock_unlock (glwthread_rwlock_t *lock)
-{
- if (!lock->guard.done)
- return EINVAL;
- EnterCriticalSection (&lock->lock);
- if (lock->runcount < 0)
- {
- /* Drop a writer lock. */
- if (!(lock->runcount == -1))
- abort ();
- lock->runcount = 0;
- }
- else
- {
- /* Drop a reader lock. */
- if (!(lock->runcount > 0))
- {
- LeaveCriticalSection (&lock->lock);
- return EPERM;
- }
- lock->runcount--;
- }
- if (lock->runcount == 0)
- {
- /* POSIX recommends that "write locks shall take precedence over read
- locks", to avoid "writer starvation". */
- if (lock->waiting_writers.count > 0)
- {
- /* Wake up one of the waiting writers. */
- lock->runcount--;
- glwthread_waitqueue_notify_first (&lock->waiting_writers);
- }
- else
- {
- /* Wake up all waiting readers. */
- lock->runcount += lock->waiting_readers.count;
- glwthread_waitqueue_notify_all (&lock->waiting_readers);
- }
- }
- LeaveCriticalSection (&lock->lock);
- return 0;
-}
-
-int
-glwthread_rwlock_destroy (glwthread_rwlock_t *lock)
-{
- if (!lock->guard.done)
- return EINVAL;
- if (lock->runcount != 0)
- return EBUSY;
- DeleteCriticalSection (&lock->lock);
- if (lock->waiting_readers.array != NULL)
- free (lock->waiting_readers.array);
- if (lock->waiting_writers.array != NULL)
- free (lock->waiting_writers.array);
- lock->guard.done = 0;
- return 0;
-}
+++ /dev/null
-/* Read-write locks (native Windows implementation).
- Copyright (C) 2005-2019 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-win32.h. */
-
-#ifndef _WINDOWS_RWLOCK_H
-#define _WINDOWS_RWLOCK_H
-
-#define WIN32_LEAN_AND_MEAN /* avoid including junk */
-#include <windows.h>
-
-#include "windows-initguard.h"
-
-/* It is impossible to implement read-write locks using plain locks, without
- introducing an extra thread dedicated to managing read-write locks.
- Therefore here we need to use the low-level Event type. */
-
-typedef struct
- {
- HANDLE *array; /* array of waiting threads, each represented by an event */
- unsigned int count; /* number of waiting threads */
- unsigned int alloc; /* length of allocated array */
- unsigned int offset; /* index of first waiting thread in array */
- }
- glwthread_carray_waitqueue_t;
-typedef struct
- {
- glwthread_initguard_t guard; /* protects the initialization */
- CRITICAL_SECTION lock; /* protects the remaining fields */
- glwthread_carray_waitqueue_t waiting_readers; /* waiting readers */
- glwthread_carray_waitqueue_t waiting_writers; /* waiting writers */
- int runcount; /* number of readers running, or -1 when a writer runs */
- }
- glwthread_rwlock_t;
-
-#define GLWTHREAD_RWLOCK_INIT { GLWTHREAD_INITGUARD_INIT }
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void glwthread_rwlock_init (glwthread_rwlock_t *lock);
-extern int glwthread_rwlock_rdlock (glwthread_rwlock_t *lock);
-extern int glwthread_rwlock_wrlock (glwthread_rwlock_t *lock);
-extern int glwthread_rwlock_tryrdlock (glwthread_rwlock_t *lock);
-extern int glwthread_rwlock_trywrlock (glwthread_rwlock_t *lock);
-extern int glwthread_rwlock_unlock (glwthread_rwlock_t *lock);
-extern int glwthread_rwlock_destroy (glwthread_rwlock_t *lock);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _WINDOWS_RWLOCK_H */
+++ /dev/null
-#include <config.h>
-#define XSIZE_INLINE _GL_EXTERN_INLINE
-#include "xsize.h"
+++ /dev/null
-/* xsize.h -- Checked size_t computations.
-
- Copyright (C) 2003, 2008-2021 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program; if not, see <https://www.gnu.org/licenses/>. */
-
-#ifndef _XSIZE_H
-#define _XSIZE_H
-
-/* Get size_t. */
-#include <stddef.h>
-
-/* Get SIZE_MAX. */
-#include <limits.h>
-#if HAVE_STDINT_H
-# include <stdint.h>
-#endif
-
-/* Get ATTRIBUTE_PURE. */
-#include "attribute.h"
-
-#ifndef _GL_INLINE_HEADER_BEGIN
- #error "Please include config.h first."
-#endif
-_GL_INLINE_HEADER_BEGIN
-#ifndef XSIZE_INLINE
-# define XSIZE_INLINE _GL_INLINE
-#endif
-
-/* The size of memory objects is often computed through expressions of
- type size_t. Example:
- void* p = malloc (header_size + n * element_size).
- These computations can lead to overflow. When this happens, malloc()
- returns a piece of memory that is way too small, and the program then
- crashes while attempting to fill the memory.
- To avoid this, the functions and macros in this file check for overflow.
- The convention is that SIZE_MAX represents overflow.
- malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
- implementation that uses mmap --, it's recommended to use size_overflow_p()
- or size_in_bounds_p() before invoking malloc().
- The example thus becomes:
- size_t size = xsum (header_size, xtimes (n, element_size));
- void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
-*/
-
-/* Convert an arbitrary value >= 0 to type size_t. */
-#define xcast_size_t(N) \
- ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
-
-/* Sum of two sizes, with overflow check. */
-XSIZE_INLINE size_t ATTRIBUTE_PURE
-xsum (size_t size1, size_t size2)
-{
- size_t sum = size1 + size2;
- return (sum >= size1 ? sum : SIZE_MAX);
-}
-
-/* Sum of three sizes, with overflow check. */
-XSIZE_INLINE size_t ATTRIBUTE_PURE
-xsum3 (size_t size1, size_t size2, size_t size3)
-{
- return xsum (xsum (size1, size2), size3);
-}
-
-/* Sum of four sizes, with overflow check. */
-XSIZE_INLINE size_t ATTRIBUTE_PURE
-xsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
-{
- return xsum (xsum (xsum (size1, size2), size3), size4);
-}
-
-/* Maximum of two sizes, with overflow check. */
-XSIZE_INLINE size_t ATTRIBUTE_PURE
-xmax (size_t size1, size_t size2)
-{
- /* No explicit check is needed here, because for any n:
- max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */
- return (size1 >= size2 ? size1 : size2);
-}
-
-/* Multiplication of a count with an element size, with overflow check.
- The count must be >= 0 and the element size must be > 0.
- This is a macro, not a function, so that it works correctly even
- when N is of a wider type and N > SIZE_MAX. */
-#define xtimes(N, ELSIZE) \
- ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)
-
-/* Check for overflow. */
-#define size_overflow_p(SIZE) \
- ((SIZE) == SIZE_MAX)
-/* Check against overflow. */
-#define size_in_bounds_p(SIZE) \
- ((SIZE) != SIZE_MAX)
-
-_GL_INLINE_HEADER_END
-
-#endif /* _XSIZE_H */
-# intl.m4 serial 48 (gettext-0.21.1)
+# intl.m4 serial 49 (gettext-0.21.1)
dnl Copyright (C) 1995-2014, 2016-2021 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl Check for a program that compiles Windows resource files.
AC_CHECK_TOOL([WINDRES], [windres])
fi
-
- dnl Rename some macros and functions used for locking.
- AH_BOTTOM([
-#define __libc_lock_t gl_lock_t
-#define __libc_lock_define gl_lock_define
-#define __libc_lock_define_initialized gl_lock_define_initialized
-#define __libc_lock_init gl_lock_init
-#define __libc_lock_lock gl_lock_lock
-#define __libc_lock_unlock gl_lock_unlock
-#define __libc_lock_recursive_t gl_recursive_lock_t
-#define __libc_lock_define_recursive gl_recursive_lock_define
-#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized
-#define __libc_lock_init_recursive gl_recursive_lock_init
-#define __libc_lock_lock_recursive gl_recursive_lock_lock
-#define __libc_lock_unlock_recursive gl_recursive_lock_unlock
-#define glthread_in_use libintl_thread_in_use
-#define glthread_lock_init_func libintl_lock_init_func
-#define glthread_lock_lock_func libintl_lock_lock_func
-#define glthread_lock_unlock_func libintl_lock_unlock_func
-#define glthread_lock_destroy_func libintl_lock_destroy_func
-#define glthread_rwlock_init_multithreaded libintl_rwlock_init_multithreaded
-#define glthread_rwlock_init_func libintl_rwlock_init_func
-#define glthread_rwlock_rdlock_multithreaded libintl_rwlock_rdlock_multithreaded
-#define glthread_rwlock_rdlock_func libintl_rwlock_rdlock_func
-#define glthread_rwlock_wrlock_multithreaded libintl_rwlock_wrlock_multithreaded
-#define glthread_rwlock_wrlock_func libintl_rwlock_wrlock_func
-#define glthread_rwlock_unlock_multithreaded libintl_rwlock_unlock_multithreaded
-#define glthread_rwlock_unlock_func libintl_rwlock_unlock_func
-#define glthread_rwlock_destroy_multithreaded libintl_rwlock_destroy_multithreaded
-#define glthread_rwlock_destroy_func libintl_rwlock_destroy_func
-#define glthread_recursive_lock_init_multithreaded libintl_recursive_lock_init_multithreaded
-#define glthread_recursive_lock_init_func libintl_recursive_lock_init_func
-#define glthread_recursive_lock_lock_multithreaded libintl_recursive_lock_lock_multithreaded
-#define glthread_recursive_lock_lock_func libintl_recursive_lock_lock_func
-#define glthread_recursive_lock_unlock_multithreaded libintl_recursive_lock_unlock_multithreaded
-#define glthread_recursive_lock_unlock_func libintl_recursive_lock_unlock_func
-#define glthread_recursive_lock_destroy_multithreaded libintl_recursive_lock_destroy_multithreaded
-#define glthread_recursive_lock_destroy_func libintl_recursive_lock_destroy_func
-#define glthread_once_func libintl_once_func
-#define glthread_once_singlethreaded libintl_once_singlethreaded
-#define glthread_once_multithreaded libintl_once_multithreaded
-])
])
AC_CHECK_HEADERS([inttypes.h limits.h unistd.h sys/param.h])
AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \
- stpcpy strcasecmp strdup strtoul tsearch __fsetlocking])
+ stpcpy strcasecmp strdup strtoul __fsetlocking])
dnl Use the *_unlocked functions only if they are declared.
dnl (because some of them were defined without being declared in Solaris
lib/libxml/xpathInternals.in.h \
lib/libxml/xpointer.c \
lib/libxml/xpointer.in.h \
+lib/localename.c.diff \
+lib/localename-table.h.diff \
lib/markup.c \
lib/markup.h \
lib/mem-hash-map.c \
lib/progname.h.diff \
lib/regex_internal.h.diff \
lib/unistd.in.h.diff \
+lib/tsearch.c.diff \
lib/xerror.c \
lib/xerror.h \
lib/xgetcwd.c \
modules/backupfile \
modules/closeout \
modules/error-progname \
+modules/gettext-runtime-intl-misc \
modules/gettext-runtime-misc \
modules/gettext-tools-misc \
modules/java \
modules/libxml \
modules/markup \
modules/mem-hash-map \
+modules/tsearch.diff \
modules/xerror \
modules/xgetcwd
--- /dev/null
+diff --git a/lib/localename-table.h b/lib/localename-table.h
+index f365b24..98f5b9f 100644
+--- a/lib/localename-table.h
++++ b/lib/localename-table.h
+@@ -21,11 +21,7 @@
+ # include <stddef.h>
+ # include <locale.h>
+
+-# ifdef IN_LIBINTL
+-# include "lock.h"
+-# else
+-# include "glthread/lock.h"
+-# endif
++# include "glthread/lock.h"
+
+ struct locale_categories_names
+ {
--- /dev/null
+--- localename.c.orig 2021-06-14 15:51:56.574445150 +0200
++++ localename.c 2021-06-14 15:55:23.703421518 +0200
+@@ -21,11 +21,7 @@
+ #include <config.h>
+
+ /* Specification. */
+-#ifdef IN_LIBINTL
+-# include "gettextP.h"
+-#else
+-# include "localename.h"
+-#endif
++#include "localename.h"
+
+ #include <limits.h>
+ #include <stdbool.h>
+@@ -46,9 +42,7 @@
+ # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGINFO_H) || defined __CYGWIN__
+ # include <langinfo.h>
+ # endif
+-# if !defined IN_LIBINTL
+-# include "glthread/lock.h"
+-# endif
++# include "glthread/lock.h"
+ # if defined __sun
+ # if HAVE_GETLOCALENAME_L
+ /* Solaris >= 12. */
+@@ -70,9 +64,7 @@
+
+ #if defined _WIN32 && !defined __CYGWIN__
+ # define WINDOWS_NATIVE
+-# if !defined IN_LIBINTL
+-# include "glthread/lock.h"
+-# endif
++# include "glthread/lock.h"
+ #endif
+
+ #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
--- /dev/null
+diff --git a/lib/tsearch.c b/lib/tsearch.c
+index 2b775b1..dcc16d7 100644
+--- a/lib/tsearch.c
++++ b/lib/tsearch.c
+@@ -92,11 +92,7 @@
+ #include <config.h>
+
+ /* Specification. */
+-#ifdef IN_LIBINTL
+-# include "tsearch.h"
+-#else
+-# include <search.h>
+-#endif
++#include <search.h>
+
+ #include <stdlib.h>
+
--- /dev/null
+Description:
+
+Files:
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+# Parameterization of the 'relocatable-lib-lgpl' module.
+AM_CPPFLAGS += \
+ -DIN_LIBRARY -DINSTALLDIR=\"$(libdir)\" -DNO_XMALLOC -DBUILDING_DLL \
+ -Dset_relocation_prefix=libintl_set_relocation_prefix \
+ -DDEPENDS_ON_LIBICONV=1
+
+Include:
+
+License:
+LGPLv2+
+
+Maintainer:
+Bruno Haible
--- /dev/null
+diff --git a/modules/tsearch b/modules/tsearch
+index 4a2b5ed..6ffdf2f 100644
+--- a/modules/tsearch
++++ b/modules/tsearch
+@@ -22,7 +22,7 @@ Include:
+ <search.h>
+
+ License:
+-LGPL
++LGPLv2+
+
+ Maintainer:
+ all, glibc