eb/libebutils/puts_eucjp.c
2016-10-28 20:02:30 -07:00

156 lines
4.1 KiB
C

/* -*- C -*-
* Copyright (c) 2003-2006 Motoyuki Kasahara
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_ICONV_H
#include <iconv.h>
#endif
#if defined(HAVE_LIBCHARSET_H)
#include <libcharset.h>
#elif defined(HAVE_LANGINFO_H)
#include <langinfo.h>
#endif
/*
* Convert `string' from EUC-JP to the current locale encoding, and
* then write it to `stream'.
*/
int
fputs_eucjp_to_locale(const char *string, FILE *stream)
{
#if defined(HAVE_ICONV_OPEN)
size_t string_length;
const char *locale_encoding;
char *buffer = NULL;
size_t buffer_size;
iconv_t cd = (iconv_t)-1;
const char *in_p;
char *out_p;
size_t in_left;
size_t out_left;
int fputs_result;
string_length = strlen(string);
#if defined(HAVE_LOCALE_CHARSET)
locale_encoding = locale_charset();
#elif defined(HAVE_NL_LANGINFO) && defined(CODESET)
locale_encoding = nl_langinfo(CODESET);
#else
locale_encoding = NULL;
#endif
if (locale_encoding == NULL)
goto failed;
cd = iconv_open(locale_encoding, "eucJP");
if (cd == (iconv_t)-1)
cd = iconv_open(locale_encoding, "EUC-JP");
if (cd == (iconv_t)-1)
goto failed;
buffer_size = (string_length + 1) * 2;
for (;;) {
buffer = malloc(buffer_size);
if (buffer == NULL)
goto failed;
in_p = string;
in_left = string_length + 1;
out_p = buffer;
out_left = buffer_size;
if (iconv(cd, &in_p, &in_left, &out_p, &out_left) != -1)
break;
if (errno == E2BIG) {
/*
* Reset initial state.
* To avoid a bug of iconv() on Solaris 2.6, we set `in_left',
* `out_p' and `out_left' to non-NULL values.
*/
in_left = 0;
out_p = buffer;
out_left = 0;
iconv(cd, NULL, &in_left, &out_p, &out_left);
free(buffer);
buffer = NULL;
buffer_size += string_length + 1;
continue;
} else {
goto failed;
}
}
iconv_close(cd);
fputs_result = fputs(buffer, stream);
free(buffer);
return fputs_result;
/*
* An error occurs...
*/
failed:
if (cd != (iconv_t)-1)
iconv_close(cd);
if (buffer != NULL)
free(buffer);
return fputs(string, stream);
#else /* not HAVE_ICONV_OPEN */
return fputs(string, stream);
#endif /* not HAVE_ICONV_OPEN */
}
/*
* Convert `string' from EUC-JP to the current locale encoding, and
* then write it and a newline to `stdout'.
*/
int
puts_eucjp_to_locale(const char *string)
{
if (fputs_eucjp_to_locale(string, stdout) == EOF)
return EOF;
if (fputs_eucjp_to_locale("\n", stdout) == EOF)
return EOF;
return 0;
}