This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
| Other format: | [Raw text] | |
Hi!
The following patch fixes a bunch of things.
Primarily, addition of __names[] array to __locale_struct broke binary
compatibility - programs using e.g. isdigit_l etc. suddenly give
broken results (including libstdc++-v3).
Second, at least tllocale.ps documents uselocale:
> The function returns the locale handle previously passed
> to uselocale() for the current thread. If there was no such call
> before the return value is LC_GLOBAL_LOCALE.
That's also consistent with setlocale behaviour (and libstdc++-v3 uses it).
But current uselocale only returns previous locale if called with
uselocale(NULL) and otherwise returns the argument which was passed to it.
That would mean
locale_t old = uselocale(new);
something
uselocale(old);
sequence would have to be rewritten as:
locale_t old = uselocale(NULL);
uselocale(new);
something
uselocale(old);
I really thing we should follow the paper in here.
Third thing is uselocale and gettext - although __names was introduced,
newlocale created locales would have all __names[X] set to _nl_C_name
and thus gettext would not work properly.
The fourth thing is newlocale/duplocale failure handling and on success
avoiding memory leaking.
2002-08-31 Jakub Jelinek <jakub@redhat.com>
* locale/newlocale.c: Include string.h.
(__newlocale): Fill in __names elements, free them on failure.
On failure call _nl_remove_locale when necessary.
Free old __names and all locale data if using base.
* locale/duplocale.c (__duplocale): Free newly strduped __names,
not members of dataset on failure.
* locale/uselocale.c (__uselocale): Always return previous locale_t,
not only when newloc is NULL.
* locale/xlocale.h (__struct locale_struct): Put __names last
for binary compatibility of inline is*_l and to*_l.
--- libc/locale/newlocale.c.jj 2002-08-12 15:27:48.000000000 +0200
+++ libc/locale/newlocale.c 2002-08-31 17:06:46.000000000 +0200
@@ -22,6 +22,7 @@
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
+#include <string.h>
#include "localeinfo.h"
@@ -148,7 +149,32 @@ __newlocale (int category_mask, const ch
result.__locales[cnt] = _nl_find_locale (locale_path, locale_path_len,
cnt, &newnames[cnt]);
if (result.__locales[cnt] == NULL)
- return NULL;
+ {
+ exit_free:
+ for (--cnt; cnt >= 0; --cnt)
+ if (cnt != LC_ALL && (category_mask & 1 << cnt) != 0)
+ {
+ if (result.__locales[cnt]->usage_count != UNDELETABLE)
+ /* We can remove the data. */
+ _nl_remove_locale (cnt, result.__locales[cnt]);
+ if (result.__names[cnt] != _nl_C_name)
+ free ((char *) result.__names[cnt]);
+ }
+ return NULL;
+ }
+ if (newnames[cnt] == _nl_C_name)
+ result.__names[cnt] = _nl_C_name;
+ else
+ {
+ result.__names[cnt] = __strdup (newnames[cnt]);
+ if (result.__names[cnt] == NULL)
+ {
+ if (result.__locales[cnt]->usage_count != UNDELETABLE)
+ /* We can remove the data. */
+ _nl_remove_locale (cnt, result.__locales[cnt]);
+ goto exit_free;
+ }
+ }
}
/* We successfully loaded all required data. */
@@ -157,12 +183,24 @@ __newlocale (int category_mask, const ch
/* Allocate new structure. */
result_ptr = (__locale_t) malloc (sizeof (struct __locale_struct));
if (result_ptr == NULL)
- return NULL;
-
+ goto exit_free;
}
else
- /* We modify the base structure. */
- result_ptr = base;
+ {
+ /* We modify the base structure. */
+ result_ptr = base;
+
+ /* Need to free the old names and old locale data. */
+ for (cnt = 0; cnt < __LC_LAST; ++cnt)
+ if (cnt != LC_ALL && (category_mask & 1 << cnt) != 0)
+ {
+ if (base->__locales[cnt]->usage_count != UNDELETABLE)
+ /* We can remove the data. */
+ _nl_remove_locale (cnt, base->__locales[cnt]);
+ if (base->__names[cnt] != _nl_C_name)
+ free ((char *) base->__names[cnt]);
+ }
+ }
*result_ptr = result;
--- libc/locale/duplocale.c.jj 2002-08-31 09:40:42.000000000 +0200
+++ libc/locale/duplocale.c 2002-08-31 17:06:46.000000000 +0200
@@ -55,9 +55,9 @@ __duplocale (__locale_t dataset)
result->__names[cnt] = __strdup (dataset->__names[cnt]);
if (result->__names[cnt] == NULL)
{
- while (cnt-- > 0)
- if (dataset->__names[cnt] != _nl_C_name)
- free ((char *) dataset->__names[cnt]);
+ while (--cnt >= 0)
+ if (result->__names[cnt] != _nl_C_name)
+ free ((char *) result->__names[cnt]);
free (result);
result = NULL;
break;
--- libc/locale/uselocale.c.jj 2002-08-28 12:58:05.000000000 +0200
+++ libc/locale/uselocale.c 2002-08-31 18:07:09.000000000 +0200
@@ -28,16 +28,16 @@
locale_t
__uselocale (locale_t newloc)
{
- if (newloc == NULL)
- {
- locale_t loc = __libc_tsd_get (LOCALE);
- return loc == &_nl_global_locale ? LC_GLOBAL_LOCALE : loc;
- }
- else
+ locale_t oldloc = __libc_tsd_get (LOCALE);
+
+ if (oldloc == &_nl_global_locale)
+ oldloc = LC_GLOBAL_LOCALE;
+
+ if (newloc != NULL)
{
- const locale_t locobj
- = newloc == LC_GLOBAL_LOCALE ? &_nl_global_locale : newloc;
- __libc_tsd_set (LOCALE, locobj);
+ if (newloc == LC_GLOBAL_LOCALE)
+ newloc = &_nl_global_locale;
+ __libc_tsd_set (LOCALE, newloc);
#ifdef NL_CURRENT_INDIRECT
/* Now we must update all the per-category thread-local variables to
@@ -58,13 +58,13 @@ __uselocale (locale_t newloc)
weak_extern (_nl_current_##category##_used) \
weak_extern (_nl_current_##category) \
if (&_nl_current_##category##_used != 0) \
- _nl_current_##category = &locobj->__locales[category]; \
+ _nl_current_##category = &newloc->__locales[category]; \
}
# include "categories.def"
# undef DEFINE_CATEGORY
#endif
}
- return newloc;
+ return oldloc;
}
weak_alias (__uselocale, uselocale)
--- libc/locale/xlocale.h.jj 2002-08-31 09:40:42.000000000 +0200
+++ libc/locale/xlocale.h 2002-08-31 19:40:35.000000000 +0200
@@ -29,12 +29,14 @@ typedef struct __locale_struct
{
/* Note: LC_ALL is not a valid index into this array. */
struct locale_data *__locales[13]; /* 13 = __LC_LAST. */
- const char *__names[13];
/* To increase the speed of this solution we add some special members. */
const unsigned short int *__ctype_b;
const int *__ctype_tolower;
const int *__ctype_toupper;
+
+ /* Note: LC_ALL is not a valid index into this array. */
+ const char *__names[13]; /* 13 = __LC_LAST. */
} *__locale_t;
#endif /* xlocale.h */
Jakub
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |