| @@ -1,430 +1,441 @@ | | | @@ -1,430 +1,441 @@ |
1 | /* $NetBSD: conv.c,v 1.2 2013/11/22 15:52:05 christos Exp $ */ | | 1 | /* $NetBSD: conv.c,v 1.3 2014/01/07 21:46:47 christos Exp $ */ |
2 | /*- | | 2 | /*- |
3 | * Copyright (c) 1993, 1994 | | 3 | * Copyright (c) 1993, 1994 |
4 | * The Regents of the University of California. All rights reserved. | | 4 | * The Regents of the University of California. All rights reserved. |
5 | * Copyright (c) 1993, 1994, 1995, 1996 | | 5 | * Copyright (c) 1993, 1994, 1995, 1996 |
6 | * Keith Bostic. All rights reserved. | | 6 | * Keith Bostic. All rights reserved. |
7 | * | | 7 | * |
8 | * See the LICENSE file for redistribution information. | | 8 | * See the LICENSE file for redistribution information. |
9 | */ | | 9 | */ |
10 | | | 10 | |
11 | #include "config.h" | | 11 | #include "config.h" |
12 | | | 12 | |
13 | #ifndef lint | | 13 | #ifndef lint |
14 | static const char sccsid[] = "Id: conv.c,v 1.27 2001/08/18 21:41:41 skimo Exp (Berkeley) Date: 2001/08/18 21:41:41 "; | | 14 | static const char sccsid[] = "Id: conv.c,v 1.27 2001/08/18 21:41:41 skimo Exp (Berkeley) Date: 2001/08/18 21:41:41 "; |
15 | #endif /* not lint */ | | 15 | #endif /* not lint */ |
16 | | | 16 | |
17 | #include <sys/types.h> | | 17 | #include <sys/types.h> |
18 | #include <sys/queue.h> | | 18 | #include <sys/queue.h> |
19 | #include <sys/time.h> | | 19 | #include <sys/time.h> |
20 | | | 20 | |
21 | #include <bitstring.h> | | 21 | #include <bitstring.h> |
22 | #include <errno.h> | | 22 | #include <errno.h> |
23 | #include <limits.h> | | 23 | #include <limits.h> |
24 | #include <stdio.h> | | 24 | #include <stdio.h> |
25 | #include <stdlib.h> | | 25 | #include <stdlib.h> |
26 | #include <string.h> | | 26 | #include <string.h> |
27 | #include <unistd.h> | | 27 | #include <unistd.h> |
28 | | | 28 | |
29 | #include "common.h" | | 29 | #include "common.h" |
30 | | | 30 | |
31 | #ifdef USE_ICONV | | 31 | #ifdef USE_ICONV |
32 | #include <langinfo.h> | | 32 | #include <langinfo.h> |
33 | #include <iconv.h> | | 33 | #include <iconv.h> |
34 | | | 34 | |
35 | #define LANGCODESET nl_langinfo(CODESET) | | 35 | #define LANGCODESET nl_langinfo(CODESET) |
36 | #else | | 36 | #else |
37 | typedef int iconv_t; | | 37 | typedef int iconv_t; |
38 | | | 38 | |
39 | #define LANGCODESET "" | | 39 | #define LANGCODESET "" |
40 | #endif | | 40 | #endif |
41 | | | 41 | |
42 | #include <locale.h> | | 42 | #include <locale.h> |
43 | | | 43 | |
44 | #ifdef USE_WIDECHAR | | 44 | #ifdef USE_WIDECHAR |
45 | static int | | 45 | static int |
46 | raw2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, size_t *tolen, | | 46 | raw2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, size_t *tolen, |
47 | const CHAR_T **dst) | | 47 | const CHAR_T **dst) |
48 | { | | 48 | { |
49 | int i; | | 49 | int i; |
50 | CHAR_T **tostr = (CHAR_T **)(void *)&cw->bp1; | | 50 | CHAR_T **tostr = (CHAR_T **)(void *)&cw->bp1; |
51 | size_t *blen = &cw->blen1; | | 51 | size_t *blen = &cw->blen1; |
52 | | | 52 | |
53 | BINC_RETW(NULL, *tostr, *blen, len); | | 53 | BINC_RETW(NULL, *tostr, *blen, len); |
54 | | | 54 | |
55 | *tolen = len; | | 55 | *tolen = len; |
56 | for (i = 0; i < len; ++i) | | 56 | for (i = 0; i < len; ++i) { |
57 | (*tostr)[i] = (u_char) str[i]; | | 57 | CHAR_T w = (u_char)str[i]; |
| | | 58 | memcpy((*tostr) + i, &w, sizeof(**tostr)); |
| | | 59 | } |
58 | | | 60 | |
59 | *dst = cw->bp1; | | 61 | *dst = cw->bp1; |
60 | | | 62 | |
61 | return 0; | | 63 | return 0; |
62 | } | | 64 | } |
63 | | | 65 | |
64 | #ifndef ERROR_ON_CONVERT | | 66 | #ifndef ERROR_ON_CONVERT |
65 | #define HANDLE_ICONV_ERROR(o, i, ol, il) do { \ | | 67 | #define HANDLE_ICONV_ERROR(o, i, ol, il) do { \ |
66 | *o++ = *i++; \ | | 68 | *o++ = *i++; \ |
67 | ol--; il--; \ | | 69 | ol--; il--; \ |
68 | } while (/*CONSTCOND*/0) | | 70 | } while (/*CONSTCOND*/0) |
69 | #define HANDLE_MBR_ERROR(n, mbs, d, s) do { \ | | 71 | #define HANDLE_MBR_ERROR(n, mbs, d, s) do { \ |
70 | d = s; \ | | 72 | d = s; \ |
71 | MEMSET(&mbs, 0, 1); \ | | 73 | MEMSET(&mbs, 0, 1); \ |
72 | n = 1; \ | | 74 | n = 1; \ |
73 | } while (/*CONSTCOND*/0) | | 75 | } while (/*CONSTCOND*/0) |
74 | #else | | 76 | #else |
75 | #define HANDLE_ICONV_ERROR goto err | | 77 | #define HANDLE_ICONV_ERROR goto err |
76 | #define HANDLE_MBR_ERROR goto err | | 78 | #define HANDLE_MBR_ERROR goto err |
77 | #endif | | 79 | #endif |
78 | | | 80 | |
79 | #define CONV_BUFFER_SIZE 512 | | 81 | #define CONV_BUFFER_SIZE 512 |
80 | /* fill the buffer with codeset encoding of string pointed to by str | | 82 | /* fill the buffer with codeset encoding of string pointed to by str |
81 | * left has the number of bytes left in str and is adjusted | | 83 | * left has the number of bytes left in str and is adjusted |
82 | * len contains the number of bytes put in the buffer | | 84 | * len contains the number of bytes put in the buffer |
83 | */ | | 85 | */ |
84 | #ifdef USE_ICONV | | 86 | #ifdef USE_ICONV |
85 | #define CONVERT(str, left, src, len) \ | | 87 | #define CONVERT(str, left, src, len) \ |
86 | do { \ | | 88 | do { \ |
87 | size_t outleft; \ | | 89 | size_t outleft; \ |
88 | char *bp = buffer; \ | | 90 | char *bp = buffer; \ |
89 | outleft = CONV_BUFFER_SIZE; \ | | 91 | outleft = CONV_BUFFER_SIZE; \ |
90 | errno = 0; \ | | 92 | errno = 0; \ |
91 | if (iconv(id, (const char **)&str, &left, &bp, &outleft) \ | | 93 | if (iconv(id, (const char **)&str, &left, &bp, &outleft) \ |
92 | == (size_t)-1 /* && errno != E2BIG */) \ | | 94 | == (size_t)-1 /* && errno != E2BIG */) \ |
93 | HANDLE_ICONV_ERROR(bp, str, outleft, left); \ | | 95 | HANDLE_ICONV_ERROR(bp, str, outleft, left); \ |
94 | if ((len = CONV_BUFFER_SIZE - outleft) == 0) { \ | | 96 | if ((len = CONV_BUFFER_SIZE - outleft) == 0) { \ |
95 | error = -left; \ | | 97 | error = -left; \ |
96 | goto err; \ | | 98 | goto err; \ |
97 | } \ | | 99 | } \ |
98 | src = buffer; \ | | 100 | src = buffer; \ |
99 | } while (0) | | 101 | } while (0) |
100 | #else | | 102 | #else |
101 | #define CONVERT(str, left, src, len) | | 103 | #define CONVERT(str, left, src, len) |
102 | #endif | | 104 | #endif |
103 | | | 105 | |
104 | static int | | 106 | static int |
105 | default_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, | | 107 | default_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, |
106 | size_t *tolen, const CHAR_T **dst, const char *enc) | | 108 | size_t *tolen, const CHAR_T **dst, const char *enc) |
107 | { | | 109 | { |
108 | int j; | | 110 | int j; |
109 | size_t i = 0; | | 111 | size_t i = 0; |
110 | CHAR_T **tostr = (CHAR_T **)(void *)&cw->bp1; | | 112 | CHAR_T **tostr = (CHAR_T **)(void *)&cw->bp1; |
111 | size_t *blen = &cw->blen1; | | 113 | size_t *blen = &cw->blen1; |
112 | mbstate_t mbs; | | 114 | mbstate_t mbs; |
113 | size_t n; | | 115 | size_t n; |
114 | ssize_t nlen = len; | | 116 | ssize_t nlen = len; |
115 | const char *src = (const char *)str; | | 117 | const char *src = (const char *)str; |
116 | iconv_t id = (iconv_t)-1; | | 118 | iconv_t id = (iconv_t)-1; |
117 | char buffer[CONV_BUFFER_SIZE]; | | 119 | char buffer[CONV_BUFFER_SIZE]; |
118 | size_t left = len; | | 120 | size_t left = len; |
119 | int error = 1; | | 121 | int error = 1; |
120 | | | 122 | |
121 | MEMSET(&mbs, 0, 1); | | 123 | MEMSET(&mbs, 0, 1); |
122 | BINC_RETW(NULL, *tostr, *blen, nlen); | | 124 | BINC_RETW(NULL, *tostr, *blen, nlen); |
123 | | | 125 | |
124 | #ifdef USE_ICONV | | 126 | #ifdef USE_ICONV |
125 | if (strcmp(nl_langinfo(CODESET), enc)) { | | 127 | if (strcmp(nl_langinfo(CODESET), enc)) { |
126 | id = iconv_open(nl_langinfo(CODESET), enc); | | 128 | id = iconv_open(nl_langinfo(CODESET), enc); |
127 | if (id == (iconv_t)-1) | | 129 | if (id == (iconv_t)-1) |
128 | goto err; | | 130 | goto err; |
129 | CONVERT(str, left, src, len); | | 131 | CONVERT(str, left, src, len); |
130 | } | | 132 | } |
131 | #endif | | 133 | #endif |
132 | | | 134 | |
133 | for (i = 0, j = 0; j < len; ) { | | 135 | for (i = 0, j = 0; j < len; ) { |
134 | n = mbrtowc((*tostr)+i, src+j, len-j, &mbs); | | 136 | CHAR_T w; |
| | | 137 | n = mbrtowc(&w, src + j, len - j, &mbs); |
| | | 138 | memcpy((*tostr) + i, &w, sizeof(**tostr)); |
135 | /* NULL character converted */ | | 139 | /* NULL character converted */ |
136 | if (n == (size_t)-2) error = -(len-j); | | 140 | if (n == (size_t)-2) error = -(len - j); |
137 | if (n == (size_t)-1 || n == (size_t)-2) | | 141 | if (n == (size_t)-1 || n == (size_t)-2) { |
138 | HANDLE_MBR_ERROR(n, mbs, (*tostr)[i], src[j]); | | 142 | HANDLE_MBR_ERROR(n, mbs, w, src[j]); |
| | | 143 | memcpy((*tostr) + i, &w, sizeof(**tostr)); |
| | | 144 | } |
139 | if (n == 0) n = 1; | | 145 | if (n == 0) n = 1; |
140 | j += n; | | 146 | j += n; |
141 | if (++i >= *blen) { | | 147 | if (++i >= *blen) { |
142 | nlen += 256; | | 148 | nlen += 256; |
143 | BINC_RETW(NULL, *tostr, *blen, nlen); | | 149 | BINC_RETW(NULL, *tostr, *blen, nlen); |
144 | } | | 150 | } |
145 | if (id != (iconv_t)-1 && j == len && left) { | | 151 | if (id != (iconv_t)-1 && j == len && left) { |
146 | CONVERT(str, left, src, len); | | 152 | CONVERT(str, left, src, len); |
147 | j = 0; | | 153 | j = 0; |
148 | } | | 154 | } |
149 | } | | 155 | } |
150 | *tolen = i; | | 156 | *tolen = i; |
151 | | | 157 | |
152 | if (id != (iconv_t)-1) | | 158 | if (id != (iconv_t)-1) |
153 | iconv_close(id); | | 159 | iconv_close(id); |
154 | | | 160 | |
155 | *dst = cw->bp1; | | 161 | *dst = cw->bp1; |
156 | | | 162 | |
157 | return 0; | | 163 | return 0; |
158 | err: | | 164 | err: |
159 | *tolen = i; | | 165 | *tolen = i; |
160 | if (id != (iconv_t)-1) | | 166 | if (id != (iconv_t)-1) |
161 | iconv_close(id); | | 167 | iconv_close(id); |
162 | *dst = cw->bp1; | | 168 | *dst = cw->bp1; |
163 | | | 169 | |
164 | return error; | | 170 | return error; |
165 | } | | 171 | } |
166 | | | 172 | |
167 | static int | | 173 | static int |
168 | fe_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, | | 174 | fe_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, |
169 | size_t *tolen, const CHAR_T **dst) | | 175 | size_t *tolen, const CHAR_T **dst) |
170 | { | | 176 | { |
171 | return default_char2int(sp, str, len, cw, tolen, dst, O_STR(sp, O_FILEENCODING)); | | 177 | return default_char2int(sp, str, len, cw, tolen, dst, O_STR(sp, O_FILEENCODING)); |
172 | } | | 178 | } |
173 | | | 179 | |
174 | static int | | 180 | static int |
175 | ie_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, | | 181 | ie_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, |
176 | size_t *tolen, const CHAR_T **dst) | | 182 | size_t *tolen, const CHAR_T **dst) |
177 | { | | 183 | { |
178 | return default_char2int(sp, str, len, cw, tolen, dst, O_STR(sp, O_INPUTENCODING)); | | 184 | return default_char2int(sp, str, len, cw, tolen, dst, O_STR(sp, O_INPUTENCODING)); |
179 | } | | 185 | } |
180 | | | 186 | |
181 | static int | | 187 | static int |
182 | cs_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, | | 188 | cs_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, |
183 | size_t *tolen, const CHAR_T **dst) | | 189 | size_t *tolen, const CHAR_T **dst) |
184 | { | | 190 | { |
185 | return default_char2int(sp, str, len, cw, tolen, dst, LANGCODESET); | | 191 | return default_char2int(sp, str, len, cw, tolen, dst, LANGCODESET); |
186 | } | | 192 | } |
187 | | | 193 | |
188 | static int | | 194 | static int |
189 | CHAR_T_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, | | 195 | CHAR_T_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, |
190 | size_t *tolen, const char **dst) | | 196 | size_t *tolen, const char **dst) |
191 | { | | 197 | { |
192 | *tolen = len * sizeof(CHAR_T); | | 198 | *tolen = len * sizeof(CHAR_T); |
193 | *dst = (const char *)(const void *)str; | | 199 | *dst = (const char *)(const void *)str; |
194 | | | 200 | |
195 | return 0; | | 201 | return 0; |
196 | } | | 202 | } |
197 | | | 203 | |
198 | static int | | 204 | static int |
199 | CHAR_T_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, | | 205 | CHAR_T_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, |
200 | size_t *tolen, const CHAR_T **dst) | | 206 | size_t *tolen, const CHAR_T **dst) |
201 | { | | 207 | { |
202 | *tolen = len / sizeof(CHAR_T); | | 208 | *tolen = len / sizeof(CHAR_T); |
203 | *dst = (const CHAR_T*) str; | | 209 | *dst = (const CHAR_T*) str; |
204 | | | 210 | |
205 | return 0; | | 211 | return 0; |
206 | } | | 212 | } |
207 | | | 213 | |
208 | static int | | 214 | static int |
209 | int2raw(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, size_t *tolen, | | 215 | int2raw(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, size_t *tolen, |
210 | const char **dst) | | 216 | const char **dst) |
211 | { | | 217 | { |
212 | int i; | | 218 | int i; |
213 | char **tostr = (char **)(void *)&cw->bp1; | | 219 | char **tostr = (char **)(void *)&cw->bp1; |
214 | size_t *blen = &cw->blen1; | | 220 | size_t *blen = &cw->blen1; |
215 | | | 221 | |
216 | BINC_RETC(NULL, *tostr, *blen, len); | | 222 | BINC_RETC(NULL, *tostr, *blen, len); |
217 | | | 223 | |
218 | *tolen = len; | | 224 | *tolen = len; |
219 | for (i = 0; i < len; ++i) | | 225 | for (i = 0; i < len; ++i) { |
220 | (*tostr)[i] = str[i]; | | 226 | CHAR_T w; |
| | | 227 | memcpy(&w, str + i, sizeof(w)); |
| | | 228 | (*tostr)[i] = w; |
| | | 229 | } |
221 | | | 230 | |
222 | *dst = cw->bp1; | | 231 | *dst = cw->bp1; |
223 | | | 232 | |
224 | return 0; | | 233 | return 0; |
225 | } | | 234 | } |
226 | | | 235 | |
227 | static int | | 236 | static int |
228 | default_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, | | 237 | default_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, |
229 | size_t *tolen, const char **pdst, const char *enc) | | 238 | size_t *tolen, const char **pdst, const char *enc) |
230 | { | | 239 | { |
231 | size_t i, j; | | 240 | size_t i, j; |
232 | int offset = 0; | | 241 | int offset = 0; |
233 | char **tostr = (char **)(void *)&cw->bp1; | | 242 | char **tostr = (char **)(void *)&cw->bp1; |
234 | size_t *blen = &cw->blen1; | | 243 | size_t *blen = &cw->blen1; |
235 | mbstate_t mbs; | | 244 | mbstate_t mbs; |
236 | size_t n; | | 245 | size_t n; |
237 | ssize_t nlen = len + MB_CUR_MAX; | | 246 | ssize_t nlen = len + MB_CUR_MAX; |
238 | char *dst; | | 247 | char *dst; |
239 | size_t buflen; | | 248 | size_t buflen; |
240 | char buffer[CONV_BUFFER_SIZE]; | | 249 | char buffer[CONV_BUFFER_SIZE]; |
241 | iconv_t id = (iconv_t)-1; | | 250 | iconv_t id = (iconv_t)-1; |
242 | | | 251 | |
243 | /* convert first len bytes of buffer and append it to cw->bp | | 252 | /* convert first len bytes of buffer and append it to cw->bp |
244 | * len is adjusted => 0 | | 253 | * len is adjusted => 0 |
245 | * offset contains the offset in cw->bp and is adjusted | | 254 | * offset contains the offset in cw->bp and is adjusted |
246 | * cw->bp is grown as required | | 255 | * cw->bp is grown as required |
247 | */ | | 256 | */ |
248 | #ifdef USE_ICONV | | 257 | #ifdef USE_ICONV |
249 | #define CONVERT2(len, cw, offset) \ | | 258 | #define CONVERT2(len, cw, offset) \ |
250 | do { \ | | 259 | do { \ |
251 | const char *bp = buffer; \ | | 260 | const char *bp = buffer; \ |
252 | while (len != 0) { \ | | 261 | while (len != 0) { \ |
253 | size_t outleft = cw->blen1 - offset; \ | | 262 | size_t outleft = cw->blen1 - offset; \ |
254 | char *obp = (char *)cw->bp1 + offset; \ | | 263 | char *obp = (char *)cw->bp1 + offset; \ |
255 | if (cw->blen1 < offset + MB_CUR_MAX) { \ | | 264 | if (cw->blen1 < offset + MB_CUR_MAX) { \ |
256 | nlen += 256; \ | | 265 | nlen += 256; \ |
257 | BINC_RETC(NULL, cw->bp1, cw->blen1, nlen); \ | | 266 | BINC_RETC(NULL, cw->bp1, cw->blen1, nlen); \ |
258 | } \ | | 267 | } \ |
259 | errno = 0; \ | | 268 | errno = 0; \ |
260 | if (iconv(id, &bp, &len, &obp, &outleft) == (size_t)-1 && \ | | 269 | if (iconv(id, &bp, &len, &obp, &outleft) == (size_t)-1 && \ |
261 | errno != E2BIG) \ | | 270 | errno != E2BIG) \ |
262 | HANDLE_ICONV_ERROR(obp, bp, outleft, len); \ | | 271 | HANDLE_ICONV_ERROR(obp, bp, outleft, len); \ |
263 | offset = cw->blen1 - outleft; \ | | 272 | offset = cw->blen1 - outleft; \ |
264 | } \ | | 273 | } \ |
265 | } while (0) | | 274 | } while (0) |
266 | #else | | 275 | #else |
267 | #define CONVERT2(len, cw, offset) | | 276 | #define CONVERT2(len, cw, offset) |
268 | #endif | | 277 | #endif |
269 | | | 278 | |
270 | | | 279 | |
271 | MEMSET(&mbs, 0, 1); | | 280 | MEMSET(&mbs, 0, 1); |
272 | BINC_RETC(NULL, *tostr, *blen, nlen); | | 281 | BINC_RETC(NULL, *tostr, *blen, nlen); |
273 | dst = *tostr; buflen = *blen; | | 282 | dst = *tostr; buflen = *blen; |
274 | | | 283 | |
275 | #ifdef USE_ICONV | | 284 | #ifdef USE_ICONV |
276 | if (strcmp(nl_langinfo(CODESET), enc)) { | | 285 | if (strcmp(nl_langinfo(CODESET), enc)) { |
277 | id = iconv_open(enc, nl_langinfo(CODESET)); | | 286 | id = iconv_open(enc, nl_langinfo(CODESET)); |
278 | if (id == (iconv_t)-1) | | 287 | if (id == (iconv_t)-1) |
279 | goto err; | | 288 | goto err; |
280 | dst = buffer; buflen = CONV_BUFFER_SIZE; | | 289 | dst = buffer; buflen = CONV_BUFFER_SIZE; |
281 | } | | 290 | } |
282 | #endif | | 291 | #endif |
283 | | | 292 | |
284 | for (i = 0, j = 0; i < (size_t)len; ++i) { | | 293 | for (i = 0, j = 0; i < (size_t)len; ++i) { |
285 | n = wcrtomb(dst+j, str[i], &mbs); | | 294 | CHAR_T w; |
| | | 295 | memcpy(&w, str + i, sizeof(w)); |
| | | 296 | n = wcrtomb(dst + j, w, &mbs); |
286 | if (n == (size_t)-1) | | 297 | if (n == (size_t)-1) |
287 | HANDLE_MBR_ERROR(n, mbs, dst[j], str[i]); | | 298 | HANDLE_MBR_ERROR(n, mbs, dst[j], w); |
288 | j += n; | | 299 | j += n; |
289 | if (buflen < j + MB_CUR_MAX) { | | 300 | if (buflen < j + MB_CUR_MAX) { |
290 | if (id != (iconv_t)-1) { | | 301 | if (id != (iconv_t)-1) { |
291 | CONVERT2(j, cw, offset); | | 302 | CONVERT2(j, cw, offset); |
292 | } else { | | 303 | } else { |
293 | nlen += 256; | | 304 | nlen += 256; |
294 | BINC_RETC(NULL, *tostr, *blen, nlen); | | 305 | BINC_RETC(NULL, *tostr, *blen, nlen); |
295 | dst = *tostr; buflen = *blen; | | 306 | dst = *tostr; buflen = *blen; |
296 | } | | 307 | } |
297 | } | | 308 | } |
298 | } | | 309 | } |
299 | | | 310 | |
300 | n = wcrtomb(dst+j, L'\0', &mbs); | | 311 | n = wcrtomb(dst + j, L'\0', &mbs); |
301 | j += n - 1; /* don't count NUL at the end */ | | 312 | j += n - 1; /* don't count NUL at the end */ |
302 | *tolen = j; | | 313 | *tolen = j; |
303 | | | 314 | |
304 | if (id != (iconv_t)-1) { | | 315 | if (id != (iconv_t)-1) { |
305 | CONVERT2(j, cw, offset); | | 316 | CONVERT2(j, cw, offset); |
306 | *tolen = offset; | | 317 | *tolen = offset; |
307 | } | | 318 | } |
308 | | | 319 | |
309 | *pdst = cw->bp1; | | 320 | *pdst = cw->bp1; |
310 | | | 321 | |
311 | return 0; | | 322 | return 0; |
312 | err: | | 323 | err: |
313 | *tolen = j; | | 324 | *tolen = j; |
314 | | | 325 | |
315 | *pdst = cw->bp1; | | 326 | *pdst = cw->bp1; |
316 | | | 327 | |
317 | return 1; | | 328 | return 1; |
318 | } | | 329 | } |
319 | | | 330 | |
320 | static int | | 331 | static int |
321 | fe_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, | | 332 | fe_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, |
322 | size_t *tolen, const char **dst) | | 333 | size_t *tolen, const char **dst) |
323 | { | | 334 | { |
324 | return default_int2char(sp, str, len, cw, tolen, dst, O_STR(sp, O_FILEENCODING)); | | 335 | return default_int2char(sp, str, len, cw, tolen, dst, O_STR(sp, O_FILEENCODING)); |
325 | } | | 336 | } |
326 | | | 337 | |
327 | static int | | 338 | static int |
328 | cs_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, | | 339 | cs_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, |
329 | size_t *tolen, const char **dst) | | 340 | size_t *tolen, const char **dst) |
330 | { | | 341 | { |
331 | return default_int2char(sp, str, len, cw, tolen, dst, LANGCODESET); | | 342 | return default_int2char(sp, str, len, cw, tolen, dst, LANGCODESET); |
332 | } | | 343 | } |
333 | | | 344 | |
334 | #endif | | 345 | #endif |
335 | | | 346 | |
336 | | | 347 | |
337 | void | | 348 | void |
338 | conv_init (SCR *orig, SCR *sp) | | 349 | conv_init (SCR *orig, SCR *sp) |
339 | { | | 350 | { |
340 | if (orig != NULL) | | 351 | if (orig != NULL) |
341 | MEMCPY(&sp->conv, &orig->conv, 1); | | 352 | MEMCPY(&sp->conv, &orig->conv, 1); |
342 | else { | | 353 | else { |
343 | setlocale(LC_ALL, ""); | | 354 | setlocale(LC_ALL, ""); |
344 | #ifdef USE_WIDECHAR | | 355 | #ifdef USE_WIDECHAR |
345 | sp->conv.sys2int = cs_char2int; | | 356 | sp->conv.sys2int = cs_char2int; |
346 | sp->conv.int2sys = cs_int2char; | | 357 | sp->conv.int2sys = cs_int2char; |
347 | sp->conv.file2int = fe_char2int; | | 358 | sp->conv.file2int = fe_char2int; |
348 | sp->conv.int2file = fe_int2char; | | 359 | sp->conv.int2file = fe_int2char; |
349 | sp->conv.input2int = ie_char2int; | | 360 | sp->conv.input2int = ie_char2int; |
350 | #endif | | 361 | #endif |
351 | #ifdef USE_ICONV | | 362 | #ifdef USE_ICONV |
352 | o_set(sp, O_FILEENCODING, OS_STRDUP, nl_langinfo(CODESET), 0); | | 363 | o_set(sp, O_FILEENCODING, OS_STRDUP, nl_langinfo(CODESET), 0); |
353 | o_set(sp, O_INPUTENCODING, OS_STRDUP, nl_langinfo(CODESET), 0); | | 364 | o_set(sp, O_INPUTENCODING, OS_STRDUP, nl_langinfo(CODESET), 0); |
354 | #endif | | 365 | #endif |
355 | } | | 366 | } |
356 | } | | 367 | } |
357 | | | 368 | |
358 | int | | 369 | int |
359 | conv_enc (SCR *sp, int option, const char *enc) | | 370 | conv_enc (SCR *sp, int option, const char *enc) |
360 | { | | 371 | { |
361 | #if defined(USE_WIDECHAR) && defined(USE_ICONV) | | 372 | #if defined(USE_WIDECHAR) && defined(USE_ICONV) |
362 | iconv_t id; | | 373 | iconv_t id; |
363 | char2wchar_t *c2w; | | 374 | char2wchar_t *c2w; |
364 | wchar2char_t *w2c; | | 375 | wchar2char_t *w2c; |
365 | | | 376 | |
366 | switch (option) { | | 377 | switch (option) { |
367 | case O_FILEENCODING: | | 378 | case O_FILEENCODING: |
368 | c2w = &sp->conv.file2int; | | 379 | c2w = &sp->conv.file2int; |
369 | w2c = &sp->conv.int2file; | | 380 | w2c = &sp->conv.int2file; |
370 | break; | | 381 | break; |
371 | case O_INPUTENCODING: | | 382 | case O_INPUTENCODING: |
372 | c2w = &sp->conv.input2int; | | 383 | c2w = &sp->conv.input2int; |
373 | w2c = NULL; | | 384 | w2c = NULL; |
374 | break; | | 385 | break; |
375 | default: | | 386 | default: |
376 | c2w = NULL; | | 387 | c2w = NULL; |
377 | w2c = NULL; | | 388 | w2c = NULL; |
378 | break; | | 389 | break; |
379 | } | | 390 | } |
380 | | | 391 | |
381 | if (!*enc) { | | 392 | if (!*enc) { |
382 | if (c2w) *c2w = raw2int; | | 393 | if (c2w) *c2w = raw2int; |
383 | if (w2c) *w2c = int2raw; | | 394 | if (w2c) *w2c = int2raw; |
384 | return 0; | | 395 | return 0; |
385 | } | | 396 | } |
386 | | | 397 | |
387 | if (!strcmp(enc, "WCHAR_T")) { | | 398 | if (!strcmp(enc, "WCHAR_T")) { |
388 | if (c2w) *c2w = CHAR_T_char2int; | | 399 | if (c2w) *c2w = CHAR_T_char2int; |
389 | if (w2c) *w2c = CHAR_T_int2char; | | 400 | if (w2c) *w2c = CHAR_T_int2char; |
390 | return 0; | | 401 | return 0; |
391 | } | | 402 | } |
392 | | | 403 | |
393 | id = iconv_open(enc, nl_langinfo(CODESET)); | | 404 | id = iconv_open(enc, nl_langinfo(CODESET)); |
394 | if (id == (iconv_t)-1) | | 405 | if (id == (iconv_t)-1) |
395 | goto err; | | 406 | goto err; |
396 | iconv_close(id); | | 407 | iconv_close(id); |
397 | id = iconv_open(nl_langinfo(CODESET), enc); | | 408 | id = iconv_open(nl_langinfo(CODESET), enc); |
398 | if (id == (iconv_t)-1) | | 409 | if (id == (iconv_t)-1) |
399 | goto err; | | 410 | goto err; |
400 | iconv_close(id); | | 411 | iconv_close(id); |
401 | | | 412 | |
402 | switch (option) { | | 413 | switch (option) { |
403 | case O_FILEENCODING: | | 414 | case O_FILEENCODING: |
404 | *c2w = fe_char2int; | | 415 | *c2w = fe_char2int; |
405 | *w2c = fe_int2char; | | 416 | *w2c = fe_int2char; |
406 | break; | | 417 | break; |
407 | case O_INPUTENCODING: | | 418 | case O_INPUTENCODING: |
408 | *c2w = ie_char2int; | | 419 | *c2w = ie_char2int; |
409 | break; | | 420 | break; |
410 | } | | 421 | } |
411 | | | 422 | |
412 | F_CLR(sp, SC_CONV_ERROR); | | 423 | F_CLR(sp, SC_CONV_ERROR); |
413 | F_SET(sp, SC_SCR_REFORMAT); | | 424 | F_SET(sp, SC_SCR_REFORMAT); |
414 | | | 425 | |
415 | return 0; | | 426 | return 0; |
416 | err: | | 427 | err: |
417 | switch (option) { | | 428 | switch (option) { |
418 | case O_FILEENCODING: | | 429 | case O_FILEENCODING: |
419 | msgq(sp, M_ERR, | | 430 | msgq(sp, M_ERR, |
420 | "321|File encoding conversion not supported"); | | 431 | "321|File encoding conversion not supported"); |
421 | break; | | 432 | break; |
422 | case O_INPUTENCODING: | | 433 | case O_INPUTENCODING: |
423 | msgq(sp, M_ERR, | | 434 | msgq(sp, M_ERR, |
424 | "322|Input encoding conversion not supported"); | | 435 | "322|Input encoding conversion not supported"); |
425 | break; | | 436 | break; |
426 | } | | 437 | } |
427 | #endif | | 438 | #endif |
428 | return 1; | | 439 | return 1; |
429 | } | | 440 | } |
430 | | | 441 | |