1*0a6a1f1dSLionel Sambuc /* $NetBSD: conv.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */
284d9c625SLionel Sambuc /*-
384d9c625SLionel Sambuc * Copyright (c) 1993, 1994
484d9c625SLionel Sambuc * The Regents of the University of California. All rights reserved.
584d9c625SLionel Sambuc * Copyright (c) 1993, 1994, 1995, 1996
684d9c625SLionel Sambuc * Keith Bostic. All rights reserved.
784d9c625SLionel Sambuc *
884d9c625SLionel Sambuc * See the LICENSE file for redistribution information.
984d9c625SLionel Sambuc */
1084d9c625SLionel Sambuc
1184d9c625SLionel Sambuc #include "config.h"
1284d9c625SLionel Sambuc
13*0a6a1f1dSLionel Sambuc #include <sys/cdefs.h>
14*0a6a1f1dSLionel Sambuc #if 0
1584d9c625SLionel Sambuc #ifndef lint
1684d9c625SLionel Sambuc 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 ";
1784d9c625SLionel Sambuc #endif /* not lint */
18*0a6a1f1dSLionel Sambuc #else
19*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: conv.c,v 1.4 2014/01/26 21:43:45 christos Exp $");
20*0a6a1f1dSLionel Sambuc #endif
2184d9c625SLionel Sambuc
2284d9c625SLionel Sambuc #include <sys/types.h>
2384d9c625SLionel Sambuc #include <sys/queue.h>
2484d9c625SLionel Sambuc #include <sys/time.h>
2584d9c625SLionel Sambuc
2684d9c625SLionel Sambuc #include <bitstring.h>
2784d9c625SLionel Sambuc #include <errno.h>
2884d9c625SLionel Sambuc #include <limits.h>
2984d9c625SLionel Sambuc #include <stdio.h>
3084d9c625SLionel Sambuc #include <stdlib.h>
3184d9c625SLionel Sambuc #include <string.h>
3284d9c625SLionel Sambuc #include <unistd.h>
3384d9c625SLionel Sambuc
3484d9c625SLionel Sambuc #include "common.h"
3584d9c625SLionel Sambuc
3684d9c625SLionel Sambuc #ifdef USE_ICONV
3784d9c625SLionel Sambuc #include <langinfo.h>
3884d9c625SLionel Sambuc #include <iconv.h>
3984d9c625SLionel Sambuc
4084d9c625SLionel Sambuc #define LANGCODESET nl_langinfo(CODESET)
4184d9c625SLionel Sambuc #else
4284d9c625SLionel Sambuc typedef int iconv_t;
4384d9c625SLionel Sambuc
4484d9c625SLionel Sambuc #define LANGCODESET ""
4584d9c625SLionel Sambuc #endif
4684d9c625SLionel Sambuc
4784d9c625SLionel Sambuc #include <locale.h>
4884d9c625SLionel Sambuc
4984d9c625SLionel Sambuc #ifdef USE_WIDECHAR
5084d9c625SLionel Sambuc static int
raw2int(SCR * sp,const char * str,ssize_t len,CONVWIN * cw,size_t * tolen,const CHAR_T ** dst)5184d9c625SLionel Sambuc raw2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw, size_t *tolen,
5284d9c625SLionel Sambuc const CHAR_T **dst)
5384d9c625SLionel Sambuc {
5484d9c625SLionel Sambuc int i;
5584d9c625SLionel Sambuc CHAR_T **tostr = (CHAR_T **)(void *)&cw->bp1;
5684d9c625SLionel Sambuc size_t *blen = &cw->blen1;
5784d9c625SLionel Sambuc
5884d9c625SLionel Sambuc BINC_RETW(NULL, *tostr, *blen, len);
5984d9c625SLionel Sambuc
6084d9c625SLionel Sambuc *tolen = len;
61*0a6a1f1dSLionel Sambuc for (i = 0; i < len; ++i) {
62*0a6a1f1dSLionel Sambuc CHAR_T w = (u_char)str[i];
63*0a6a1f1dSLionel Sambuc memcpy((*tostr) + i, &w, sizeof(**tostr));
64*0a6a1f1dSLionel Sambuc }
6584d9c625SLionel Sambuc
6684d9c625SLionel Sambuc *dst = cw->bp1;
6784d9c625SLionel Sambuc
6884d9c625SLionel Sambuc return 0;
6984d9c625SLionel Sambuc }
7084d9c625SLionel Sambuc
7184d9c625SLionel Sambuc #ifndef ERROR_ON_CONVERT
7284d9c625SLionel Sambuc #define HANDLE_ICONV_ERROR(o, i, ol, il) do { \
7384d9c625SLionel Sambuc *o++ = *i++; \
7484d9c625SLionel Sambuc ol--; il--; \
7584d9c625SLionel Sambuc } while (/*CONSTCOND*/0)
7684d9c625SLionel Sambuc #define HANDLE_MBR_ERROR(n, mbs, d, s) do { \
7784d9c625SLionel Sambuc d = s; \
7884d9c625SLionel Sambuc MEMSET(&mbs, 0, 1); \
7984d9c625SLionel Sambuc n = 1; \
8084d9c625SLionel Sambuc } while (/*CONSTCOND*/0)
8184d9c625SLionel Sambuc #else
8284d9c625SLionel Sambuc #define HANDLE_ICONV_ERROR goto err
8384d9c625SLionel Sambuc #define HANDLE_MBR_ERROR goto err
8484d9c625SLionel Sambuc #endif
8584d9c625SLionel Sambuc
8684d9c625SLionel Sambuc #define CONV_BUFFER_SIZE 512
8784d9c625SLionel Sambuc /* fill the buffer with codeset encoding of string pointed to by str
8884d9c625SLionel Sambuc * left has the number of bytes left in str and is adjusted
8984d9c625SLionel Sambuc * len contains the number of bytes put in the buffer
9084d9c625SLionel Sambuc */
9184d9c625SLionel Sambuc #ifdef USE_ICONV
9284d9c625SLionel Sambuc #define CONVERT(str, left, src, len) \
9384d9c625SLionel Sambuc do { \
9484d9c625SLionel Sambuc size_t outleft; \
9584d9c625SLionel Sambuc char *bp = buffer; \
9684d9c625SLionel Sambuc outleft = CONV_BUFFER_SIZE; \
9784d9c625SLionel Sambuc errno = 0; \
9884d9c625SLionel Sambuc if (iconv(id, (const char **)&str, &left, &bp, &outleft) \
9984d9c625SLionel Sambuc == (size_t)-1 /* && errno != E2BIG */) \
10084d9c625SLionel Sambuc HANDLE_ICONV_ERROR(bp, str, outleft, left); \
10184d9c625SLionel Sambuc if ((len = CONV_BUFFER_SIZE - outleft) == 0) { \
10284d9c625SLionel Sambuc error = -left; \
10384d9c625SLionel Sambuc goto err; \
10484d9c625SLionel Sambuc } \
10584d9c625SLionel Sambuc src = buffer; \
10684d9c625SLionel Sambuc } while (0)
10784d9c625SLionel Sambuc #else
10884d9c625SLionel Sambuc #define CONVERT(str, left, src, len)
10984d9c625SLionel Sambuc #endif
11084d9c625SLionel Sambuc
11184d9c625SLionel Sambuc static int
default_char2int(SCR * sp,const char * str,ssize_t len,CONVWIN * cw,size_t * tolen,const CHAR_T ** dst,const char * enc)11284d9c625SLionel Sambuc default_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw,
11384d9c625SLionel Sambuc size_t *tolen, const CHAR_T **dst, const char *enc)
11484d9c625SLionel Sambuc {
11584d9c625SLionel Sambuc int j;
11684d9c625SLionel Sambuc size_t i = 0;
11784d9c625SLionel Sambuc CHAR_T **tostr = (CHAR_T **)(void *)&cw->bp1;
11884d9c625SLionel Sambuc size_t *blen = &cw->blen1;
11984d9c625SLionel Sambuc mbstate_t mbs;
12084d9c625SLionel Sambuc size_t n;
12184d9c625SLionel Sambuc ssize_t nlen = len;
12284d9c625SLionel Sambuc const char *src = (const char *)str;
12384d9c625SLionel Sambuc iconv_t id = (iconv_t)-1;
12484d9c625SLionel Sambuc char buffer[CONV_BUFFER_SIZE];
12584d9c625SLionel Sambuc size_t left = len;
12684d9c625SLionel Sambuc int error = 1;
12784d9c625SLionel Sambuc
12884d9c625SLionel Sambuc MEMSET(&mbs, 0, 1);
12984d9c625SLionel Sambuc BINC_RETW(NULL, *tostr, *blen, nlen);
13084d9c625SLionel Sambuc
13184d9c625SLionel Sambuc #ifdef USE_ICONV
13284d9c625SLionel Sambuc if (strcmp(nl_langinfo(CODESET), enc)) {
13384d9c625SLionel Sambuc id = iconv_open(nl_langinfo(CODESET), enc);
13484d9c625SLionel Sambuc if (id == (iconv_t)-1)
13584d9c625SLionel Sambuc goto err;
13684d9c625SLionel Sambuc CONVERT(str, left, src, len);
13784d9c625SLionel Sambuc }
13884d9c625SLionel Sambuc #endif
13984d9c625SLionel Sambuc
14084d9c625SLionel Sambuc for (i = 0, j = 0; j < len; ) {
141*0a6a1f1dSLionel Sambuc CHAR_T w;
142*0a6a1f1dSLionel Sambuc n = mbrtowc(&w, src + j, len - j, &mbs);
143*0a6a1f1dSLionel Sambuc memcpy((*tostr) + i, &w, sizeof(**tostr));
14484d9c625SLionel Sambuc /* NULL character converted */
14584d9c625SLionel Sambuc if (n == (size_t)-2) error = -(len - j);
146*0a6a1f1dSLionel Sambuc if (n == (size_t)-1 || n == (size_t)-2) {
147*0a6a1f1dSLionel Sambuc HANDLE_MBR_ERROR(n, mbs, w, src[j]);
148*0a6a1f1dSLionel Sambuc memcpy((*tostr) + i, &w, sizeof(**tostr));
149*0a6a1f1dSLionel Sambuc }
15084d9c625SLionel Sambuc if (n == 0) n = 1;
15184d9c625SLionel Sambuc j += n;
15284d9c625SLionel Sambuc if (++i >= *blen) {
15384d9c625SLionel Sambuc nlen += 256;
15484d9c625SLionel Sambuc BINC_RETW(NULL, *tostr, *blen, nlen);
15584d9c625SLionel Sambuc }
15684d9c625SLionel Sambuc if (id != (iconv_t)-1 && j == len && left) {
15784d9c625SLionel Sambuc CONVERT(str, left, src, len);
15884d9c625SLionel Sambuc j = 0;
15984d9c625SLionel Sambuc }
16084d9c625SLionel Sambuc }
16184d9c625SLionel Sambuc *tolen = i;
16284d9c625SLionel Sambuc
16384d9c625SLionel Sambuc if (id != (iconv_t)-1)
16484d9c625SLionel Sambuc iconv_close(id);
16584d9c625SLionel Sambuc
16684d9c625SLionel Sambuc *dst = cw->bp1;
16784d9c625SLionel Sambuc
16884d9c625SLionel Sambuc return 0;
16984d9c625SLionel Sambuc err:
17084d9c625SLionel Sambuc *tolen = i;
17184d9c625SLionel Sambuc if (id != (iconv_t)-1)
17284d9c625SLionel Sambuc iconv_close(id);
17384d9c625SLionel Sambuc *dst = cw->bp1;
17484d9c625SLionel Sambuc
17584d9c625SLionel Sambuc return error;
17684d9c625SLionel Sambuc }
17784d9c625SLionel Sambuc
17884d9c625SLionel Sambuc static int
fe_char2int(SCR * sp,const char * str,ssize_t len,CONVWIN * cw,size_t * tolen,const CHAR_T ** dst)17984d9c625SLionel Sambuc fe_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw,
18084d9c625SLionel Sambuc size_t *tolen, const CHAR_T **dst)
18184d9c625SLionel Sambuc {
18284d9c625SLionel Sambuc return default_char2int(sp, str, len, cw, tolen, dst, O_STR(sp, O_FILEENCODING));
18384d9c625SLionel Sambuc }
18484d9c625SLionel Sambuc
18584d9c625SLionel Sambuc static int
ie_char2int(SCR * sp,const char * str,ssize_t len,CONVWIN * cw,size_t * tolen,const CHAR_T ** dst)18684d9c625SLionel Sambuc ie_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw,
18784d9c625SLionel Sambuc size_t *tolen, const CHAR_T **dst)
18884d9c625SLionel Sambuc {
18984d9c625SLionel Sambuc return default_char2int(sp, str, len, cw, tolen, dst, O_STR(sp, O_INPUTENCODING));
19084d9c625SLionel Sambuc }
19184d9c625SLionel Sambuc
19284d9c625SLionel Sambuc static int
cs_char2int(SCR * sp,const char * str,ssize_t len,CONVWIN * cw,size_t * tolen,const CHAR_T ** dst)19384d9c625SLionel Sambuc cs_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw,
19484d9c625SLionel Sambuc size_t *tolen, const CHAR_T **dst)
19584d9c625SLionel Sambuc {
19684d9c625SLionel Sambuc return default_char2int(sp, str, len, cw, tolen, dst, LANGCODESET);
19784d9c625SLionel Sambuc }
19884d9c625SLionel Sambuc
19984d9c625SLionel Sambuc static int
CHAR_T_int2char(SCR * sp,const CHAR_T * str,ssize_t len,CONVWIN * cw,size_t * tolen,const char ** dst)20084d9c625SLionel Sambuc CHAR_T_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw,
20184d9c625SLionel Sambuc size_t *tolen, const char **dst)
20284d9c625SLionel Sambuc {
20384d9c625SLionel Sambuc *tolen = len * sizeof(CHAR_T);
20484d9c625SLionel Sambuc *dst = (const char *)(const void *)str;
20584d9c625SLionel Sambuc
20684d9c625SLionel Sambuc return 0;
20784d9c625SLionel Sambuc }
20884d9c625SLionel Sambuc
20984d9c625SLionel Sambuc static int
CHAR_T_char2int(SCR * sp,const char * str,ssize_t len,CONVWIN * cw,size_t * tolen,const CHAR_T ** dst)21084d9c625SLionel Sambuc CHAR_T_char2int(SCR *sp, const char * str, ssize_t len, CONVWIN *cw,
21184d9c625SLionel Sambuc size_t *tolen, const CHAR_T **dst)
21284d9c625SLionel Sambuc {
21384d9c625SLionel Sambuc *tolen = len / sizeof(CHAR_T);
21484d9c625SLionel Sambuc *dst = (const CHAR_T*) str;
21584d9c625SLionel Sambuc
21684d9c625SLionel Sambuc return 0;
21784d9c625SLionel Sambuc }
21884d9c625SLionel Sambuc
21984d9c625SLionel Sambuc static int
int2raw(SCR * sp,const CHAR_T * str,ssize_t len,CONVWIN * cw,size_t * tolen,const char ** dst)22084d9c625SLionel Sambuc int2raw(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw, size_t *tolen,
22184d9c625SLionel Sambuc const char **dst)
22284d9c625SLionel Sambuc {
22384d9c625SLionel Sambuc int i;
22484d9c625SLionel Sambuc char **tostr = (char **)(void *)&cw->bp1;
22584d9c625SLionel Sambuc size_t *blen = &cw->blen1;
22684d9c625SLionel Sambuc
22784d9c625SLionel Sambuc BINC_RETC(NULL, *tostr, *blen, len);
22884d9c625SLionel Sambuc
22984d9c625SLionel Sambuc *tolen = len;
230*0a6a1f1dSLionel Sambuc for (i = 0; i < len; ++i) {
231*0a6a1f1dSLionel Sambuc CHAR_T w;
232*0a6a1f1dSLionel Sambuc memcpy(&w, str + i, sizeof(w));
233*0a6a1f1dSLionel Sambuc (*tostr)[i] = w;
234*0a6a1f1dSLionel Sambuc }
23584d9c625SLionel Sambuc
23684d9c625SLionel Sambuc *dst = cw->bp1;
23784d9c625SLionel Sambuc
23884d9c625SLionel Sambuc return 0;
23984d9c625SLionel Sambuc }
24084d9c625SLionel Sambuc
24184d9c625SLionel Sambuc static int
default_int2char(SCR * sp,const CHAR_T * str,ssize_t len,CONVWIN * cw,size_t * tolen,const char ** pdst,const char * enc)24284d9c625SLionel Sambuc default_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw,
24384d9c625SLionel Sambuc size_t *tolen, const char **pdst, const char *enc)
24484d9c625SLionel Sambuc {
24584d9c625SLionel Sambuc size_t i, j;
24684d9c625SLionel Sambuc int offset = 0;
24784d9c625SLionel Sambuc char **tostr = (char **)(void *)&cw->bp1;
24884d9c625SLionel Sambuc size_t *blen = &cw->blen1;
24984d9c625SLionel Sambuc mbstate_t mbs;
25084d9c625SLionel Sambuc size_t n;
25184d9c625SLionel Sambuc ssize_t nlen = len + MB_CUR_MAX;
25284d9c625SLionel Sambuc char *dst;
25384d9c625SLionel Sambuc size_t buflen;
25484d9c625SLionel Sambuc char buffer[CONV_BUFFER_SIZE];
25584d9c625SLionel Sambuc iconv_t id = (iconv_t)-1;
25684d9c625SLionel Sambuc
25784d9c625SLionel Sambuc /* convert first len bytes of buffer and append it to cw->bp
25884d9c625SLionel Sambuc * len is adjusted => 0
25984d9c625SLionel Sambuc * offset contains the offset in cw->bp and is adjusted
26084d9c625SLionel Sambuc * cw->bp is grown as required
26184d9c625SLionel Sambuc */
26284d9c625SLionel Sambuc #ifdef USE_ICONV
26384d9c625SLionel Sambuc #define CONVERT2(len, cw, offset) \
26484d9c625SLionel Sambuc do { \
26584d9c625SLionel Sambuc const char *bp = buffer; \
26684d9c625SLionel Sambuc while (len != 0) { \
26784d9c625SLionel Sambuc size_t outleft = cw->blen1 - offset; \
26884d9c625SLionel Sambuc char *obp = (char *)cw->bp1 + offset; \
26984d9c625SLionel Sambuc if (cw->blen1 < offset + MB_CUR_MAX) { \
27084d9c625SLionel Sambuc nlen += 256; \
27184d9c625SLionel Sambuc BINC_RETC(NULL, cw->bp1, cw->blen1, nlen); \
27284d9c625SLionel Sambuc } \
27384d9c625SLionel Sambuc errno = 0; \
27484d9c625SLionel Sambuc if (iconv(id, &bp, &len, &obp, &outleft) == (size_t)-1 && \
27584d9c625SLionel Sambuc errno != E2BIG) \
27684d9c625SLionel Sambuc HANDLE_ICONV_ERROR(obp, bp, outleft, len); \
27784d9c625SLionel Sambuc offset = cw->blen1 - outleft; \
27884d9c625SLionel Sambuc } \
27984d9c625SLionel Sambuc } while (0)
28084d9c625SLionel Sambuc #else
28184d9c625SLionel Sambuc #define CONVERT2(len, cw, offset)
28284d9c625SLionel Sambuc #endif
28384d9c625SLionel Sambuc
28484d9c625SLionel Sambuc
28584d9c625SLionel Sambuc MEMSET(&mbs, 0, 1);
28684d9c625SLionel Sambuc BINC_RETC(NULL, *tostr, *blen, nlen);
28784d9c625SLionel Sambuc dst = *tostr; buflen = *blen;
28884d9c625SLionel Sambuc
28984d9c625SLionel Sambuc #ifdef USE_ICONV
29084d9c625SLionel Sambuc if (strcmp(nl_langinfo(CODESET), enc)) {
29184d9c625SLionel Sambuc id = iconv_open(enc, nl_langinfo(CODESET));
29284d9c625SLionel Sambuc if (id == (iconv_t)-1)
29384d9c625SLionel Sambuc goto err;
29484d9c625SLionel Sambuc dst = buffer; buflen = CONV_BUFFER_SIZE;
29584d9c625SLionel Sambuc }
29684d9c625SLionel Sambuc #endif
29784d9c625SLionel Sambuc
29884d9c625SLionel Sambuc for (i = 0, j = 0; i < (size_t)len; ++i) {
299*0a6a1f1dSLionel Sambuc CHAR_T w;
300*0a6a1f1dSLionel Sambuc memcpy(&w, str + i, sizeof(w));
301*0a6a1f1dSLionel Sambuc n = wcrtomb(dst + j, w, &mbs);
30284d9c625SLionel Sambuc if (n == (size_t)-1)
303*0a6a1f1dSLionel Sambuc HANDLE_MBR_ERROR(n, mbs, dst[j], w);
30484d9c625SLionel Sambuc j += n;
30584d9c625SLionel Sambuc if (buflen < j + MB_CUR_MAX) {
30684d9c625SLionel Sambuc if (id != (iconv_t)-1) {
30784d9c625SLionel Sambuc CONVERT2(j, cw, offset);
30884d9c625SLionel Sambuc } else {
30984d9c625SLionel Sambuc nlen += 256;
31084d9c625SLionel Sambuc BINC_RETC(NULL, *tostr, *blen, nlen);
31184d9c625SLionel Sambuc dst = *tostr; buflen = *blen;
31284d9c625SLionel Sambuc }
31384d9c625SLionel Sambuc }
31484d9c625SLionel Sambuc }
31584d9c625SLionel Sambuc
31684d9c625SLionel Sambuc n = wcrtomb(dst + j, L'\0', &mbs);
31784d9c625SLionel Sambuc j += n - 1; /* don't count NUL at the end */
31884d9c625SLionel Sambuc *tolen = j;
31984d9c625SLionel Sambuc
32084d9c625SLionel Sambuc if (id != (iconv_t)-1) {
32184d9c625SLionel Sambuc CONVERT2(j, cw, offset);
32284d9c625SLionel Sambuc *tolen = offset;
32384d9c625SLionel Sambuc }
32484d9c625SLionel Sambuc
32584d9c625SLionel Sambuc *pdst = cw->bp1;
32684d9c625SLionel Sambuc
32784d9c625SLionel Sambuc return 0;
32884d9c625SLionel Sambuc err:
32984d9c625SLionel Sambuc *tolen = j;
33084d9c625SLionel Sambuc
33184d9c625SLionel Sambuc *pdst = cw->bp1;
33284d9c625SLionel Sambuc
33384d9c625SLionel Sambuc return 1;
33484d9c625SLionel Sambuc }
33584d9c625SLionel Sambuc
33684d9c625SLionel Sambuc static int
fe_int2char(SCR * sp,const CHAR_T * str,ssize_t len,CONVWIN * cw,size_t * tolen,const char ** dst)33784d9c625SLionel Sambuc fe_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw,
33884d9c625SLionel Sambuc size_t *tolen, const char **dst)
33984d9c625SLionel Sambuc {
34084d9c625SLionel Sambuc return default_int2char(sp, str, len, cw, tolen, dst, O_STR(sp, O_FILEENCODING));
34184d9c625SLionel Sambuc }
34284d9c625SLionel Sambuc
34384d9c625SLionel Sambuc static int
cs_int2char(SCR * sp,const CHAR_T * str,ssize_t len,CONVWIN * cw,size_t * tolen,const char ** dst)34484d9c625SLionel Sambuc cs_int2char(SCR *sp, const CHAR_T * str, ssize_t len, CONVWIN *cw,
34584d9c625SLionel Sambuc size_t *tolen, const char **dst)
34684d9c625SLionel Sambuc {
34784d9c625SLionel Sambuc return default_int2char(sp, str, len, cw, tolen, dst, LANGCODESET);
34884d9c625SLionel Sambuc }
34984d9c625SLionel Sambuc
35084d9c625SLionel Sambuc #endif
35184d9c625SLionel Sambuc
35284d9c625SLionel Sambuc
35384d9c625SLionel Sambuc void
conv_init(SCR * orig,SCR * sp)35484d9c625SLionel Sambuc conv_init (SCR *orig, SCR *sp)
35584d9c625SLionel Sambuc {
35684d9c625SLionel Sambuc if (orig != NULL)
35784d9c625SLionel Sambuc MEMCPY(&sp->conv, &orig->conv, 1);
35884d9c625SLionel Sambuc else {
35984d9c625SLionel Sambuc setlocale(LC_ALL, "");
36084d9c625SLionel Sambuc #ifdef USE_WIDECHAR
36184d9c625SLionel Sambuc sp->conv.sys2int = cs_char2int;
36284d9c625SLionel Sambuc sp->conv.int2sys = cs_int2char;
36384d9c625SLionel Sambuc sp->conv.file2int = fe_char2int;
36484d9c625SLionel Sambuc sp->conv.int2file = fe_int2char;
36584d9c625SLionel Sambuc sp->conv.input2int = ie_char2int;
36684d9c625SLionel Sambuc #endif
36784d9c625SLionel Sambuc #ifdef USE_ICONV
36884d9c625SLionel Sambuc o_set(sp, O_FILEENCODING, OS_STRDUP, nl_langinfo(CODESET), 0);
36984d9c625SLionel Sambuc o_set(sp, O_INPUTENCODING, OS_STRDUP, nl_langinfo(CODESET), 0);
37084d9c625SLionel Sambuc #endif
37184d9c625SLionel Sambuc }
37284d9c625SLionel Sambuc }
37384d9c625SLionel Sambuc
37484d9c625SLionel Sambuc int
conv_enc(SCR * sp,int option,const char * enc)37584d9c625SLionel Sambuc conv_enc (SCR *sp, int option, const char *enc)
37684d9c625SLionel Sambuc {
37784d9c625SLionel Sambuc #if defined(USE_WIDECHAR) && defined(USE_ICONV)
37884d9c625SLionel Sambuc iconv_t id;
37984d9c625SLionel Sambuc char2wchar_t *c2w;
38084d9c625SLionel Sambuc wchar2char_t *w2c;
38184d9c625SLionel Sambuc
38284d9c625SLionel Sambuc switch (option) {
38384d9c625SLionel Sambuc case O_FILEENCODING:
38484d9c625SLionel Sambuc c2w = &sp->conv.file2int;
38584d9c625SLionel Sambuc w2c = &sp->conv.int2file;
38684d9c625SLionel Sambuc break;
38784d9c625SLionel Sambuc case O_INPUTENCODING:
38884d9c625SLionel Sambuc c2w = &sp->conv.input2int;
38984d9c625SLionel Sambuc w2c = NULL;
39084d9c625SLionel Sambuc break;
39184d9c625SLionel Sambuc default:
39284d9c625SLionel Sambuc c2w = NULL;
39384d9c625SLionel Sambuc w2c = NULL;
39484d9c625SLionel Sambuc break;
39584d9c625SLionel Sambuc }
39684d9c625SLionel Sambuc
39784d9c625SLionel Sambuc if (!*enc) {
39884d9c625SLionel Sambuc if (c2w) *c2w = raw2int;
39984d9c625SLionel Sambuc if (w2c) *w2c = int2raw;
40084d9c625SLionel Sambuc return 0;
40184d9c625SLionel Sambuc }
40284d9c625SLionel Sambuc
40384d9c625SLionel Sambuc if (!strcmp(enc, "WCHAR_T")) {
40484d9c625SLionel Sambuc if (c2w) *c2w = CHAR_T_char2int;
40584d9c625SLionel Sambuc if (w2c) *w2c = CHAR_T_int2char;
40684d9c625SLionel Sambuc return 0;
40784d9c625SLionel Sambuc }
40884d9c625SLionel Sambuc
40984d9c625SLionel Sambuc id = iconv_open(enc, nl_langinfo(CODESET));
41084d9c625SLionel Sambuc if (id == (iconv_t)-1)
41184d9c625SLionel Sambuc goto err;
41284d9c625SLionel Sambuc iconv_close(id);
41384d9c625SLionel Sambuc id = iconv_open(nl_langinfo(CODESET), enc);
41484d9c625SLionel Sambuc if (id == (iconv_t)-1)
41584d9c625SLionel Sambuc goto err;
41684d9c625SLionel Sambuc iconv_close(id);
41784d9c625SLionel Sambuc
41884d9c625SLionel Sambuc switch (option) {
41984d9c625SLionel Sambuc case O_FILEENCODING:
42084d9c625SLionel Sambuc *c2w = fe_char2int;
42184d9c625SLionel Sambuc *w2c = fe_int2char;
42284d9c625SLionel Sambuc break;
42384d9c625SLionel Sambuc case O_INPUTENCODING:
42484d9c625SLionel Sambuc *c2w = ie_char2int;
42584d9c625SLionel Sambuc break;
42684d9c625SLionel Sambuc }
42784d9c625SLionel Sambuc
42884d9c625SLionel Sambuc F_CLR(sp, SC_CONV_ERROR);
42984d9c625SLionel Sambuc F_SET(sp, SC_SCR_REFORMAT);
43084d9c625SLionel Sambuc
43184d9c625SLionel Sambuc return 0;
43284d9c625SLionel Sambuc err:
43384d9c625SLionel Sambuc switch (option) {
43484d9c625SLionel Sambuc case O_FILEENCODING:
43584d9c625SLionel Sambuc msgq(sp, M_ERR,
43684d9c625SLionel Sambuc "321|File encoding conversion not supported");
43784d9c625SLionel Sambuc break;
43884d9c625SLionel Sambuc case O_INPUTENCODING:
43984d9c625SLionel Sambuc msgq(sp, M_ERR,
44084d9c625SLionel Sambuc "322|Input encoding conversion not supported");
44184d9c625SLionel Sambuc break;
44284d9c625SLionel Sambuc }
44384d9c625SLionel Sambuc #endif
44484d9c625SLionel Sambuc return 1;
44584d9c625SLionel Sambuc }
44684d9c625SLionel Sambuc
447