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] |