1 --- rpm-4.4.7/rpmio/strtolocale.c.orig 2005-10-28 04:53:34.000000000 +0200
2 +++ rpm-4.4.7/rpmio/strtolocale.c 2007-02-12 19:16:36.000000000 +0100
12 -/*@access mbstate_t @*/
15 - * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
16 - * @param p memory to free
17 - * @retval NULL always
19 -/*@unused@*/ static inline /*@null@*/ void *
20 -_free(/*@only@*/ /*@null@*/ const void * p) /*@modifies p@*/
22 - if (p != NULL) free((void *)p);
25 +static char *locale_encoding = NULL;
26 +static int locale_encoding_is_utf8;
28 const char * xstrtolocale(const char *str)
31 - const unsigned char *cp;
35 - int ccl, cca, mb_cur_max;
45 - wstr = (wchar_t *)xmalloc((strlen(str) + 1) * sizeof(*wstr));
47 - cp = (const unsigned char *)str;
48 - while ((c = *cp++) != 0) {
50 - if ((c & 0xc0) != 0x80) {
51 - /* encoding error */
54 - c = (c & 0x3f) | (state << 6);
55 - if (!(state & 0x40000000)) {
56 - /* check for overlong sequences */
57 - if ((c & 0x820823e0) == 0x80000000)
59 - else if ((c & 0x020821f0) == 0x02000000)
61 - else if ((c & 0x000820f8) == 0x00080000)
63 - else if ((c & 0x0000207c) == 0x00002000)
71 - c = (c & 0x01) | 0xbffffffc; /* 5 bytes to follow */
73 - c = (c & 0x03) | 0xbfffff00; /* 4 */
75 - c = (c & 0x07) | 0xbfffc000; /* 3 */
77 - c = (c & 0x0f) | 0xbff00000; /* 2 */
79 - c = (c & 0x1f) | 0xfc000000; /* 1 */
81 - c = 0xfdffffff; /* overlong */
85 - state = (c & 0x80000000) ? c : 0;
92 - /* encoding error, assume latin1 */
94 - cp = (const unsigned char *)str;
96 - while ((c = *cp++) != 0) {
100 + size_t src_size, dest_size;
101 + char *result, *src, *dest;
103 + if (locale_encoding == NULL) {
104 + const char *encoding = nl_langinfo(CODESET);
105 + locale_encoding = xmalloc(strlen(encoding) + 11);
106 + sprintf(locale_encoding, "%s//TRANSLIT", encoding);
107 + locale_encoding_is_utf8 = strcasecmp(encoding, "UTF-8") == 0;
111 - mb_cur_max = MB_CUR_MAX;
112 - memset(&ps, 0, sizeof(ps));
113 - cc = xmalloc(mb_cur_max);
114 - /* test locale encoding */
115 - if (wcrtomb(cc, 0x20ac, &ps) != 3 || memcmp(cc, "\342\202\254", 3))
117 - if (locisutf8 == strisutf8) {
118 - wstr = _free(wstr);
120 + if (!str || !*str || locale_encoding_is_utf8)
123 + cd = iconv_open(locale_encoding, "UTF-8");
124 + if (cd == (iconv_t)-1)
127 + src_size = strlen(str);
128 + dest_size = src_size + 1;
129 + result = xmalloc(dest_size);
133 + size_t status = iconv(cd, &src, &src_size, &dest, &dest_size);
134 + if (status == (size_t)-1) {
135 + size_t dest_offset;
136 + if (errno != E2BIG) {
141 + dest_offset = dest - result;
143 + result = xrealloc(result, dest_offset + dest_size);
144 + dest = result + dest_offset;
145 + } else if (src_size == 0) {
146 + if (src == NULL) break;
151 - memset(&ps, 0, sizeof(ps));
153 - for (wp = wstr; ; wp++) {
154 - l = wcrtomb(cc + ccl, *wp, &ps);
157 - if (l == (size_t)-1) {
158 - if (*wp < (wchar_t)256 && mbsinit(&ps)) {
162 - l = wcrtomb(cc + ccl, (wchar_t)'?', &ps);
164 - if (l == 0 || l == (size_t)-1)
169 - cc = xrealloc(cc, cca + mb_cur_max);
173 + if (dest_size == 0) {
174 + size_t dest_offset = dest - result;
175 + result = xrealloc(result, dest_offset + 1);
176 + dest = result + dest_offset;
178 - wstr = _free(wstr);
179 - return (const char *)cc;