mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-14 23:50:49 +02:00
fix obscure macOS issue where the Apple locale is set to something setlocale(3) doesn't understand; don't source .bash_logout if the shell is running setuid; fix for macOS issue with pipe size throttling and here-documents
This commit is contained in:
@@ -86,6 +86,7 @@ HEADERS = gmo.h gettextP.h hash-string.h loadinfo.h plural-exp.h \
|
||||
thread-optim.h tsearch.h verify.h xsize.h \
|
||||
printf-args.h printf-parse.h wprintf-parse.h \
|
||||
export.h os2compat.h plural-exp.h vasnprintf.h vasnwprintf.h \
|
||||
localename.h \
|
||||
libgnuintl.in.h
|
||||
|
||||
SOURCES = bindtextdom.c dcgettext.c dgettext.c gettext.c \
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/* Determine name of the currently selected locale.
|
||||
Copyright (C) 2007, 2009-2026 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GL_LOCALENAME_H
|
||||
#define _GL_LOCALENAME_H
|
||||
|
||||
/* This file uses _GL_ATTRIBUTE_CONST, HAVE_CFPREFERENCESCOPYAPPVALUE. */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Determine the current locale's name.
|
||||
It considers both the POSIX notion of locale name (see functions
|
||||
gl_locale_name_thread and gl_locale_name_posix) and the system notion
|
||||
of locale name (see function gl_locale_name_default).
|
||||
CATEGORY is a locale category abbreviation, as defined in <locale.h>,
|
||||
but not LC_ALL. E.g. LC_MESSAGES.
|
||||
CATEGORYNAME is the name of CATEGORY as a string, e.g. "LC_MESSAGES".
|
||||
Return the locale category's name, canonicalized 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. */
|
||||
extern const char * gl_locale_name (int category, const char *categoryname);
|
||||
|
||||
/* Determine the current per-thread locale's name, as specified by uselocale()
|
||||
calls.
|
||||
CATEGORY is a locale category abbreviation, as defined in <locale.h>,
|
||||
but not LC_ALL. E.g. LC_MESSAGES.
|
||||
CATEGORYNAME is the name of CATEGORY as a string, e.g. "LC_MESSAGES".
|
||||
Return the locale category's name, canonicalized into XPG syntax
|
||||
language[_territory][.codeset][@modifier]
|
||||
or NULL if no locale has been specified for the current thread.
|
||||
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. */
|
||||
extern const char * gl_locale_name_thread (int category, const char *categoryname);
|
||||
|
||||
/* Determine the thread-independent current locale's name, as specified by
|
||||
setlocale() calls or by environment variables.
|
||||
CATEGORY is a locale category abbreviation, as defined in <locale.h>,
|
||||
but not LC_ALL. E.g. LC_MESSAGES.
|
||||
CATEGORYNAME is the name of CATEGORY as a string, e.g. "LC_MESSAGES".
|
||||
Return the locale category's name, canonicalized into XPG syntax
|
||||
language[_territory][.codeset][@modifier]
|
||||
or NULL if no locale has been specified to setlocale() or by environment
|
||||
variables.
|
||||
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. */
|
||||
extern const char * gl_locale_name_posix (int category, const char *categoryname);
|
||||
|
||||
/* Determine the default locale's name, as specified by environment
|
||||
variables.
|
||||
Return the locale category's name, or NULL if no locale has been specified
|
||||
by environment variables.
|
||||
The result must not be freed; it is statically allocated. */
|
||||
extern const char * gl_locale_name_environ (int category, const char *categoryname);
|
||||
|
||||
/* Determine the default locale's name. This is the current locale's name,
|
||||
if not specified by uselocale() calls, by setlocale() calls, or by
|
||||
environment variables. This locale name is usually determined by systems
|
||||
settings that the user can manipulate through a GUI.
|
||||
|
||||
Quoting POSIX:2001:
|
||||
"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 C 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. IEEE Std 1003.1-2001 does
|
||||
not require such a facility."
|
||||
|
||||
The result must not be freed; it is statically allocated. */
|
||||
extern const char * gl_locale_name_default (void)
|
||||
#if !(HAVE_CFPREFERENCESCOPYAPPVALUE || defined _WIN32 || defined __CYGWIN__)
|
||||
_GL_ATTRIBUTE_CONST
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
/* These functions with the '_unsafe' suffix are like the functions without
|
||||
this suffix, above, except that the result is not statically allocated, but
|
||||
instead only valid in the current thread, until the next uselocale(),
|
||||
setlocale(), newlocale(), or freelocale() call. */
|
||||
extern const char * gl_locale_name_unsafe (int category,
|
||||
const char *categoryname);
|
||||
extern const char * gl_locale_name_thread_unsafe (int category,
|
||||
const char *categoryname);
|
||||
extern const char * gl_locale_name_posix_unsafe (int category,
|
||||
const char *categoryname);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GL_LOCALENAME_H */
|
||||
@@ -0,0 +1,64 @@
|
||||
/* Make the global locale minimally POSIX compliant.
|
||||
Copyright (C) 2025-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file 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 file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Bruno Haible <bruno@clisp.org>, 2025. */
|
||||
|
||||
#ifndef _SETLOCALE_FIXES_H
|
||||
#define _SETLOCALE_FIXES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
|
||||
/* This section is only relevant on platforms that lack LC_MESSAGES, namely
|
||||
native Windows. */
|
||||
|
||||
/* setlocale_messages (NAME) is like setlocale (LC_MESSAGES, NAME). */
|
||||
extern const char *setlocale_messages (const char *name);
|
||||
|
||||
/* setlocale_messages_null () is like setlocale (LC_MESSAGES, NULL), except that
|
||||
it is guaranteed to be multithread-safe. */
|
||||
extern const char *setlocale_messages_null (void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined __ANDROID__
|
||||
|
||||
/* This section is only relevant on Android.
|
||||
While OpenBSD ≥ 6.2 and Android API level >= 21 have a fake locale_t type,
|
||||
regarding the global locale, OpenBSD at least stores the name of each
|
||||
category of the global locale. Android doesn't do this, and additionally
|
||||
has a bug: setting any category != LC_CTYPE of the global locale affects
|
||||
the LC_CTYPE category as well. */
|
||||
|
||||
/* Like setlocale (CATEGORY, NAME), but fixes these two Android bugs. */
|
||||
extern const char *setlocale_fixed (int category, const char *name);
|
||||
|
||||
/* Like setlocale_null (CATEGORY), but consistent with setlocale_fixed. */
|
||||
extern const char *setlocale_fixed_null (int category);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SETLOCALE_FIXES_H */
|
||||
+234
-69
@@ -1,6 +1,5 @@
|
||||
/* setlocale() function that respects the locale chosen by the user.
|
||||
Copyright (C) 2009, 2011, 2013, 2018-2019 Free Software Foundation, Inc.
|
||||
Written by Bruno Haible <bruno@clisp.org>, 2009.
|
||||
Copyright (C) 2009-2026 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
|
||||
@@ -15,6 +14,8 @@
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Bruno Haible. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
@@ -25,23 +26,40 @@
|
||||
This matters on MacOS X 10 and Windows.
|
||||
See the comments in localename.c, function gl_locale_name_default. */
|
||||
|
||||
/* Specification. */
|
||||
#include <locale.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* When building a DLL, we must export some functions. Note that because
|
||||
the functions are only defined for binary backward compatibility, we
|
||||
don't need to use __declspec(dllimport) in any case. */
|
||||
#if HAVE_VISIBILITY && BUILDING_DLL
|
||||
# define DLL_EXPORTED __attribute__((__visibility__("default")))
|
||||
#elif defined _MSC_VER && BUILDING_DLL
|
||||
# define DLL_EXPORTED __declspec(dllexport)
|
||||
/* When building a shared library, we must export some functions.
|
||||
Note that because this is a .c file, not a .h file, we don't need to use
|
||||
__declspec(dllimport) in any case. */
|
||||
#if HAVE_VISIBILITY && BUILDING_LIBRARY
|
||||
# define SHLIB_EXPORTED __attribute__((__visibility__("default")))
|
||||
#elif defined _MSC_VER && BUILDING_LIBRARY
|
||||
/* When building with MSVC, exporting a symbol means that the object file
|
||||
contains a "linker directive" of the form /EXPORT:symbol. This can be
|
||||
inspected through the "objdump -s --section=.drectve FILE" or
|
||||
"dumpbin /directives FILE" commands.
|
||||
The symbols from this file should be exported if and only if the object
|
||||
file gets included in a DLL. Libtool, on Windows platforms, defines
|
||||
the C macro DLL_EXPORT (together with PIC) when compiling for a shared
|
||||
library (called DLL under Windows) and does not define it when compiling
|
||||
an object file meant to be linked statically into some executable. */
|
||||
# if defined DLL_EXPORT
|
||||
# define SHLIB_EXPORTED __declspec(dllexport)
|
||||
# else
|
||||
# define SHLIB_EXPORTED
|
||||
# endif
|
||||
#else
|
||||
# define DLL_EXPORTED
|
||||
# define SHLIB_EXPORTED
|
||||
#endif
|
||||
|
||||
#include "gettextP.h"
|
||||
#include "setlocale-fixes.h"
|
||||
#include "localename.h"
|
||||
|
||||
#if HAVE_CFLOCALECOPYPREFERREDLANGUAGES || HAVE_CFPREFERENCESCOPYAPPVALUE
|
||||
# if HAVE_CFLOCALECOPYPREFERREDLANGUAGES
|
||||
@@ -52,8 +70,17 @@
|
||||
# include <CoreFoundation/CFPropertyList.h>
|
||||
# include <CoreFoundation/CFArray.h>
|
||||
# include <CoreFoundation/CFString.h>
|
||||
extern void gl_locale_name_canonicalize (char *name);
|
||||
#endif
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
/* Get _nl_msg_cat_cntr declaration. */
|
||||
#include "gettextP.h"
|
||||
|
||||
#if (defined __APPLE__ && defined __MACH__) || defined _WIN32 || defined __CYGWIN__
|
||||
|
||||
# undef setlocale
|
||||
@@ -649,6 +676,7 @@ search (const struct table_entry *table, size_t table_size, const char *string,
|
||||
static char *
|
||||
setlocale_unixlike (int category, const char *locale)
|
||||
{
|
||||
int is_utf8 = (GetACP () == 65001);
|
||||
char *result;
|
||||
char llCC_buf[64];
|
||||
char ll_buf[64];
|
||||
@@ -659,6 +687,15 @@ setlocale_unixlike (int category, const char *locale)
|
||||
if (locale != NULL && strcmp (locale, "POSIX") == 0)
|
||||
locale = "C";
|
||||
|
||||
/* The native Windows implementation of setlocale, in the UTF-8 environment,
|
||||
does not understand the locale names "C.UTF-8" or "C.utf8" or "C.65001",
|
||||
but it understands "English_United States.65001", which is functionally
|
||||
equivalent. */
|
||||
if (locale != NULL
|
||||
&& ((is_utf8 && strcmp (locale, "C") == 0)
|
||||
|| strcmp (locale, "C.UTF-8") == 0))
|
||||
locale = "English_United States.65001";
|
||||
|
||||
/* First, try setlocale with the original argument unchanged. */
|
||||
result = setlocale (category, locale);
|
||||
if (result != NULL)
|
||||
@@ -691,7 +728,15 @@ setlocale_unixlike (int category, const char *locale)
|
||||
*/
|
||||
if (strcmp (llCC_buf, locale) != 0)
|
||||
{
|
||||
result = setlocale (category, llCC_buf);
|
||||
if (is_utf8)
|
||||
{
|
||||
char buf[64+6];
|
||||
strcpy (buf, llCC_buf);
|
||||
strcat (buf, ".65001");
|
||||
result = setlocale (category, buf);
|
||||
}
|
||||
else
|
||||
result = setlocale (category, llCC_buf);
|
||||
if (result != NULL)
|
||||
return result;
|
||||
}
|
||||
@@ -708,7 +753,15 @@ setlocale_unixlike (int category, const char *locale)
|
||||
for (i = range.lo; i < range.hi; i++)
|
||||
{
|
||||
/* Try the replacement in language_table[i]. */
|
||||
result = setlocale (category, language_table[i].english);
|
||||
if (is_utf8)
|
||||
{
|
||||
char buf[64+6];
|
||||
strcpy (buf, language_table[i].english);
|
||||
strcat (buf, ".65001");
|
||||
result = setlocale (category, buf);
|
||||
}
|
||||
else
|
||||
result = setlocale (category, language_table[i].english);
|
||||
if (result != NULL)
|
||||
return result;
|
||||
}
|
||||
@@ -762,13 +815,15 @@ setlocale_unixlike (int category, const char *locale)
|
||||
size_t part1_len = strlen (part1);
|
||||
const char *part2 = country_table[j].english;
|
||||
size_t part2_len = strlen (part2) + 1;
|
||||
char buf[64+64];
|
||||
char buf[64+64+6];
|
||||
|
||||
if (!(part1_len + 1 + part2_len <= sizeof (buf)))
|
||||
if (!(part1_len + 1 + part2_len + 6 <= sizeof (buf)))
|
||||
abort ();
|
||||
memcpy (buf, part1, part1_len);
|
||||
buf[part1_len] = '_';
|
||||
memcpy (buf + part1_len + 1, part2, part2_len);
|
||||
if (is_utf8)
|
||||
strcat (buf, ".65001");
|
||||
|
||||
/* Try the concatenated replacements. */
|
||||
result = setlocale (category, buf);
|
||||
@@ -786,8 +841,16 @@ setlocale_unixlike (int category, const char *locale)
|
||||
for (i = language_range.lo; i < language_range.hi; i++)
|
||||
{
|
||||
/* Try only the language replacement. */
|
||||
result =
|
||||
setlocale (category, language_table[i].english);
|
||||
if (is_utf8)
|
||||
{
|
||||
char buf[64+6];
|
||||
strcpy (buf, language_table[i].english);
|
||||
strcat (buf, ".65001");
|
||||
result = setlocale (category, buf);
|
||||
}
|
||||
else
|
||||
result =
|
||||
setlocale (category, language_table[i].english);
|
||||
if (result != NULL)
|
||||
return result;
|
||||
}
|
||||
@@ -808,7 +871,7 @@ setlocale_unixlike (int category, const char *locale)
|
||||
static char *
|
||||
setlocale_unixlike (int category, const char *locale)
|
||||
{
|
||||
char *result = setlocale (category, locale);
|
||||
char *result = setlocale_fixed (category, locale);
|
||||
if (result == NULL)
|
||||
switch (category)
|
||||
{
|
||||
@@ -841,22 +904,12 @@ setlocale_unixlike (int category, const char *locale)
|
||||
|
||||
# if LC_MESSAGES == 1729
|
||||
|
||||
/* The system does not store an LC_MESSAGES locale category. Do it here. */
|
||||
static char lc_messages_name[64] = "C";
|
||||
|
||||
/* Like setlocale, but support also LC_MESSAGES. */
|
||||
static char *
|
||||
setlocale_single (int category, const char *locale)
|
||||
{
|
||||
if (category == LC_MESSAGES)
|
||||
{
|
||||
if (locale != NULL)
|
||||
{
|
||||
lc_messages_name[sizeof (lc_messages_name) - 1] = '\0';
|
||||
strncpy (lc_messages_name, locale, sizeof (lc_messages_name) - 1);
|
||||
}
|
||||
return lc_messages_name;
|
||||
}
|
||||
return setlocale_messages (locale);
|
||||
else
|
||||
return setlocale_unixlike (category, locale);
|
||||
}
|
||||
@@ -932,6 +985,7 @@ static char const locales_with_principal_territory[][6 + 1] =
|
||||
"fy_NL", /* Western Frisian Netherlands */
|
||||
"ga_IE", /* Irish Ireland */
|
||||
"gd_GB", /* Scottish Gaelic Britain */
|
||||
"gl_ES", /* Galician Spain */
|
||||
"gon_IN", /* Gondi India */
|
||||
"gsw_CH", /* Swiss German Switzerland */
|
||||
"gu_IN", /* Gujarati India */
|
||||
@@ -1050,6 +1104,7 @@ static char const locales_with_principal_territory[][6 + 1] =
|
||||
"suk_TZ", /* Sukuma Tanzania */
|
||||
"sus_GN", /* Susu Guinea */
|
||||
"sv_SE", /* Swedish Sweden */
|
||||
"ta_IN", /* Tamil India */
|
||||
"te_IN", /* Telugu India */
|
||||
"tem_SL", /* Timne Sierra Leone */
|
||||
"tet_ID", /* Tetum Indonesia */
|
||||
@@ -1061,7 +1116,7 @@ static char const locales_with_principal_territory[][6 + 1] =
|
||||
"tl_PH", /* Tagalog Philippines */
|
||||
"to_TO", /* Tonga Tonga */
|
||||
"tpi_PG", /* Tok Pisin Papua New Guinea */
|
||||
"tr_TR", /* Turkish Turkey */
|
||||
"tr_TR", /* Turkish Türkiye */
|
||||
"tum_MW", /* Tumbuka Malawi */
|
||||
"ug_CN", /* Uighur China */
|
||||
"uk_UA", /* Ukrainian Ukraine */
|
||||
@@ -1316,7 +1371,7 @@ static char const locales_with_principal_language[][6 + 1] =
|
||||
"tk_TM", /* Turkmen Turkmenistan */
|
||||
"ar_TN", /* Arabic Tunisia */
|
||||
"to_TO", /* Tonga Tonga */
|
||||
"tr_TR", /* Turkish Turkey */
|
||||
"tr_TR", /* Turkish Türkiye */
|
||||
"zh_TW", /* Chinese Taiwan */
|
||||
"sw_TZ", /* Swahili Tanzania */
|
||||
"uk_UA", /* Ukrainian Ukraine */
|
||||
@@ -1386,7 +1441,7 @@ get_main_locale_with_same_territory (const char *locale)
|
||||
|
||||
# endif
|
||||
|
||||
DLL_EXPORTED
|
||||
SHLIB_EXPORTED
|
||||
char *
|
||||
libintl_setlocale (int category, const char *locale)
|
||||
{
|
||||
@@ -1552,7 +1607,7 @@ libintl_setlocale (int category, const char *locale)
|
||||
For LC_COLLATE, the application should use the locale
|
||||
properties kCFLocaleCollationIdentifier,
|
||||
kCFLocaleCollatorIdentifier.
|
||||
For LC_MONETARY, the applicationshould use the locale
|
||||
For LC_MONETARY, the application should use the locale
|
||||
properties kCFLocaleCurrencySymbol,
|
||||
kCFLocaleCurrencyCode.
|
||||
But since most applications don't have macOS specific
|
||||
@@ -1587,7 +1642,7 @@ libintl_setlocale (int category, const char *locale)
|
||||
/* All steps were successful. */
|
||||
++_nl_msg_cat_cntr;
|
||||
free (saved_locale);
|
||||
return setlocale (LC_ALL, NULL);
|
||||
goto ret_all;
|
||||
|
||||
fail:
|
||||
if (saved_locale[0] != '\0') /* don't risk an endless recursion */
|
||||
@@ -1611,55 +1666,165 @@ libintl_setlocale (int category, const char *locale)
|
||||
}
|
||||
else
|
||||
{
|
||||
# if defined _WIN32 && ! defined __CYGWIN__
|
||||
if (category == LC_ALL && locale != NULL && strchr (locale, '.') != NULL)
|
||||
# if LC_MESSAGES == 1729
|
||||
if (locale != NULL)
|
||||
{
|
||||
char *saved_locale;
|
||||
char truncated_locale[SETLOCALE_NULL_ALL_MAX];
|
||||
const char *native_locale;
|
||||
const char *messages_locale;
|
||||
|
||||
/* Back up the old locale. */
|
||||
saved_locale = setlocale (LC_ALL, NULL);
|
||||
if (saved_locale == NULL)
|
||||
return NULL;
|
||||
saved_locale = strdup (saved_locale);
|
||||
if (saved_locale == NULL)
|
||||
return NULL;
|
||||
|
||||
if (setlocale_unixlike (LC_ALL, locale) == NULL)
|
||||
if (strncmp (locale, "LC_COLLATE=", 11) == 0)
|
||||
{
|
||||
free (saved_locale);
|
||||
return NULL;
|
||||
/* The locale argument indicates a mixed locale. It must be of
|
||||
the form
|
||||
"LC_COLLATE=...;LC_CTYPE=...;LC_MONETARY=...;LC_NUMERIC=...;LC_TIME=...;LC_MESSAGES=..."
|
||||
since that is what this function returns (see ret_all below).
|
||||
Decompose it. */
|
||||
const char *last_semicolon = strrchr (locale, ';');
|
||||
if (!(last_semicolon != NULL
|
||||
&& strncmp (last_semicolon + 1, "LC_MESSAGES=", 12) == 0))
|
||||
return NULL;
|
||||
if (category == LC_MESSAGES)
|
||||
return setlocale_single (category, last_semicolon + 13);
|
||||
size_t truncated_locale_len = last_semicolon - locale;
|
||||
if (truncated_locale_len >= sizeof (truncated_locale))
|
||||
return NULL;
|
||||
memcpy (truncated_locale, locale, truncated_locale_len);
|
||||
truncated_locale[truncated_locale_len] = '\0';
|
||||
native_locale = truncated_locale;
|
||||
messages_locale = last_semicolon + 13;
|
||||
}
|
||||
else
|
||||
{
|
||||
native_locale = locale;
|
||||
messages_locale = locale;
|
||||
}
|
||||
|
||||
/* On native Windows, setlocale(LC_ALL,...) may succeed but set the
|
||||
LC_CTYPE category to an invalid value ("C") when it does not
|
||||
support the specified encoding. Report a failure instead. */
|
||||
if (strcmp (setlocale (LC_CTYPE, NULL), "C") == 0)
|
||||
if (category == LC_ALL)
|
||||
{
|
||||
if (saved_locale[0] != '\0') /* don't risk an endless recursion */
|
||||
setlocale (LC_ALL, saved_locale);
|
||||
free (saved_locale);
|
||||
return NULL;
|
||||
}
|
||||
/* In the underlying implementation, LC_ALL does not contain
|
||||
LC_MESSAGES. Therefore we need to handle LC_MESSAGES
|
||||
separately. */
|
||||
char *result;
|
||||
|
||||
/* It was really successful. */
|
||||
++_nl_msg_cat_cntr;
|
||||
free (saved_locale);
|
||||
return setlocale (LC_ALL, NULL);
|
||||
# if defined _WIN32 && ! defined __CYGWIN__
|
||||
if (strchr (native_locale, '.') != NULL)
|
||||
{
|
||||
char *saved_locale;
|
||||
|
||||
/* Back up the old locale. */
|
||||
saved_locale = setlocale (LC_ALL, NULL);
|
||||
if (saved_locale == NULL)
|
||||
return NULL;
|
||||
saved_locale = strdup (saved_locale);
|
||||
if (saved_locale == NULL)
|
||||
return NULL;
|
||||
|
||||
if (setlocale_unixlike (LC_ALL, native_locale) == NULL)
|
||||
{
|
||||
free (saved_locale);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* On native Windows, setlocale(LC_ALL,...) may succeed but
|
||||
set the LC_CTYPE category to an invalid value ("C") when
|
||||
it does not support the specified encoding. Report a
|
||||
failure instead. */
|
||||
if (strcmp (setlocale (LC_CTYPE, NULL), "C") == 0)
|
||||
{
|
||||
/* Don't risk an endless recursion. */
|
||||
if (saved_locale[0] != '\0')
|
||||
setlocale (LC_ALL, saved_locale);
|
||||
free (saved_locale);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* It was really successful. */
|
||||
free (saved_locale);
|
||||
result = setlocale (LC_ALL, NULL);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
result = setlocale_single (LC_ALL, native_locale);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
setlocale_single (LC_MESSAGES, messages_locale);
|
||||
|
||||
++_nl_msg_cat_cntr;
|
||||
goto ret_all;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *result;
|
||||
|
||||
if (category == LC_MESSAGES)
|
||||
result = setlocale_single (category, messages_locale);
|
||||
else
|
||||
result = setlocale_single (category, native_locale);
|
||||
if (result != NULL)
|
||||
++_nl_msg_cat_cntr;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
else /* locale == NULL */
|
||||
{
|
||||
if (category == LC_ALL)
|
||||
goto ret_all;
|
||||
else
|
||||
return setlocale_single (category, NULL);
|
||||
}
|
||||
# else
|
||||
return setlocale_single (category, locale);
|
||||
# endif
|
||||
{
|
||||
char *result = setlocale_single (category, locale);
|
||||
if (result != NULL)
|
||||
++_nl_msg_cat_cntr;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
ret_all:
|
||||
/* Return the name of all categories of the current locale. */
|
||||
# if LC_MESSAGES == 1729 /* native Windows */
|
||||
/* The locale name for mixed locales looks like this:
|
||||
"LC_COLLATE=...;LC_CTYPE=...;LC_MONETARY=...;LC_NUMERIC=...;LC_TIME=..."
|
||||
If necessary, add ";LC_MESSAGES=..." at the end. */
|
||||
{
|
||||
char *name1 = setlocale (LC_ALL, NULL);
|
||||
char *name2 = setlocale_single (LC_MESSAGES, NULL);
|
||||
if (strcmp (name1, name2) == 0)
|
||||
/* Not a mixed locale. */
|
||||
return name1;
|
||||
else
|
||||
{
|
||||
static char resultbuf[SETLOCALE_NULL_ALL_MAX];
|
||||
/* Prepare the result in a stack-allocated buffer, in order to reduce
|
||||
race conditions in a multithreaded situation. */
|
||||
char stackbuf[SETLOCALE_NULL_ALL_MAX];
|
||||
if (strncmp (name1, "LC_COLLATE=", 11) == 0)
|
||||
{
|
||||
if (strlen (name1) + strlen (name2) + 13 >= sizeof (stackbuf))
|
||||
return NULL;
|
||||
sprintf (stackbuf, "%s;LC_MESSAGES=%s", name1, name2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (5 * strlen (name1) + strlen (name2) + 68 >= sizeof (stackbuf))
|
||||
return NULL;
|
||||
sprintf (stackbuf,
|
||||
"LC_COLLATE=%s;LC_CTYPE=%s;LC_MONETARY=%s;LC_NUMERIC=%s;LC_TIME=%s;LC_MESSAGES=%s",
|
||||
name1, name1, name1, name1, name1, name2);
|
||||
}
|
||||
strcpy (resultbuf, stackbuf);
|
||||
return resultbuf;
|
||||
}
|
||||
}
|
||||
# elif defined __ANDROID__
|
||||
return setlocale_fixed_null (LC_ALL);
|
||||
# else
|
||||
return setlocale (LC_ALL, NULL);
|
||||
# endif
|
||||
}
|
||||
|
||||
# if HAVE_NEWLOCALE
|
||||
|
||||
DLL_EXPORTED
|
||||
SHLIB_EXPORTED
|
||||
locale_t
|
||||
libintl_newlocale (int category_mask, const char *locale, locale_t base)
|
||||
{
|
||||
|
||||
@@ -1212,7 +1212,7 @@ the previous command.
|
||||
Once the argument \fIn\fP is computed,
|
||||
this uses the history expansion facilities to extract the
|
||||
\fIn\fPth word, as if the
|
||||
.Q !\fIn\fP
|
||||
.Q !!:\fIn\fP
|
||||
history expansion had been specified.
|
||||
.TP
|
||||
.B
|
||||
|
||||
@@ -1501,7 +1501,7 @@ the previous command.
|
||||
Once the argument @var{n} is computed,
|
||||
this uses the history expansion facilities to extract the
|
||||
@var{n}th word, as if the
|
||||
@samp{!@var{n}} history expansion had been specified.
|
||||
@samp{!!:@var{n}} history expansion had been specified.
|
||||
|
||||
@item yank-last-arg (M-. or M-_)
|
||||
Insert last argument to the previous command (the last word of the
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
@ignore
|
||||
Copyright (C) 1988-2025 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2026 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set EDITION 8.3
|
||||
@set VERSION 8.3
|
||||
|
||||
@set UPDATED 25 August 2025
|
||||
@set UPDATED-MONTH August 2025
|
||||
@set UPDATED 9 July 2026
|
||||
@set UPDATED-MONTH July 2026
|
||||
|
||||
@set LASTCHANGE Mon Aug 25 11:33:46 EDT 2025
|
||||
@set LASTCHANGE Thu Jul 9 09:20:35 EDT 2026
|
||||
|
||||
Reference in New Issue
Block a user