From: Bruno Haible Date: Sun, 20 Jun 2021 01:43:17 +0000 (+0200) Subject: build: Simplify the use of gnulib in libintl. X-Git-Tag: v0.22~246 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a80b9021019fe311b81771d67138496f512ef35a;p=thirdparty%2Fgettext.git build: Simplify the use of gnulib in libintl. * 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 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 , localename.h. (gl_locale_name_canonicalize): New declaration. * Makefile.am (distcheck-hook): Remove the file comparisons for files in gettext-runtime/intl/. --- diff --git a/.gitignore b/.gitignore index 98e686f51..6cca49c0e 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,9 @@ /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 diff --git a/Makefile.am b/Makefile.am index c59ef678d..764336cda 100644 --- a/Makefile.am +++ b/Makefile.am @@ -83,36 +83,6 @@ distcheck-hook: 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 diff --git a/autogen.sh b/autogen.sh index a4efe1901..e91c616cb 100755 --- a/autogen.sh +++ b/autogen.sh @@ -103,7 +103,21 @@ if ! $skip_gnulib; then $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 @@ -423,7 +437,7 @@ dir0=`pwd` 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 \ diff --git a/gettext-runtime/intl/Makefile.am b/gettext-runtime/intl/Makefile.am index 55de129a1..a4a099933 100644 --- a/gettext-runtime/intl/Makefile.am +++ b/gettext-runtime/intl/Makefile.am @@ -18,9 +18,9 @@ ## 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 = @@ -33,8 +33,9 @@ SUFFIXES = # -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 @@ -45,14 +46,6 @@ if WOE32 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". @@ -75,22 +68,8 @@ EXTRA_DIST += \ 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 @@ -212,29 +191,13 @@ LIBINTLSOURCES = \ 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 @@ -285,15 +248,6 @@ libintl.h: $(srcdir)/libgnuintl.in.h < $(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, @@ -366,46 +320,20 @@ plural.lo: $(srcdir)/plural.c $(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. @@ -415,43 +343,30 @@ if USE_INCLUDED_LIBINTL 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 @@ -478,10 +393,12 @@ MOSTLYCLEANFILES += libintl.res.lo 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. @@ -499,11 +416,11 @@ LTV_REVISION=0 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) @@ -614,6 +531,10 @@ uninstall-aliasfile: ref-del.sed 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 diff --git a/gettext-runtime/intl/arg-nonnull.h b/gettext-runtime/intl/arg-nonnull.h deleted file mode 100644 index 2eb5ad07b..000000000 --- a/gettext-runtime/intl/arg-nonnull.h +++ /dev/null @@ -1,26 +0,0 @@ -/* 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 . */ - -/* _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 diff --git a/gettext-runtime/intl/attribute.h b/gettext-runtime/intl/attribute.h deleted file mode 100644 index 01e472ab7..000000000 --- a/gettext-runtime/intl/attribute.h +++ /dev/null @@ -1,218 +0,0 @@ -/* 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 . */ - -/* 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 */ diff --git a/gettext-runtime/intl/bindtextdom.c b/gettext-runtime/intl/bindtextdom.c index 57cf1f486..81674eed5 100644 --- a/gettext-runtime/intl/bindtextdom.c +++ b/gettext-runtime/intl/bindtextdom.c @@ -1,5 +1,5 @@ /* 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 @@ -36,7 +36,7 @@ # 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 . */ diff --git a/gettext-runtime/intl/configure.ac b/gettext-runtime/intl/configure.ac index 1ce146d61..7325360d3 100644 --- a/gettext-runtime/intl/configure.ac +++ b/gettext-runtime/intl/configure.ac @@ -42,9 +42,12 @@ gl_PROG_AR_RANLIB 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. @@ -82,10 +85,8 @@ AM_CONDITIONAL([BUILD_INCLUDED_LIBINTL], [test $BUILD_INCLUDED_LIBINTL = yes]) 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 @@ -110,6 +111,9 @@ fi 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) @@ -123,6 +127,123 @@ AH_BOTTOM([ #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 diff --git a/gettext-runtime/intl/dcigettext.c b/gettext-runtime/intl/dcigettext.c index 0e9710bcf..133c93a70 100644 --- a/gettext-runtime/intl/dcigettext.c +++ b/gettext-runtime/intl/dcigettext.c @@ -1,5 +1,5 @@ /* 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 @@ -87,6 +87,7 @@ extern int errno; #if !defined _LIBC # include "localcharset.h" +# include "localename.h" #endif #include "gettextP.h" @@ -109,7 +110,7 @@ extern int errno; # 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. */ @@ -155,18 +156,7 @@ static void *mempcpy (void *dest, const void *src, size_t n); # endif #endif -/* Use a replacement if the system does not provide the `tsearch' function - family. */ -#if defined HAVE_TSEARCH || defined _LIBC -# include -#else -# define tsearch libintl_tsearch -# define tfind libintl_tfind -# define tdelete libintl_tdelete -# define twalk libintl_twalk -# include "tsearch.h" -#endif - +#include #ifdef _LIBC # define tsearch __tsearch #endif @@ -1748,10 +1738,6 @@ mempcpy (void *dest, const void *src, size_t n) } #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 diff --git a/gettext-runtime/intl/filename.h b/gettext-runtime/intl/filename.h deleted file mode 100644 index 013531244..000000000 --- a/gettext-runtime/intl/filename.h +++ /dev/null @@ -1,110 +0,0 @@ -/* 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 . */ - -/* From Paul Eggert and Jim Meyering. */ - -#ifndef _FILENAME_H -#define _FILENAME_H - -#include - -#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 */ diff --git a/gettext-runtime/intl/finddomain.c b/gettext-runtime/intl/finddomain.c index 830558d59..afc9201e0 100644 --- a/gettext-runtime/intl/finddomain.c +++ b/gettext-runtime/intl/finddomain.c @@ -1,5 +1,5 @@ /* 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 , 1995. This program is free software: you can redistribute it and/or modify @@ -43,7 +43,7 @@ # 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 @@ */ diff --git a/gettext-runtime/intl/flexmember.h b/gettext-runtime/intl/flexmember.h deleted file mode 100644 index 5a531726e..000000000 --- a/gettext-runtime/intl/flexmember.h +++ /dev/null @@ -1,57 +0,0 @@ -/* 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 . - - Written by Paul Eggert. */ - -#include - -/* 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)) diff --git a/gettext-runtime/intl/gettextP.h b/gettext-runtime/intl/gettextP.h index 1efeb192c..bb00555ee 100644 --- a/gettext-runtime/intl/gettextP.h +++ b/gettext-runtime/intl/gettextP.h @@ -1,5 +1,5 @@ /* 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 , 1995. This program is free software: you can redistribute it and/or modify @@ -33,7 +33,7 @@ # include # define gl_rwlock_define __libc_rwlock_define #else -# include "lock.h" +# include "glthread/lock.h" #endif #ifdef _LIBC @@ -234,29 +234,11 @@ extern LIBINTL_DLL_EXPORTED int _nl_msg_cat_cntr; #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, diff --git a/gettext-runtime/intl/loadmsgcat.c b/gettext-runtime/intl/loadmsgcat.c index d5a5fe171..5ca9d6e44 100644 --- a/gettext-runtime/intl/loadmsgcat.c +++ b/gettext-runtime/intl/loadmsgcat.c @@ -1,5 +1,5 @@ /* 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 @@ -99,7 +99,7 @@ char *alloca (); #ifdef _LIBC # include #else -# include "lock.h" +# include "glthread/lock.h" #endif /* Provide fallback values for macros that ought to be defined in . diff --git a/gettext-runtime/intl/localcharset.c b/gettext-runtime/intl/localcharset.c deleted file mode 100644 index ec7542769..000000000 --- a/gettext-runtime/intl/localcharset.c +++ /dev/null @@ -1,1159 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible . */ - -#include - -/* Specification. */ -#include "localcharset.h" - -#include -#include -#include -#include - -#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 -#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 -# else -# if 0 /* see comment regarding use of setlocale(), below */ -# include -# endif -# endif -# ifdef __CYGWIN__ -# define WIN32_LEAN_AND_MEAN -# include -# endif -#elif defined WINDOWS_NATIVE -# define WIN32_LEAN_AND_MEAN -# include - /* 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 -#endif - -/* For MB_CUR_MAX_L */ -#if defined DARWIN7 -# include -#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: - . - See also "__convcp() of kLIBC": - . */ - { "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 - and . */ - { "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; -} diff --git a/gettext-runtime/intl/localcharset.h b/gettext-runtime/intl/localcharset.h deleted file mode 100644 index 98a7eff98..000000000 --- a/gettext-runtime/intl/localcharset.h +++ /dev/null @@ -1,137 +0,0 @@ -/* 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 . */ - -#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 */ diff --git a/gettext-runtime/intl/localealias.c b/gettext-runtime/intl/localealias.c index 7a09f4a27..c5d6fa281 100644 --- a/gettext-runtime/intl/localealias.c +++ b/gettext-runtime/intl/localealias.c @@ -1,5 +1,5 @@ /* 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 @@ -86,7 +86,7 @@ char *alloca (); #ifdef _LIBC # include #else -# include "lock.h" +# include "glthread/lock.h" #endif #ifndef internal_function diff --git a/gettext-runtime/intl/localename-table.c b/gettext-runtime/intl/localename-table.c deleted file mode 100644 index 10be7bedf..000000000 --- a/gettext-runtime/intl/localename-table.c +++ /dev/null @@ -1,48 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 2018. */ - -#include - -#if HAVE_WORKING_USELOCALE && HAVE_NAMELESS_LOCALES - -/* Specification. */ -#include "localename-table.h" - -#include - -/* 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 diff --git a/gettext-runtime/intl/localename-table.in.h b/gettext-runtime/intl/localename-table.in.h deleted file mode 100644 index 6b2a807be..000000000 --- a/gettext-runtime/intl/localename-table.in.h +++ /dev/null @@ -1,73 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 2018. */ - -#if HAVE_WORKING_USELOCALE && HAVE_NAMELESS_LOCALES - -# include -# include - -# 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 diff --git a/gettext-runtime/intl/localename.c b/gettext-runtime/intl/localename.c deleted file mode 100644 index 0e63da4d4..000000000 --- a/gettext-runtime/intl/localename.c +++ /dev/null @@ -1,3464 +0,0 @@ -/* 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 . */ - -/* Written by Ulrich Drepper , 1995. */ -/* Native Windows code written by Tor Lillqvist . */ -/* Mac OS X code written by Bruno Haible . */ - -#include - -/* Specification. */ -#ifdef IN_LIBINTL -# include "gettextP.h" -#else -# include "localename.h" -#endif - -#include -#include -#include -#include -#include -#include - -#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 . */ -# if defined __APPLE__ && defined __MACH__ -# include -# endif -# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGINFO_H) || defined __CYGWIN__ -# include -# 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 -# endif -# endif -# if HAVE_NAMELESS_LOCALES -# include -# include "localename-table.h" -# endif -#endif - -#if HAVE_CFPREFERENCESCOPYAPPVALUE -# include -# include -#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 -# include -/* 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 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: - /* - calls it "Sesotho sa Leboa"; according to - - - 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 . */ - 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 ), - 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 (); -} diff --git a/gettext-runtime/intl/lock.c b/gettext-runtime/intl/lock.c deleted file mode 100644 index f509e217e..000000000 --- a/gettext-runtime/intl/lock.c +++ /dev/null @@ -1,749 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 2005. - Based on GCC's gthr-posix.h, gthr-posix95.h. */ - -#include - -#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 - -/* ========================================================================= */ diff --git a/gettext-runtime/intl/lock.h b/gettext-runtime/intl/lock.h deleted file mode 100644 index d65f2c033..000000000 --- a/gettext-runtime/intl/lock.h +++ /dev/null @@ -1,789 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 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 -#include - -#if !defined c11_threads_in_use -# if HAVE_THREADS_H && USE_POSIX_THREADS_WEAK -# include -# 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 - -# 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 - -# 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 - -# 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 */ diff --git a/gettext-runtime/intl/log.c b/gettext-runtime/intl/log.c index 8257ef8bf..aea66e86b 100644 --- a/gettext-runtime/intl/log.c +++ b/gettext-runtime/intl/log.c @@ -1,5 +1,5 @@ /* 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 @@ -28,7 +28,7 @@ #ifdef _LIBC # include #else -# include "lock.h" +# include "glthread/lock.h" #endif /* Separator between msgctxt and msgid in .mo files. */ diff --git a/gettext-runtime/intl/plural-exp.h b/gettext-runtime/intl/plural-exp.h index c578bcacd..eac31afca 100644 --- a/gettext-runtime/intl/plural-exp.h +++ b/gettext-runtime/intl/plural-exp.h @@ -1,5 +1,5 @@ /* 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 , 2000. This program is free software: you can redistribute it and/or modify @@ -94,10 +94,10 @@ struct parse_args # 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 diff --git a/gettext-runtime/intl/printf-args.c b/gettext-runtime/intl/printf-args.c deleted file mode 100644 index af120baac..000000000 --- a/gettext-runtime/intl/printf-args.c +++ /dev/null @@ -1,186 +0,0 @@ -/* 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 . */ - -/* 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 -#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; -} diff --git a/gettext-runtime/intl/printf-args.h b/gettext-runtime/intl/printf-args.h deleted file mode 100644 index a0f71595f..000000000 --- a/gettext-runtime/intl/printf-args.h +++ /dev/null @@ -1,157 +0,0 @@ -/* 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 . */ - -#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 - -/* Get wchar_t. */ -#if HAVE_WCHAR_T -# include -#endif - -/* Get wint_t. */ -#if HAVE_WINT_T -# include -#endif - -/* Get va_list. */ -#include - - -/* 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 */ diff --git a/gettext-runtime/intl/printf-parse.c b/gettext-runtime/intl/printf-parse.c deleted file mode 100644 index 7de467a1d..000000000 --- a/gettext-runtime/intl/printf-parse.c +++ /dev/null @@ -1,639 +0,0 @@ -/* 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 . */ - -/* 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 -#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 - -/* Get intmax_t. */ -#if defined IN_LIBINTL || defined IN_LIBASPRINTF -# if HAVE_STDINT_H_WITH_UINTMAX -# include -# endif -# if HAVE_INTTYPES_H_WITH_UINTMAX -# include -# endif -#else -# include -#endif - -/* malloc(), realloc(), free(). */ -#include - -/* memcpy(). */ -#include - -/* errno. */ -#include - -/* 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 diff --git a/gettext-runtime/intl/printf-parse.h b/gettext-runtime/intl/printf-parse.h deleted file mode 100644 index c7c55045e..000000000 --- a/gettext-runtime/intl/printf-parse.h +++ /dev/null @@ -1,84 +0,0 @@ -/* 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 . */ - -#ifndef _PRINTF_PARSE_H -#define _PRINTF_PARSE_H - -#if HAVE_FEATURES_H -# include /* 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 */ diff --git a/gettext-runtime/intl/printf.c b/gettext-runtime/intl/printf.c index 7c07ed759..d327c5ebc 100644 --- a/gettext-runtime/intl/printf.c +++ b/gettext-runtime/intl/printf.c @@ -1,5 +1,5 @@ /* 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 , 2003. This program is free software: you can redistribute it and/or modify @@ -81,6 +81,8 @@ char *alloca (); # define libintl_printf __printf__ #endif +#if 0 /* not needed */ + /* Define auxiliary functions declared in "printf-args.h". */ #include "printf-args.c" @@ -88,11 +90,16 @@ char *alloca (); #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 @@ -112,7 +119,7 @@ libintl_vfprintf (FILE *stream, const char *format, va_list args) #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) { @@ -174,7 +181,7 @@ libintl_vsprintf (char *resultbuf, const char *format, va_list args) #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); @@ -229,7 +236,7 @@ libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list a # 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) @@ -275,7 +282,7 @@ int 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) @@ -318,10 +325,10 @@ libintl_asprintf (char **resultp, const char *format, ...) #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 @@ -345,7 +352,7 @@ libintl_vfwprintf (FILE *stream, const wchar_t *format, va_list args) # 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) { @@ -410,7 +417,7 @@ libintl_vswprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, va_ # 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) diff --git a/gettext-runtime/intl/relocatable.c b/gettext-runtime/intl/relocatable.c deleted file mode 100644 index 9461458df..000000000 --- a/gettext-runtime/intl/relocatable.c +++ /dev/null @@ -1,594 +0,0 @@ -/* Provide relocatable packages. - Copyright (C) 2003-2006, 2008-2020 Free Software Foundation, Inc. - Written by Bruno Haible , 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 . */ - - -/* Tell glibc's to provide a prototype for getline(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#define _GL_USE_STDLIB_ALLOC 1 -#include - -/* Specification. */ -#include "relocatable.h" - -#if ENABLE_RELOCATABLE - -#include -#include -#include -#include - -#ifdef NO_XMALLOC -# define xmalloc malloc -#else -# include "xalloc.h" -#endif - -#if defined _WIN32 && !defined __CYGWIN__ -# define WIN32_LEAN_AND_MEAN -# include -#endif - -#ifdef __EMX__ -# define INCL_DOS -# include - -# define strcmp stricmp -# define strncmp strnicmp -#endif - -#if DEPENDS_ON_LIBCHARSET -# include -#endif -#if DEPENDS_ON_LIBICONV && HAVE_ICONV -# include -#endif -#if DEPENDS_ON_LIBINTL && ENABLE_NLS -# include -#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 ). */ - -/* 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 diff --git a/gettext-runtime/intl/relocatable.h b/gettext-runtime/intl/relocatable.h deleted file mode 100644 index 4253b667c..000000000 --- a/gettext-runtime/intl/relocatable.h +++ /dev/null @@ -1,101 +0,0 @@ -/* Provide relocatable packages. - Copyright (C) 2003, 2005, 2008-2017 Free Software Foundation, Inc. - Written by Bruno Haible , 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 . */ - -#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 */ diff --git a/gettext-runtime/intl/setlocale-lock.c b/gettext-runtime/intl/setlocale-lock.c deleted file mode 100644 index b824e383e..000000000 --- a/gettext-runtime/intl/setlocale-lock.c +++ /dev/null @@ -1,150 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 2019. */ - -#include - -/* 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 - -# 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 - -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 -# include - -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 diff --git a/gettext-runtime/intl/setlocale.c b/gettext-runtime/intl/setlocale.c index 2995db1c8..71f6f3c08 100644 --- a/gettext-runtime/intl/setlocale.c +++ b/gettext-runtime/intl/setlocale.c @@ -25,7 +25,10 @@ This matters on MacOS X 10 and Windows. See the comments in localename.c, function gl_locale_name_default. */ +/* Specification. */ #include + +#include #include #include #include @@ -41,7 +44,7 @@ # define DLL_EXPORTED #endif -#include "gettextP.h" +#include "localename.h" #if HAVE_CFLOCALECOPYPREFERREDLANGUAGES || HAVE_CFPREFERENCESCOPYAPPVALUE # if HAVE_CFLOCALECOPYPREFERREDLANGUAGES @@ -52,8 +55,12 @@ # include # include # include +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 diff --git a/gettext-runtime/intl/setlocale_null.c b/gettext-runtime/intl/setlocale_null.c deleted file mode 100644 index 1a2db2e90..000000000 --- a/gettext-runtime/intl/setlocale_null.c +++ /dev/null @@ -1,411 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 2019. */ - -#include - -/* Specification. */ -#include "setlocale_null.h" - -#include -#include -#include -#include -#if defined _WIN32 && !defined __CYGWIN__ -# include -#endif - -#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE) -# if defined _WIN32 && !defined __CYGWIN__ - -# define WIN32_LEAN_AND_MEAN /* avoid including junk */ -# include - -# elif HAVE_PTHREAD_API - -# include -# if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS -# include -# 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 - -# 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 -} diff --git a/gettext-runtime/intl/setlocale_null.h b/gettext-runtime/intl/setlocale_null.h deleted file mode 100644 index b6c5c3150..000000000 --- a/gettext-runtime/intl/setlocale_null.h +++ /dev/null @@ -1,82 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 2019. */ - -#ifndef _SETLOCALE_NULL_H -#define _SETLOCALE_NULL_H - -#include - -#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 */ diff --git a/gettext-runtime/intl/textdomain.c b/gettext-runtime/intl/textdomain.c index fb2209dc0..a509aafd4 100644 --- a/gettext-runtime/intl/textdomain.c +++ b/gettext-runtime/intl/textdomain.c @@ -1,5 +1,5 @@ /* 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 @@ -35,7 +35,7 @@ # 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 @@ */ diff --git a/gettext-runtime/intl/thread-optim.h b/gettext-runtime/intl/thread-optim.h deleted file mode 100644 index ef38ceb8f..000000000 --- a/gettext-runtime/intl/thread-optim.h +++ /dev/null @@ -1,60 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 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 -# define gl_multithreaded() !__libc_single_threaded -#else -# define gl_multithreaded() 1 -#endif - -#endif /* _THREAD_OPTIM_H */ diff --git a/gettext-runtime/intl/threadlib.c b/gettext-runtime/intl/threadlib.c deleted file mode 100644 index 2e134228f..000000000 --- a/gettext-runtime/intl/threadlib.c +++ /dev/null @@ -1,108 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 2005. */ - -#include - -/* ========================================================================= */ - -#if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS - -/* Use the POSIX threads library. */ - -# include -# include -# include - -# 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; diff --git a/gettext-runtime/intl/tsearch.c b/gettext-runtime/intl/tsearch.c deleted file mode 100644 index 9e191ef8f..000000000 --- a/gettext-runtime/intl/tsearch.c +++ /dev/null @@ -1,682 +0,0 @@ -/* Copyright (C) 1995-1997, 2000, 2006 Free Software Foundation, Inc. - Contributed by Bernd Schmidt , 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 . */ - -/* 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 - -/* Specification. */ -#ifdef IN_LIBINTL -# include "tsearch.h" -#else -# include -#endif - -#include - -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 - -#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 */ diff --git a/gettext-runtime/intl/tsearch.h b/gettext-runtime/intl/tsearch.h deleted file mode 100644 index e3a5ca44b..000000000 --- a/gettext-runtime/intl/tsearch.h +++ /dev/null @@ -1,81 +0,0 @@ -/* 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 . */ - -#ifndef _TSEARCH_H -#define _TSEARCH_H - -#if HAVE_TSEARCH - -/* Get tseach(), tfind(), tdelete(), twalk() declarations. */ -#include - -#else - -#ifdef __cplusplus -extern "C" { -#endif - -/* See , - - 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 */ diff --git a/gettext-runtime/intl/vasnprintf.c b/gettext-runtime/intl/vasnprintf.c deleted file mode 100644 index ab1119875..000000000 --- a/gettext-runtime/intl/vasnprintf.c +++ /dev/null @@ -1,5871 +0,0 @@ -/* 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 . */ - -/* 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 to provide a prototype for snprintf(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifndef VASNPRINTF -# include -#endif -#ifndef IN_LIBINTL -# include -#endif - -/* Specification. */ -#ifndef VASNPRINTF -# if WIDE_CHAR_VERSION -# include "vasnwprintf.h" -# else -# include "vasnprintf.h" -# endif -#endif - -#include /* localeconv() */ -#include /* snprintf(), sprintf() */ -#include /* abort(), malloc(), realloc(), free() */ -#include /* memcpy(), strlen() */ -#include /* errno */ -#include /* CHAR_BIT */ -#include /* DBL_MAX_EXP, LDBL_MAX_EXP */ -#if HAVE_NL_LANGINFO -# include -#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 -# include "float+.h" -#endif - -#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL -# include -# include "isnand-nolibm.h" -#endif - -#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL -# include -# include "isnanl-nolibm.h" -# include "fpucw.h" -#endif - -#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL -# include -# include "isnand-nolibm.h" -# include "printf-frexp.h" -#endif - -#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL -# include -# 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=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=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=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 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, 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 - ). - 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 - and - - 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 diff --git a/gettext-runtime/intl/verify.h b/gettext-runtime/intl/verify.h deleted file mode 100644 index cdae80ef0..000000000 --- a/gettext-runtime/intl/verify.h +++ /dev/null @@ -1,331 +0,0 @@ -/* 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 . */ - -/* 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 , included by 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 -# 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 - 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 - . 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 diff --git a/gettext-runtime/intl/windows-initguard.h b/gettext-runtime/intl/windows-initguard.h deleted file mode 100644 index 7a3aa6d43..000000000 --- a/gettext-runtime/intl/windows-initguard.h +++ /dev/null @@ -1,35 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 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 - -typedef struct - { - volatile int done; - volatile LONG started; - } - glwthread_initguard_t; - -#define GLWTHREAD_INITGUARD_INIT { 0, -1 } - -#endif /* _WINDOWS_INITGUARD_H */ diff --git a/gettext-runtime/intl/windows-mutex.c b/gettext-runtime/intl/windows-mutex.c deleted file mode 100644 index 9c1f82aab..000000000 --- a/gettext-runtime/intl/windows-mutex.c +++ /dev/null @@ -1,95 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 2005. - Based on GCC's gthr-win32.h. */ - -#include - -/* Specification. */ -#include "windows-mutex.h" - -#include - -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; -} diff --git a/gettext-runtime/intl/windows-mutex.h b/gettext-runtime/intl/windows-mutex.h deleted file mode 100644 index 5d3d8e4db..000000000 --- a/gettext-runtime/intl/windows-mutex.h +++ /dev/null @@ -1,51 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 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 - -#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 */ diff --git a/gettext-runtime/intl/windows-once.c b/gettext-runtime/intl/windows-once.c deleted file mode 100644 index 73315b12f..000000000 --- a/gettext-runtime/intl/windows-once.c +++ /dev/null @@ -1,62 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 2005. - Based on GCC's gthr-win32.h. */ - -#include - -/* Specification. */ -#include "windows-once.h" - -#include - -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 (); - } - } - } -} diff --git a/gettext-runtime/intl/windows-once.h b/gettext-runtime/intl/windows-once.h deleted file mode 100644 index 3beced439..000000000 --- a/gettext-runtime/intl/windows-once.h +++ /dev/null @@ -1,47 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 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 - -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 */ diff --git a/gettext-runtime/intl/windows-recmutex.c b/gettext-runtime/intl/windows-recmutex.c deleted file mode 100644 index 265fcbeb3..000000000 --- a/gettext-runtime/intl/windows-recmutex.c +++ /dev/null @@ -1,127 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 2005. - Based on GCC's gthr-win32.h. */ - -#include - -/* Specification. */ -#include "windows-recmutex.h" - -#include - -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; -} diff --git a/gettext-runtime/intl/windows-recmutex.h b/gettext-runtime/intl/windows-recmutex.h deleted file mode 100644 index 2586cc50e..000000000 --- a/gettext-runtime/intl/windows-recmutex.h +++ /dev/null @@ -1,57 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 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 - -#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 */ diff --git a/gettext-runtime/intl/windows-rwlock.c b/gettext-runtime/intl/windows-rwlock.c deleted file mode 100644 index 30707d4ec..000000000 --- a/gettext-runtime/intl/windows-rwlock.c +++ /dev/null @@ -1,377 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 2005. - Based on GCC's gthr-win32.h. */ - -#include - -/* Specification. */ -#include "windows-rwlock.h" - -#include -#include - -/* 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; -} diff --git a/gettext-runtime/intl/windows-rwlock.h b/gettext-runtime/intl/windows-rwlock.h deleted file mode 100644 index 8fc017c76..000000000 --- a/gettext-runtime/intl/windows-rwlock.h +++ /dev/null @@ -1,68 +0,0 @@ -/* 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 . */ - -/* Written by Bruno Haible , 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 - -#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 */ diff --git a/gettext-runtime/intl/xsize.c b/gettext-runtime/intl/xsize.c deleted file mode 100644 index 4b4914c2c..000000000 --- a/gettext-runtime/intl/xsize.c +++ /dev/null @@ -1,3 +0,0 @@ -#include -#define XSIZE_INLINE _GL_EXTERN_INLINE -#include "xsize.h" diff --git a/gettext-runtime/intl/xsize.h b/gettext-runtime/intl/xsize.h deleted file mode 100644 index 3f367f6c2..000000000 --- a/gettext-runtime/intl/xsize.h +++ /dev/null @@ -1,108 +0,0 @@ -/* 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 . */ - -#ifndef _XSIZE_H -#define _XSIZE_H - -/* Get size_t. */ -#include - -/* Get SIZE_MAX. */ -#include -#if HAVE_STDINT_H -# include -#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 */ diff --git a/gettext-runtime/m4/intl.m4 b/gettext-runtime/m4/intl.m4 index 84a166f61..5453f195e 100644 --- a/gettext-runtime/m4/intl.m4 +++ b/gettext-runtime/m4/intl.m4 @@ -1,4 +1,4 @@ -# 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, @@ -160,48 +160,6 @@ AC_DEFUN([AM_INTL_SUBDIR], 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 -]) ]) @@ -242,7 +200,7 @@ AC_DEFUN([gt_INTL_SUBDIR_CORE], 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 diff --git a/gnulib-local/Makefile.am b/gnulib-local/Makefile.am index 8045a8068..d6004ef1c 100644 --- a/gnulib-local/Makefile.am +++ b/gnulib-local/Makefile.am @@ -136,6 +136,8 @@ lib/libxml/xpath.in.h \ 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 \ @@ -144,6 +146,7 @@ lib/obstack.h.diff \ 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 \ @@ -154,6 +157,7 @@ m4/libxml.m4 \ modules/backupfile \ modules/closeout \ modules/error-progname \ +modules/gettext-runtime-intl-misc \ modules/gettext-runtime-misc \ modules/gettext-tools-misc \ modules/java \ @@ -161,6 +165,7 @@ modules/libtextstyle-dummy \ modules/libxml \ modules/markup \ modules/mem-hash-map \ +modules/tsearch.diff \ modules/xerror \ modules/xgetcwd diff --git a/gnulib-local/lib/localename-table.h.diff b/gnulib-local/lib/localename-table.h.diff new file mode 100644 index 000000000..8b99815a7 --- /dev/null +++ b/gnulib-local/lib/localename-table.h.diff @@ -0,0 +1,17 @@ +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 + # include + +-# ifdef IN_LIBINTL +-# include "lock.h" +-# else +-# include "glthread/lock.h" +-# endif ++# include "glthread/lock.h" + + struct locale_categories_names + { diff --git a/gnulib-local/lib/localename.c.diff b/gnulib-local/lib/localename.c.diff new file mode 100644 index 000000000..14ee65975 --- /dev/null +++ b/gnulib-local/lib/localename.c.diff @@ -0,0 +1,37 @@ +--- 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 + + /* Specification. */ +-#ifdef IN_LIBINTL +-# include "gettextP.h" +-#else +-# include "localename.h" +-#endif ++#include "localename.h" + + #include + #include +@@ -46,9 +42,7 @@ + # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGINFO_H) || defined __CYGWIN__ + # include + # 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 */ diff --git a/gnulib-local/lib/tsearch.c.diff b/gnulib-local/lib/tsearch.c.diff new file mode 100644 index 000000000..fd68a1a76 --- /dev/null +++ b/gnulib-local/lib/tsearch.c.diff @@ -0,0 +1,17 @@ +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 + + /* Specification. */ +-#ifdef IN_LIBINTL +-# include "tsearch.h" +-#else +-# include +-#endif ++#include + + #include + diff --git a/gnulib-local/modules/gettext-runtime-intl-misc b/gnulib-local/modules/gettext-runtime-intl-misc new file mode 100644 index 000000000..a6d5feb4f --- /dev/null +++ b/gnulib-local/modules/gettext-runtime-intl-misc @@ -0,0 +1,22 @@ +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 diff --git a/gnulib-local/modules/tsearch.diff b/gnulib-local/modules/tsearch.diff new file mode 100644 index 000000000..7b1b01de6 --- /dev/null +++ b/gnulib-local/modules/tsearch.diff @@ -0,0 +1,13 @@ +diff --git a/modules/tsearch b/modules/tsearch +index 4a2b5ed..6ffdf2f 100644 +--- a/modules/tsearch ++++ b/modules/tsearch +@@ -22,7 +22,7 @@ Include: + + + License: +-LGPL ++LGPLv2+ + + Maintainer: + all, glibc