diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2010-04-01 20:13:22 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2010-04-01 20:13:22 +0000 |
commit | 57f7ebe1f28f9965339be8b27db2a80a6a9a4671 (patch) | |
tree | 330a385548aa4d875e55c08107d5d02051599e22 /winsup/cygwin/nlsfuncs.cc | |
parent | c1bfa897da72bb555650e021e90b1b929a66d69c (diff) | |
download | cygnal-57f7ebe1f28f9965339be8b27db2a80a6a9a4671.tar.gz cygnal-57f7ebe1f28f9965339be8b27db2a80a6a9a4671.tar.bz2 cygnal-57f7ebe1f28f9965339be8b27db2a80a6a9a4671.zip |
* nlsfuncs.cc (rebase_locale_buf): New helper function to rebase
function pointers in locale structures. Explain why this is necessary.
(__set_lc_time_from_win): Use rebase_locale_buf after realloc.
(__set_lc_numeric_from_win): Ditto.
(__set_lc_monetary_from_win): Ditto.
Diffstat (limited to 'winsup/cygwin/nlsfuncs.cc')
-rw-r--r-- | winsup/cygwin/nlsfuncs.cc | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc index 3f2279a18..ddf6d14da 100644 --- a/winsup/cygwin/nlsfuncs.cc +++ b/winsup/cygwin/nlsfuncs.cc @@ -325,6 +325,21 @@ locale_cmp (const void *a, const void *b) return strcmp (*la, *lb); } +/* Helper function to workaround reallocs which move blocks even if they shrink. + Cygwin's realloc is not doing this, but tcsh's, for instance. All lc_foo + structures consist entirely of pointers so they are practically pointer + arrays. What we do here is just treat the lc_foo pointers as char ** and + rebase all char * pointers within, up to the given size of the structure. */ +static void +rebase_locale_buf (const void *ptrv, const char *newbase, const char *oldbase, + const void *ptrvend) +{ + const char **ptrs = (const char **) ptrv; + const char **ptrsend = (const char **) ptrvend; + while (ptrs < ptrsend) + *ptrs++ += newbase - oldbase; +} + static char * __getlocaleinfo (LCID lcid, LCTYPE type, char **ptr, size_t size, wctomb_p f_wctomb, const char *charset) @@ -625,6 +640,9 @@ __set_lc_time_from_win (const char *name, struct lc_time_T *_time_locale, era = NULL; else { + if (tmp != new_lc_time_buf) + rebase_locale_buf (_time_locale, tmp, new_lc_time_buf, + _time_locale + 1); lc_time_ptr = tmp + (lc_time_ptr - new_lc_time_buf); new_lc_time_buf = tmp; lc_time_end = new_lc_time_buf + len; @@ -674,6 +692,9 @@ __set_lc_time_from_win (const char *name, struct lc_time_T *_time_locale, free (new_lc_time_buf); return -1; } + if (tmp != new_lc_time_buf) + rebase_locale_buf (_time_locale, tmp, new_lc_time_buf, + _time_locale + 1); if (*lc_time_buf) free (*lc_time_buf); *lc_time_buf = tmp; @@ -717,6 +738,9 @@ __set_lc_numeric_from_win (const char *name, free (new_lc_numeric_buf); return -1; } + if (tmp != new_lc_numeric_buf) + rebase_locale_buf (_numeric_locale, tmp, new_lc_numeric_buf, + _numeric_locale + 1); if (*lc_numeric_buf) free (*lc_numeric_buf); *lc_numeric_buf = tmp; @@ -816,6 +840,9 @@ __set_lc_monetary_from_win (const char *name, free (new_lc_monetary_buf); return -1; } + if (tmp != new_lc_monetary_buf) + rebase_locale_buf (_monetary_locale, tmp, new_lc_monetary_buf, + _monetary_locale + 1); if (*lc_monetary_buf) free (*lc_monetary_buf); *lc_monetary_buf = tmp; |