1 /*
2 * codeconv.c
3 * Copyright(c) 2001 Takashi NEMOTO
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * Written by Takashi Nemoto (tnemoto@mvi.biglobe.ne.jp).
16 * Modified by Kazuhiko <kazuhiko@ring.gr.jp>
17 * Modified by Satomi <satomi@ring.gr.jp>
18 *
19 */
20
21 /* #define DEBUG_CODECONV */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "codeconv.h"
28
29 #ifdef HAVE_SYS_TYPES_H
30 # include <sys/types.h>
31 #endif
32
33 #include <stdio.h>
34
35 #ifdef HAVE_STDLIB_H
36 # include <stdlib.h>
37 #endif
38
39 #ifdef HAVE_LOCALE_H
40 # include <locale.h>
41 #endif
42
43 #ifdef HAVE_ICONV_H
44 # include <iconv.h>
45 #endif
46
47 #ifdef HAVE_ERRNO_H
48 # include <errno.h>
49 #endif
50
51 #ifdef HAVE_STRING_H
52 # include <string.h>
53 #endif
54
55 #ifdef HAVE_LANGINFO_H
56 #include <langinfo.h>
57 #endif
58
59 #ifndef HAVE_MEMCPY
60 #define memcpy(d, s, n) bcopy((s), (d), (n))
61 #ifdef __STDC__
62 void *memchr(const void *, int, size_t);
63 int memcmp(const void *, const void *, size_t);
64 void *memmove(void *, const void *, size_t);
65 void *memset(void *, int, size_t);
66 #else /* not __STDC__ */
67 char *memchr();
68 int memcmp();
69 char *memmove();
70 char *memset();
71 #endif /* not __STDC__ */
72 #endif
73
74 #ifdef HAVE_ICONV
75 static iconv_t cur_to_euc = (iconv_t)-1;
76 static iconv_t euc_to_cur = (iconv_t)-1;
77 static const char *eucjp_code_name = NULL;
78 #endif
79
80 /* Return code <0: error, -2: Output Buffer Overflow */
81 size_t current_to_euc PROTO((char **current, size_t *in_len,
82 char **euc, size_t *out_len));
83 static size_t euc_to_current PROTO((char **euc, size_t *in_len,
84 char **current, size_t *out_len));
85
86
87 enum CONV_MODE {IO_AUTO, IO_ICONV, IO_SJIS, IO_EUC} conv_mode;
88
89 static enum CONV_MODE detect_conv_mode PROTO((const char *encoding));
90
91
92
93
94 #define TMP_SIZE 10240
95
96 static int xputs_raw PROTO((const char *str, int len, FILE *fp));
97 static int xputs2 PROTO((const char *str, int len, FILE *fp));
98
99 static const char *euc_jp_names[] = {
100 "eucJP", "EUC-JP", "eucjp", "euc-jp", "EUCJP", "ujis", "UJIS",
101 "euc", "EUC", NULL
102 };
103
104 static const char *shift_jis_names[] = {
105 "SHIFT-JIS", "SHIFT_JIS", "SJIS", "CSSHIFTJIS", "SHIFTJIS", NULL
106 };
107
108 #ifdef HAVE_ICONV
109 static const char *iso_2022_jp_names[] = {
110 "ISO-2022-JP-3", "ISO-2022-JP-2", "ISO-2022-JP",
111 "CSISO2022JP", "CSISO2022JP2", "CSISO2022JP3",
112 "ISO-2022", "ISO2022", "ISO2022JP", "ISO2022-JP", "JIS", NULL
113 };
114
115 static const char *japanese_names[] = {
116 "ja", "japanese", NULL
117 };
118 #endif
119
match_str(str,str_list)120 static int match_str(str,str_list)
121 const char *str;
122 const char **str_list;
123 {
124 const char **ptr;
125 for(ptr=str_list;*ptr!=NULL;ptr++) {
126 if (strcasecmp(str,*ptr)==0) return 1;
127 }
128 return 0;
129 }
130
131 /*
132
133 �������Ѵ��ؿ���������
134
135
136 1. encoding �����ꤵ��Ƥ����顢�ޤ����ꤵ�줿 encoding ��
137 1a. �ޤ� ���ꤵ�줿 encoding �� EUC/SJIS ���ɤ�����Ƚ�� => IO_EUC / IO_SJIS
138 1b. ����ʤ� iconv ���Ѵ��Ǥ��� encoding ����Ƚ�� => IO_ICONV
139 �ʲ�Ʊ�͡�
140
141 2. ���˽�����Ѥߤ��ä��� �����ǽ�λ
142
143 3. ����ʤ� locale ����μ������ߤ�
144 3a. nl_langinfo(CODESET) ����� encoding ���Ф����ߤ롣
145 3b. LC_CTYPE ����� encoding ���Ф����ߤ롣
146 2e. LC_CTYPE ��Ⱦ��(.�ʹ�) ����� encoding ���Ф����ߤ롣
147
148 3. FALLBACK_ENCODING ��
149
150 4. �������� EUC_JP
151
152 ����ˤʤ���
153 SJIS �� locale ̾�� ja/japanese �ξ��
154 iconv ��ͭ���� => EUC_JP �� iconv ̾�ϡ�
155 iconv ��̵����� => 4. �� EUC_JP ���ʡ�
156 locale �� C �Ȥ� en_US ���ä��顩 => ���� FALLBACK ���롣
157 gettext �б����ξ�����ľ����
158
159 */
160
161 #ifdef HAVE_ICONV
162
163 static int
setup_eucjp_code_name()164 setup_eucjp_code_name()
165 {
166 const char **enc;
167 iconv_t ic;
168 if (eucjp_code_name == NULL) {
169 for (enc = euc_jp_names; *enc != NULL; enc++) {
170 ic = iconv_open(*enc, *enc);
171 if (ic != (iconv_t)-1) {
172 eucjp_code_name = *enc;
173 iconv_close(ic);
174 break;
175 }
176 }
177 if (eucjp_code_name == NULL) {
178 /* EUC-JP ����˼��� - ۣ��� "ja" "japanese" �� */
179 for (enc = japanese_names; *enc != NULL; enc++) {
180 ic = iconv_open(*enc,*enc);
181 if (ic != (iconv_t)-1) {
182 eucjp_code_name = *enc;
183 iconv_close(ic);
184 break;
185 }
186 }
187 }
188 }
189 return eucjp_code_name != NULL;
190 }
191
192 /* Current locale �� codeset �����ܸ줬�����뤫��
193 ���Ԥʤ� 0, �����ʤ� 1 ���֤� */
194
195 static int
iconv_test(ctoe,etoc)196 iconv_test(ctoe, etoc)
197 iconv_t ctoe, etoc;
198 {
199 /* ʸ���� "�¸�" */
200 #define TEST_STRING "\xBC\xC2\xB8\xB3"
201 #define TEST_LENGTH 50
202 char test1_0[TEST_LENGTH],test2_0[TEST_LENGTH],test3_0[TEST_LENGTH];
203 char *test1,*test2,*test3;
204 size_t ilen,olen;
205
206 if (ctoe == (iconv_t)-1 || etoc == (iconv_t)-1)
207 return 0;
208 strcpy(test1_0,TEST_STRING);
209 test1=test1_0;
210 test2=test2_0;
211 test3=test3_0;
212 ilen=strlen(TEST_STRING);
213 olen=TEST_LENGTH;
214
215 /* euc-jp => current code ���Ѵ��ƥ��� */
216 if (iconv(etoc,&test1,&ilen,&test2,&olen) == ((size_t)-1))
217 return 0;
218 if (iconv(etoc,NULL,&ilen,&test2,&olen) == ((size_t)-1))
219 return 0;
220
221 /* current code ���� ������뤫 */
222 test2=test2_0;
223 ilen=TEST_LENGTH-olen;
224 olen=TEST_LENGTH;
225 if (iconv(ctoe,&test2,&ilen,&test3,&olen) == ((size_t)-1))
226 return 0;
227 if (iconv(ctoe,NULL,&ilen,&test3,&olen) == ((size_t)-1))
228 return 0;
229
230 if (strncmp(test1_0,test3_0,strlen(test1_0)) != 0)
231 return 0;
232
233 return 1;
234 }
235
236 static int
iconv_setup(current_code_name)237 iconv_setup(current_code_name)
238 const char *current_code_name;
239 {
240 iconv_t ctoe,etoc;
241 static int disable_iconv = 0;
242
243 if (disable_iconv)
244 return 0;
245 if (eucjp_code_name == NULL) {
246 if (! setup_eucjp_code_name()) {
247 disable_iconv = 1;
248 return 0;
249 }
250 }
251
252 if (current_code_name == NULL || eucjp_code_name == NULL)
253 return 0;
254
255 ctoe = iconv_open(eucjp_code_name, current_code_name);
256 etoc = iconv_open(current_code_name, eucjp_code_name);
257
258
259 if (iconv_test(ctoe, etoc)) {
260 /* ���ޤ����ä��� ���ꤹ�� */
261 if (cur_to_euc != (iconv_t) -1)
262 iconv_close(cur_to_euc);
263 if (euc_to_cur != (iconv_t) -1)
264 iconv_close(euc_to_cur);
265 cur_to_euc=ctoe;
266 euc_to_cur=etoc;
267 return 1;
268 } else {
269 if (ctoe != (iconv_t)-1)
270 iconv_close(ctoe);
271 if (etoc != (iconv_t)-1)
272 iconv_close(etoc);
273 return 0;
274 }
275 }
276 #endif
277
detect_conv_mode(encoding)278 enum CONV_MODE detect_conv_mode(encoding)
279 const char *encoding;
280 {
281 if (encoding == NULL) return IO_AUTO;
282 if (match_str(encoding,euc_jp_names)) return IO_EUC;
283 if (match_str(encoding,shift_jis_names)) return IO_SJIS;
284 #ifdef HAVE_ICONV
285 if (match_str(encoding,iso_2022_jp_names)) {
286 const char **enc;
287 for(enc = iso_2022_jp_names;*enc != NULL; enc++){
288 if (iconv_setup(*enc))
289 return IO_ICONV;
290 }
291 } else if (iconv_setup(encoding)) {
292 return IO_ICONV;
293 }
294 #endif
295 return IO_AUTO;
296 }
297
298 int
locale_init(encoding)299 locale_init(encoding)
300 const char *encoding;
301 {
302 static int initialized = 0;
303 #ifdef HAVE_SETLOCALE
304 static char *locale_name = NULL;
305 static char *current_code_name = NULL;
306 #endif
307 enum CONV_MODE cm_temp;
308
309 #ifdef HAVE_SETLOCALE
310 locale_name = setlocale(LC_CTYPE, "");
311 #endif
312
313 /* 1. encoding �ˤ�����
314 �� ͭ���� encoding �����ꤵ���а������ͤ��� */
315 cm_temp = detect_conv_mode(encoding);
316 if (cm_temp != IO_AUTO) {
317 conv_mode = cm_temp;
318 goto init_finish;
319 }
320
321 /* ���Ǥ� ������ѤߤǤ���� ���Τޤ��� */
322 if (initialized != 0 &&
323 (conv_mode != IO_ICONV
324 #ifdef HAVE_ICONV
325 || (cur_to_euc != (iconv_t)-1 && euc_to_cur != (iconv_t)-1)
326 #endif
327 ))
328 return CODECONV_OK;
329 initialized = 0;
330 conv_mode = IO_AUTO;
331
332 #ifdef HAVE_SETLOCALE
333 /* 2. current_locale ���� ������ߤ� */
334 #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
335 /* 2a/2b. nl_langinfo(CODESET) �������� */
336 current_code_name=nl_langinfo(CODESET);
337 conv_mode=detect_conv_mode(current_code_name);
338 if (conv_mode != IO_AUTO)
339 goto init_finish;
340 #endif
341 /* 2c/2d. locale LC_CTYPE ���Τ�Τγ�ǧ */
342 conv_mode=detect_conv_mode(locale_name);
343 if (conv_mode != IO_AUTO)
344 goto init_finish;
345
346 /* 2e/2f. locale LC_CTYPE ��Ⱦ���γ�ǧ */
347 if (locale_name != NULL) {
348 char *try2;
349 locale_name = strdup(locale_name);
350 if (locale_name == NULL)
351 return CODECONV_ERROR;
352 try2 = strtok(locale_name, ".@");
353 if (try2 != NULL)
354 try2 = strtok(NULL, ".@");
355 if (try2 != NULL) {
356 conv_mode = detect_conv_mode(try2);
357 if (conv_mode != IO_AUTO) goto init_finish;
358 }
359 }
360 #endif /* HAVE_SETLOCALE */
361
362 /* 3a/3b. ����Ǥ����ʤ� FALLBACK ���� */
363 #ifdef FALLBACK_ENCODING
364 conv_mode = detect_conv_mode(FALLBACK_ENCODING);
365 #endif
366
367 /* 4. �������� EUC_JP */
368 if (conv_mode == IO_AUTO) conv_mode = IO_EUC;
369
370 init_finish:
371 initialized = 1;
372 return CODECONV_OK;
373 }
374
375 static int
xputs_raw(str,len,fp)376 xputs_raw(str, len, fp)
377 const char *str;
378 int len;
379 FILE *fp;
380 {
381 int outlen = 0;
382 int len1 = len;
383 int wlen;
384
385 while (outlen < len) {
386 wlen = fwrite(str, 1, len1, fp);
387 if (wlen == 0)
388 break;
389 outlen += wlen;
390 len1 -= wlen;
391 str += wlen;
392 }
393 return outlen;
394 }
395
396 /* Convert ISO8859-1 NO-BREAK SPACE to normal SPACE */
397 /* NBSP(0xa0) �� EUC-JP �Ȥ֤Ĥ���ʤ�Ȧ */
398 static int
convert_nbsp(str,len)399 convert_nbsp(str, len)
400 char *str;
401 int len;
402 {
403 while(len>0) {
404 if (((*str) & 0xff) == 0xa0) *str = 0x20;
405 str++;
406 len--;
407 }
408 return 1;
409 }
410
411 static int
xputs2(str,len,fp)412 xputs2(str, len, fp)
413 const char *str;
414 int len;
415 FILE *fp;
416 {
417 char *buf1p, *buf1p0;
418 char *buf2p, *buf2p0;
419 size_t len1, len2;
420 size_t outlen;
421 int ret_code;
422 size_t status;
423
424 /* The maximum size of output is 4 times larger than input. */
425 outlen = len * 4;
426
427 len1 = len;
428 len2 = outlen;
429 #ifdef HAVE_ALLOCA
430 buf1p = buf1p0 = alloca(len1);
431 #else
432 buf1p = buf1p0 = malloc(len1);
433 #endif
434 if (buf1p == NULL)
435 return EOF;
436 #ifdef HAVE_ALLOCA
437 buf2p = buf2p0 = alloca(len2);
438 #else
439 buf2p = buf2p0 = malloc(len2);
440 #endif
441 if (buf2p == NULL) {
442 free(buf1p0);
443 return EOF;
444 }
445 memcpy(buf1p, str, len);
446 convert_nbsp(buf1p, len);
447 status=euc_to_current(&buf1p, &len1, &buf2p, &len2);
448 if (status == -2) { /* ������ ��������� */
449 buf1p = buf1p0;
450 len1 = len;
451 outlen *= 3;
452 len2 = outlen;
453 #ifdef HAVE_ALLOCA
454 buf2p = buf2p0 = alloca(outlen);
455 #else
456 free(buf2p0);
457 buf2p = buf2p0 = malloc(outlen);
458 #endif
459 if (buf2p == NULL){
460 free(buf1p0);
461 return EOF;
462 }
463 status=euc_to_current(&buf1p, &len1, &buf2p, &len2);
464 }
465 if (status == CODECONV_ERROR || status == CODECONV_BUFFER_OVERFLOW) {
466 /* Conversion Error �������� ���Τޤ��� */
467 #ifndef HAVE_ALLOCA
468 free(buf1p0);
469 free(buf2p0);
470 #endif
471 return xputs_raw(str, len, fp);
472 }
473 #ifndef HAVE_ALLOCA
474 free(buf1p0);
475 #endif
476 ret_code = xputs_raw(buf2p0, outlen - len2, fp);
477 #ifndef HAVE_ALLOCA
478 free(buf2p0);
479 #endif
480 return ret_code;
481 }
482
483 int
xfputs(str,fp)484 xfputs(str, fp)
485 const char *str;
486 FILE* fp;
487 {
488 return xputs2(str, strlen(str), fp);
489 }
490
491 int
xputs(str)492 xputs(str)
493 const char *str;
494 {
495 int len;
496 len=xfputs(str, stdout);
497 if (len<0) return EOF;
498 putchar('\n');
499 return len+1;
500 }
501
502 int
xvfprintf(fp,fmt,ap)503 xvfprintf(fp, fmt, ap)
504 FILE *fp;
505 const char *fmt;
506 va_list ap;
507 {
508 char buf1[TMP_SIZE];
509 int len;
510 #ifdef HAVE_VSNPRINTF
511 len = vsnprintf(buf1, TMP_SIZE - 1, fmt, ap);
512 buf1[TMP_SIZE - 1]=0;
513 #else
514 len = vsprintf(buf1, fmt, ap);
515 #endif
516 return xputs2(buf1, len, fp);
517 }
518
519 /* USE_STDARG_H is defined in codeconv.h */
520 #ifdef USE_STDARG_H
521 int
xfprintf(FILE * fp,const char * fmt,...)522 xfprintf(FILE *fp, const char *fmt, ...)
523 #else
524 int
525 xfprintf(fp, fmt, va_alist)
526 FILE *fp;
527 const char *fmt;
528 va_dcl
529 #endif
530 {
531 int len;
532 va_list ap;
533 #ifdef USE_STDARG_H
534 va_start(ap, fmt);
535 #else
536 va_start(ap);
537 #endif
538 len = xvfprintf(fp, fmt, ap);
539 va_end(ap);
540 return len;
541 }
542
543 int
544 #ifdef USE_STDARG_H
xprintf(const char * fmt,...)545 xprintf(const char *fmt, ...)
546 #else
547 xprintf(fmt, va_alist)
548 const char *fmt;
549 va_dcl
550 #endif
551 {
552 int len;
553 va_list ap;
554 #ifdef USE_STDARG_H
555 va_start(ap, fmt);
556 #else
557 va_start(ap);
558 #endif
559 len = xvfprintf(stdout, fmt, ap);
560 va_end(ap);
561 return len;
562 }
563
564 char *
xfgets(str,size,fp)565 xfgets(str, size, fp)
566 char *str;
567 int size;
568 FILE *fp;
569 {
570 char *ibuf, *ibuf0;
571 size_t ilen;
572 size_t status;
573 char *str0;
574 int size0;
575
576 str0 = str;
577 size0 = size;
578
579 /* The maximum size of input is 4 times larger than size. */
580 ilen = size * 4;
581 #ifdef HAVE_ALLOCA
582 ibuf0 = ibuf = alloca(ilen+1);
583 #else
584 ibuf0 = ibuf = malloc(ilen+1);
585 #endif
586 if (ibuf == NULL)
587 return NULL;
588
589 if (fgets(ibuf, ilen, fp) == NULL) {
590 #ifndef HAVE_ALLOCA
591 free(ibuf);
592 #endif
593 return NULL;
594 }
595 ibuf[ilen]=0;
596 ilen=strlen(ibuf);
597
598 status = current_to_euc(&ibuf,&ilen,&str,(size_t *)&size);
599 str0[size0-size]=0;
600 #ifndef HAVE_ALLOCA
601 free(ibuf0);
602 #endif
603 if (status != CODECONV_ERROR) return str0;
604 return NULL;
605 }
606
607 /* ================================================================== */
608
609 char*
jis_to_euc(euc,jis,len)610 jis_to_euc(euc, jis, len)
611 char *euc;
612 const char *jis;
613 int len;
614 {
615 const char *jis_end;
616 char *q;
617 jis_end = jis + len;
618 /* Remove white space at tail of string */
619 while (jis_end >= jis + 2 &&
620 ((jis_end[-1] == '\0' && jis_end[-2] == '\0') ||
621 (jis_end[-1] == 0x21 && jis_end[-2] == 0x21)))
622 jis_end -= 2;
623 q = euc;
624 while (jis < jis_end)
625 *q++ = (*jis++ | 0x80);
626 *q = '\0';
627 return (char *)euc;
628 }
629
630 char*
euc_to_jis(jis,euc,len)631 euc_to_jis(jis, euc, len)
632 char *jis;
633 const char *euc;
634 int len;
635 {
636 const char *euc_end;
637 char *q;
638 euc_end = euc + len;
639 /* Remove white space at tail of string */
640 while (euc_end >= euc + 2 &&
641 ((euc_end[-1] == '\0' && euc_end[-2] == '\0') ||
642 (euc_end[-1] == 0x21 && euc_end[-2] == 0x21)))
643 euc_end -= 2;
644 q = jis;
645 while (euc < euc_end)
646 *q++ = (*euc++ & 0x7f);
647 *q = '\0';
648 return (char *)jis;
649 }
650
current_to_euc(in_buf,in_len,out_buf,out_len)651 size_t current_to_euc (in_buf,in_len,out_buf,out_len)
652 char **in_buf, **out_buf;
653 size_t *in_len,*out_len;
654 {
655 static int output_left = -1;
656 int c1, c2;
657 size_t count = 0;
658
659 #ifdef HAVE_ICONV
660 if (conv_mode == IO_ICONV) {
661 size_t ret;
662 if (cur_to_euc == (iconv_t) -1)
663 return CODECONV_ERROR;
664 ret = iconv(cur_to_euc,in_buf,in_len,out_buf,out_len);
665 if (ret != ((size_t)-1))
666 ret = iconv(cur_to_euc, NULL, in_len, out_buf, out_len);
667 #if defined (HAVE_ERRNO_H) && defined (E2BIG)
668 if (ret == ((size_t)-1)) {
669 if (errno == E2BIG)
670 return CODECONV_BUFFER_OVERFLOW;
671 return CODECONV_ERROR;
672 }
673 #endif /* HAVE_ERRNO_H / E2BIG */
674 return ret;
675 }
676 #endif /* HAVE_ICONV */
677
678 if (output_left >= 0) {
679 if (*out_len > 0) {
680 *((*in_buf)++) = output_left;
681 (*out_len)--;
682 count++;
683 output_left = -1;
684 } else {
685 /* Output Buffer Overflow */
686 return CODECONV_BUFFER_OVERFLOW;
687 }
688 }
689 if (conv_mode == IO_SJIS) {
690 while(*in_len>0) {
691 if (*out_len<=0) break;
692 c1 = *((*in_buf)++) & 0xff;
693 (*in_len)--;
694 if (c1 < 0x80) { /* ASCII ʸ�� */
695 (*out_len)--;
696 count++;
697 *((*out_buf)++)=c1;
698 continue;
699 } else if ((c1 < 0x81 || c1 > 0x9f) && (c1 < 0xe0 || c1 > 0xef)) {
700 /* Ⱦ�ѥ��� */
701 if (0xa1 <= c1 && c1 <= 0xdf) {
702 c2 = c1 - 0x80;
703 c1 = 0x8e;
704 } else {
705 return -1;
706 }
707 } else {
708 c2 = *((*in_buf)++) & 0xff;
709 (*in_len)--;
710 if (c1 > 0x9f)
711 c1 -= 0x40;
712 c1 += c1;
713 if (c2 <= 0x9e) {
714 c1 -= 0xe1;
715 if (c2 >= 0x80)
716 c2 -= 1;
717 c2 -= 0x1f;
718 } else {
719 c1 -= 0xe0;
720 c2 -= 0x7e;
721 }
722 c2 |= 0x80;
723 }
724 *((*out_buf)++) = c1 | 0x80;
725 (*out_len)--;
726 count++;
727 if (*out_len <= 0) {
728 output_left = c2;
729 return CODECONV_BUFFER_OVERFLOW;
730 }
731 *((*out_buf)++) = c2;
732 (*out_len)--;
733 count++;
734 }
735 if (*in_len == 0) return count;
736 if (*out_len == 0) return CODECONV_BUFFER_OVERFLOW;
737 return CODECONV_ERROR;
738 } else { /* IO_EUC */
739 if (*out_len < *in_len) {
740 memcpy(*out_buf,*in_buf,*out_len);
741 count = *out_len;
742 (*out_buf) += *out_len;
743 (*in_buf) += *out_len;
744 (*in_len) -= *out_len;
745 *out_len = 0;
746 return CODECONV_BUFFER_OVERFLOW;
747 } else {
748 memcpy(*out_buf,*in_buf,*in_len);
749 count = *in_len;
750 (*out_buf)+=*in_len;
751 (*in_buf)+=*in_len;
752 (*out_len)-=*in_len;
753 *in_len=0;
754 return count;
755 }
756 }
757 return CODECONV_ERROR; /* Never */
758 }
759
euc_to_current(in_buf,in_len,out_buf,out_len)760 size_t euc_to_current (in_buf,in_len,out_buf,out_len)
761 char **in_buf, **out_buf;
762 size_t *in_len,*out_len;
763 {
764 static int output_left = -1;
765 int c1, c2;
766 size_t count = 0;
767
768 #ifdef HAVE_ICONV
769 if (conv_mode == IO_ICONV) {
770 size_t ret;
771 if (euc_to_cur == (iconv_t) -1)
772 return CODECONV_ERROR;
773 ret = iconv(euc_to_cur,in_buf,in_len,out_buf,out_len);
774 if (ret != ((size_t)-1))
775 ret = iconv(euc_to_cur,NULL,in_len,out_buf,out_len);
776 #if defined (HAVE_ERRNO_H) && defined (E2BIG)
777 if (ret == ((size_t)-1)) {
778 if (errno == E2BIG)
779 return CODECONV_BUFFER_OVERFLOW;
780 return CODECONV_ERROR;
781 }
782 #endif /* HAVE_ERRNO_H / E2BIG */
783 return ret;
784 }
785 #endif /* HAVE_ICONV */
786
787 if (output_left >= 0) {
788 if (*out_len > 0) {
789 *((*in_buf)++) = output_left;
790 (*out_len)--;
791 count++;
792 output_left = -1;
793 } else {
794 /* Output Buffer Overflow */
795 return CODECONV_BUFFER_OVERFLOW;
796 }
797 }
798 if (conv_mode == IO_SJIS) {
799 while(*in_len>0) {
800 if (*out_len<=0) break;
801 c1 = *((*in_buf)++) & 0xff;
802 (*in_len)--;
803 if ((c1 & 0x80) == 0) {
804 *((*out_buf)++) = c1;
805 (*out_len)--;
806 count++;
807 continue;
808 }
809 if (0x8e == c1) {
810 *((*out_buf)++) = *((*in_buf)++) | 0x80;
811 (*in_len)--;
812 (*out_len)--;
813 count++;
814 continue;
815 }
816 c1 &= 0x7f;
817 c2 = *((*in_buf)++) & 0x7f;
818 (*in_len)--;
819 if (c1 & 0x01) {
820 c2 += 0x1f;
821 if (c2 > 0x7e)
822 c2++;
823 } else {
824 c2 += 0x7e;
825 }
826 c1 = (c1 + 0xe1) >> 1;
827 if (c1 > 0x9f)
828 c1 += 0x40;
829 *((*out_buf)++) = c1;
830 (*out_len)--;
831 count++;
832 if (*out_len <= 0) {
833 output_left = c2;
834 return CODECONV_BUFFER_OVERFLOW;
835 }
836 *((*out_buf)++) = c2;
837 (*out_len)--;
838 count++;
839 }
840 if (*in_len == 0) return count;
841 if (*out_len == 0) return CODECONV_BUFFER_OVERFLOW;
842 return CODECONV_ERROR;
843 } else { /* IO_EUC */
844 if (*out_len < *in_len) {
845 memcpy(*out_buf,*in_buf,*out_len);
846 count = *out_len;
847 (*out_buf)+=*out_len;
848 (*in_buf)+=*out_len;
849 (*in_len)-=*out_len;
850 *out_len=0;
851 return CODECONV_BUFFER_OVERFLOW;
852 } else {
853 memcpy(*out_buf,*in_buf,*in_len);
854 count = *in_len;
855 (*out_buf)+=*in_len;
856 (*in_buf)+=*in_len;
857 (*out_len)-=*in_len;
858 *in_len=0;
859 return count;
860 }
861 }
862 return CODECONV_ERROR; /* Never */
863 }
864
865