[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[bug-gettext] [PATCH] Make libintl_setlocale fail more gracefully
From: |
Dapeng Gao |
Subject: |
[bug-gettext] [PATCH] Make libintl_setlocale fail more gracefully |
Date: |
Sat, 11 Aug 2018 00:28:10 +0800 |
User-agent: |
NeoMutt/20180716-171-eb8b46 |
Hi,
I patched `libintl_setlocale` to fail more gracefully when it.
Specifically, whenver the original implementation would fail and return
NULL, the patched version makes a last effort to call `setlocale` using
the user's supplied parameters. The only exception where the function
will not make this last effort is when it fails under some specific
conditions when running in Windows.
I am not sure if this new behaviour will cause any surprises, but it
does fix the bug in my use case.
This is my first contribution, so I am not very familiar with the
development process here. I sincerely welcome any feedback or guidance.
Thank you!
Best wishes,
Dapeng
---
gettext-runtime/intl/setlocale.c | 122 +++++++++++++++++++--------------------
1 file changed, 59 insertions(+), 63 deletions(-)
diff --git a/gettext-runtime/intl/setlocale.c b/gettext-runtime/intl/setlocale.c
index df1991825..516c179e1 100644
--- a/gettext-runtime/intl/setlocale.c
+++ b/gettext-runtime/intl/setlocale.c
@@ -818,10 +818,16 @@ DLL_EXPORTED
char *
libintl_setlocale (int category, const char *locale)
{
- if (locale != NULL && locale[0] == '\0')
+ char *result = NULL;
+
+ if (locale == NULL)
+ goto fail;
+
+ if (category == LC_ALL)
{
- /* A request to the set the current locale to the default locale. */
- if (category == LC_ALL)
+ char *saved_locale;
+
+ if (locale[0] == '\0')
{
/* Set LC_CTYPE first. Then the other categories. */
static int const categories[] =
@@ -832,43 +838,41 @@ libintl_setlocale (int category, const char *locale)
LC_MONETARY,
LC_MESSAGES
};
- char *saved_locale;
- const char *base_name;
- unsigned int i;
/* Back up the old locale, in case one of the steps fails. */
saved_locale = setlocale (LC_ALL, NULL);
if (saved_locale == NULL)
- return NULL;
+ goto fail;
saved_locale = strdup (saved_locale);
if (saved_locale == NULL)
- return NULL;
+ goto fail;
/* Set LC_CTYPE category. Set all other categories (except possibly
LC_MESSAGES) to the same value in the same call; this is likely
to
save calls. */
- base_name =
+ const char *base_name =
gl_locale_name_environ (LC_CTYPE, category_to_name (LC_CTYPE));
if (base_name == NULL)
base_name = gl_locale_name_default ();
if (setlocale_unixlike (LC_ALL, base_name) == NULL)
- goto fail;
+ goto cleanup;
+
# if defined _WIN32 && ! defined __CYGWIN__
/* 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 (strchr (base_name, '.') != NULL
&& strcmp (setlocale (LC_CTYPE, NULL), "C") == 0)
- goto fail;
+ goto win32_restore;
# endif
- for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++)
+ for (size_t i = 0; i < sizeof (categories) / sizeof (categories[0]);
i++)
{
int cat = categories[i];
- const char *name;
- name = gl_locale_name_environ (cat, category_to_name (cat));
+ const char *name =
+ gl_locale_name_environ (cat, category_to_name (cat));
if (name == NULL)
name = gl_locale_name_default ();
@@ -880,80 +884,72 @@ libintl_setlocale (int category, const char *locale)
# endif
)
if (setlocale_single (cat, name) == NULL)
- goto fail;
+ goto restore;
}
/* All steps were successful. */
- ++_nl_msg_cat_cntr;
- free (saved_locale);
- return setlocale (LC_ALL, NULL);
-
- fail:
- if (saved_locale[0] != '\0') /* don't risk an endless recursion */
- setlocale (LC_ALL, saved_locale);
- free (saved_locale);
- return NULL;
+ result = setlocale (LC_ALL, NULL);
+ goto cleanup;
}
- else
- {
- char *result;
- const char *name =
- gl_locale_name_environ (category, category_to_name (category));
- if (name == NULL)
- name = gl_locale_name_default ();
-
- result = setlocale_single (category, name);
- if (result != NULL)
- ++_nl_msg_cat_cntr;
- return result;
- }
- }
- else
- {
# if defined _WIN32 && ! defined __CYGWIN__
- if (category == LC_ALL && locale != NULL && strchr (locale, '.') != NULL)
+ else if (strchr (locale, '.') != NULL)
{
- char *saved_locale;
-
/* Back up the old locale. */
saved_locale = setlocale (LC_ALL, NULL);
if (saved_locale == NULL)
- return NULL;
+ goto fail;
saved_locale = strdup (saved_locale);
if (saved_locale == NULL)
- return NULL;
+ goto fail;
if (setlocale_unixlike (LC_ALL, locale) == NULL)
- {
- free (saved_locale);
- return NULL;
- }
+ goto win32_cleanup;
/* 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 (saved_locale[0] != '\0') /* don't risk an endless recursion
*/
- setlocale (LC_ALL, saved_locale);
- free (saved_locale);
- return NULL;
- }
+ goto win32_restore;
/* It was really successful. */
- ++_nl_msg_cat_cntr;
- free (saved_locale);
- return setlocale (LC_ALL, NULL);
+ result = setlocale (LC_ALL, NULL);
+ goto cleanup;
}
- else
# endif
+ else
{
- char *result = setlocale_single (category, locale);
- if (result != NULL)
- ++_nl_msg_cat_cntr;
- return result;
+ goto fail;
}
+# if defined _WIN32 && ! defined __CYGWIN__
+ win32_restore:
+ if (saved_locale[0] != '\0') /* don't risk an endless recursion */
+ setlocale (LC_ALL, saved_locale);
+ win32_cleanup:
+ free (saved_locale);
+ return NULL;
+# endif
+ restore:
+ if (saved_locale[0] != '\0') /* don't risk an endless recursion */
+ setlocale (LC_ALL, saved_locale);
+ cleanup:
+ free (saved_locale);
}
+ else if (locale[0] == '\0')
+ {
+ const char *name =
+ gl_locale_name_environ (category, category_to_name (category));
+ if (name == NULL)
+ name = gl_locale_name_default ();
+
+ result = setlocale_single (category, name);
+ }
+
+fail:
+ if (result == NULL)
+ result = setlocale_single (category, locale);
+ if (result != NULL)
+ ++_nl_msg_cat_cntr;
+ return result;
}
# if HAVE_NEWLOCALE
--
2.15.1 (Apple Git-101)