OSDN Git Service

* refine file structure.
[nkf/nkf.git] / nkf.c
diff --git a/nkf.c b/nkf.c
index 43172a4..e265e78 100644 (file)
--- a/nkf.c
+++ b/nkf.c
  * \e$B8=:_!"\e(Bnkf \e$B$O\e(B SorceForge \e$B$K$F%a%s%F%J%s%9$,B3$1$i$l$F$$$^$9!#\e(B
  * http://sourceforge.jp/projects/nkf/
 ***********************************************************************/
-/* $Id: nkf.c,v 1.151 2007/12/06 20:13:58 naruse Exp $ */
+#define NKF_IDENT "$Id: nkf.c,v 1.166 2008/01/23 09:10:25 naruse Exp $"
 #define NKF_VERSION "2.0.8"
-#define NKF_RELEASE_DATE "2007-12-07"
+#define NKF_RELEASE_DATE "2008-01-23"
 #define COPY_RIGHT \
     "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),2000 S. Kono, COW\n" \
-    "Copyright (C) 2002-2007 Kono, Furukawa, Naruse, mastodon"
+    "Copyright (C) 2002-2008 Kono, Furukawa, Naruse, mastodon"
 
 #include "config.h"
+#include "nkf.h"
 #include "utf8tbl.h"
 
-#ifndef MIME_DECODE_DEFAULT
-#define MIME_DECODE_DEFAULT STRICT_MIME
-#endif
-#ifndef X0201_DEFAULT
-#define X0201_DEFAULT TRUE
-#endif
-
-#if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C) || defined(__MINGW32__) || defined(__EMX__) || defined(__MSDOS__) || defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)) && !defined(MSDOS)
-#define MSDOS
-#if (defined(__Win32__) || defined(_WIN32)) && !defined(__WIN32__)
-#define __WIN32__
-#endif
-#endif
-
-#ifdef PERL_XS
-#undef OVERWRITE
-#endif
-
-#ifndef PERL_XS
-#include <stdio.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(MSDOS) || defined(__OS2__)
-#include <fcntl.h>
-#include <io.h>
-#if defined(_MSC_VER) || defined(__WATCOMC__)
-#define mktemp _mktemp
-#endif
-#endif
-
-#ifdef MSDOS
-#ifdef LSI_C
-#define setbinmode(fp) fsetbin(fp)
-#elif defined(__DJGPP__)
-#include <libc/dosio.h>
-#define setbinmode(fp) djgpp_setbinmode(fp)
-#else /* Microsoft C, Turbo C */
-#define setbinmode(fp) setmode(fileno(fp), O_BINARY)
-#endif
-#else /* UNIX */
-#define setbinmode(fp)
-#endif
-
-#if defined(__DJGPP__)
-void  djgpp_setbinmode(FILE *fp)
-{
-    /* we do not use libc's setmode(), which changes COOKED/RAW mode in device. */
-    int fd, m;
-    fd = fileno(fp);
-    m = (__file_handle_modes[fd] & (~O_TEXT)) | O_BINARY;
-    __file_handle_set(fd, m);
-}
-#endif
-
-#ifdef _IOFBF /* SysV and MSDOS, Windows */
-#define       setvbuffer(fp, buf, size)       setvbuf(fp, buf, _IOFBF, size)
-#else /* BSD */
-#define       setvbuffer(fp, buf, size)       setbuffer(fp, buf, size)
-#endif
-
-/*Borland C++ 4.5 EasyWin*/
-#if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */
-#define         EASYWIN
-#ifndef __WIN16__
-#define __WIN16__
-#endif
-#include <windows.h>
-#endif
-
-#ifdef OVERWRITE
-/* added by satoru@isoternet.org */
-#if defined(__EMX__)
-#include <sys/types.h>
-#endif
-#include <sys/stat.h>
-#if !defined(MSDOS) || defined(__DJGPP__) /* UNIX, djgpp */
-#include <unistd.h>
-#if defined(__WATCOMC__)
-#include <sys/utime.h>
-#else
-#include <utime.h>
-#endif
-#else /* defined(MSDOS) */
-#ifdef __WIN32__
-#ifdef __BORLANDC__ /* BCC32 */
-#include <utime.h>
-#else /* !defined(__BORLANDC__) */
-#include <sys/utime.h>
-#endif /* (__BORLANDC__) */
-#else /* !defined(__WIN32__) */
-#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__WATCOMC__) || defined(__OS2__) || defined(__EMX__) || defined(__IBMC__) || defined(__IBMCPP__)  /* VC++, MinGW, Watcom, emx+gcc, IBM VAC++ */
-#include <sys/utime.h>
-#elif defined(__TURBOC__) /* BCC */
-#include <utime.h>
-#elif defined(LSI_C) /* LSI C */
-#endif /* (__WIN32__) */
-#endif
-#endif
-#endif
-
-#define         FALSE   0
-#define         TRUE    1
-
 /* state of output_mode and input_mode
 
    c2           0 means ASCII
-                X0201
-                ISO8859_1
-                X0208
+                JIS_X_0201
+                ISO_8859_1
+                JIS_X_0208
                 EOF      all termination
    c1           32bit data
 
  */
 
-#define         ASCII           0
-#define         X0208           1
-#define         X0201           2
-#define         ISO8859_1       8
-#define         X0212      0x2844
-#define         X0213_1    0x284F
-#define         X0213_2    0x2850
-
-/* Input Assumption */
+/* MIME ENCODE */
 
-#define         JIS_INPUT       4
-#define         EUC_INPUT      16
-#define         SJIS_INPUT      5
-#define         LATIN1_INPUT    6
 #define         FIXED_MIME      7
 #define         STRICT_MIME     8
 
-/* MIME ENCODE */
-
-#define                ISO2022JP       9
-#define        JAPANESE_EUC   10
-#define                SHIFT_JIS      11
-
-#define                UTF8           12
-#define                UTF8_INPUT     13
-#define                UTF16_INPUT    1015
-#define                UTF32_INPUT    1017
-
 /* byte order */
-
-#define                ENDIAN_BIG      1234
-#define                ENDIAN_LITTLE   4321
-#define                ENDIAN_2143     2143
-#define                ENDIAN_3412     3412
+enum byte_order {
+    ENDIAN_BIG    = 1,
+    ENDIAN_LITTLE = 2,
+    ENDIAN_2143   = 3,
+    ENDIAN_3412   = 4
+};
 
 /* ASCII CODE */
 
@@ -209,6 +82,184 @@ void  djgpp_setbinmode(FILE *fp)
 #define         SS3     0x8f
 #define         CRLF    0x0D0A
 
+
+/* encodings */
+
+enum nkf_encodings {
+    ASCII,
+    ISO_8859_1,
+    ISO_2022_JP,
+    CP50220,
+    CP50221,
+    CP50222,
+    ISO_2022_JP_1,
+    ISO_2022_JP_3,
+    SHIFT_JIS,
+    WINDOWS_31J,
+    CP10001,
+    EUC_JP,
+    CP51932,
+    EUCJP_MS,
+    EUCJP_ASCII,
+    SHIFT_JISX0213,
+    SHIFT_JIS_2004,
+    EUC_JISX0213,
+    EUC_JIS_2004,
+    UTF_8,
+    UTF_8N,
+    UTF_8_BOM,
+    UTF8_MAC,
+    UTF_16,
+    UTF_16BE,
+    UTF_16BE_BOM,
+    UTF_16LE,
+    UTF_16LE_BOM,
+    UTF_32,
+    UTF_32BE,
+    UTF_32BE_BOM,
+    UTF_32LE,
+    UTF_32LE_BOM,
+    NKF_ENCODING_TABLE_SIZE,
+    JIS_X_0201=0x1000,
+    JIS_X_0208=0x1001,
+    JIS_X_0212=0x1002,
+    JIS_X_0213_1=0x1003,
+    JIS_X_0213_2=0x1004,
+    BINARY
+};
+
+nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
+nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
+nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0);
+nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0);
+nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0);
+void j_oconv(nkf_char c2, nkf_char c1);
+void s_oconv(nkf_char c2, nkf_char c1);
+void e_oconv(nkf_char c2, nkf_char c1);
+void w_oconv(nkf_char c2, nkf_char c1);
+void w_oconv16(nkf_char c2, nkf_char c1);
+void w_oconv32(nkf_char c2, nkf_char c1);
+
+typedef struct {
+    const char *name;
+    nkf_char (*iconv)(nkf_char c2, nkf_char c1, nkf_char c0);
+    void (*oconv)(nkf_char c2, nkf_char c1);
+} nkf_native_encoding;
+
+nkf_native_encoding NkfEncodingASCII =         { "ASCII", e_iconv, e_oconv };
+nkf_native_encoding NkfEncodingISO_2022_JP =   { "ISO-2022-JP", e_iconv, j_oconv };
+nkf_native_encoding NkfEncodingShift_JIS =     { "Shift_JIS", s_iconv, s_oconv };
+nkf_native_encoding NkfEncodingEUC_JP =                { "EUC-JP", e_iconv, e_oconv };
+nkf_native_encoding NkfEncodingUTF_8 =         { "UTF-8", w_iconv, w_oconv };
+nkf_native_encoding NkfEncodingUTF_16 =                { "UTF-16", w_iconv16, w_oconv16 };
+nkf_native_encoding NkfEncodingUTF_32 =                { "UTF-32", w_iconv32, w_oconv32 };
+
+typedef struct {
+    const int id;
+    const char *name;
+    const nkf_native_encoding *base_encoding;
+} nkf_encoding;
+
+nkf_encoding nkf_encoding_table[] = {
+    {ASCII,            "US-ASCII",             &NkfEncodingASCII},
+    {ISO_8859_1,       "ISO-8859-1",           &NkfEncodingASCII},
+    {ISO_2022_JP,      "ISO-2022-JP",          &NkfEncodingISO_2022_JP},
+    {CP50220,          "CP50220",              &NkfEncodingISO_2022_JP},
+    {CP50221,          "CP50221",              &NkfEncodingISO_2022_JP},
+    {CP50222,          "CP50222",              &NkfEncodingISO_2022_JP},
+    {ISO_2022_JP_1,    "ISO-2022-JP-1",        &NkfEncodingISO_2022_JP},
+    {ISO_2022_JP_3,    "ISO-2022-JP-3",        &NkfEncodingISO_2022_JP},
+    {SHIFT_JIS,                "Shift_JIS",            &NkfEncodingShift_JIS},
+    {WINDOWS_31J,      "Windows-31J",          &NkfEncodingShift_JIS},
+    {CP10001,          "CP10001",              &NkfEncodingShift_JIS},
+    {EUC_JP,           "EUC-JP",               &NkfEncodingEUC_JP},
+    {CP51932,          "CP51932",              &NkfEncodingEUC_JP},
+    {EUCJP_MS,         "eucJP-MS",             &NkfEncodingEUC_JP},
+    {EUCJP_ASCII,      "eucJP-ASCII",          &NkfEncodingEUC_JP},
+    {SHIFT_JISX0213,   "Shift_JISX0213",       &NkfEncodingShift_JIS},
+    {SHIFT_JIS_2004,   "Shift_JIS-2004",       &NkfEncodingShift_JIS},
+    {EUC_JISX0213,     "EUC-JISX0213",         &NkfEncodingEUC_JP},
+    {EUC_JIS_2004,     "EUC-JIS-2004",         &NkfEncodingEUC_JP},
+    {UTF_8,            "UTF-8",                &NkfEncodingUTF_8},
+    {UTF_8N,           "UTF-8N",               &NkfEncodingUTF_8},
+    {UTF_8_BOM,                "UTF-8-BOM",            &NkfEncodingUTF_8},
+    {UTF8_MAC,         "UTF8-MAC",             &NkfEncodingUTF_8},
+    {UTF_16,           "UTF-16",               &NkfEncodingUTF_16},
+    {UTF_16BE,         "UTF-16BE",             &NkfEncodingUTF_16},
+    {UTF_16BE_BOM,     "UTF-16BE-BOM",         &NkfEncodingUTF_16},
+    {UTF_16LE,         "UTF-16LE",             &NkfEncodingUTF_16},
+    {UTF_16LE_BOM,     "UTF-16LE-BOM",         &NkfEncodingUTF_16},
+    {UTF_32,           "UTF-32",               &NkfEncodingUTF_32},
+    {UTF_32BE,         "UTF-32BE",             &NkfEncodingUTF_32},
+    {UTF_32BE_BOM,     "UTF-32BE-BOM",         &NkfEncodingUTF_32},
+    {UTF_32LE,         "UTF-32LE",             &NkfEncodingUTF_32},
+    {UTF_32LE_BOM,     "UTF-32LE-BOM",         &NkfEncodingUTF_32},
+    {BINARY,           "BINARY",               &NkfEncodingASCII},
+    {-1,               NULL,                   NULL}
+};
+
+struct {
+    const char *name;
+    const int id;
+} encoding_name_to_id_table[] = {
+    {"US-ASCII",               ASCII},
+    {"ASCII",                  ASCII},
+    {"ISO-2022-JP",            ISO_2022_JP},
+    {"ISO2022JP-CP932",                CP50220},
+    {"CP50220",                        CP50220},
+    {"CP50221",                        CP50221},
+    {"CP50222",                        CP50222},
+    {"ISO-2022-JP-1",          ISO_2022_JP_1},
+    {"ISO-2022-JP-3",          ISO_2022_JP_3},
+    {"SHIFT_JIS",              SHIFT_JIS},
+    {"SJIS",                   SHIFT_JIS},
+    {"WINDOWS-31J",            WINDOWS_31J},
+    {"CSWINDOWS31J",           WINDOWS_31J},
+    {"CP932",                  WINDOWS_31J},
+    {"MS932",                  WINDOWS_31J},
+    {"CP10001",                        CP10001},
+    {"EUCJP",                  EUC_JP},
+    {"EUC-JP",                 EUC_JP},
+    {"CP51932",                        CP51932},
+    {"EUC-JP-MS",              EUCJP_MS},
+    {"EUCJP-MS",               EUCJP_MS},
+    {"EUCJPMS",                        EUCJP_MS},
+    {"EUC-JP-ASCII",           EUCJP_ASCII},
+    {"EUCJP-ASCII",            EUCJP_ASCII},
+    {"SHIFT_JISX0213",         SHIFT_JISX0213},
+    {"SHIFT_JIS-2004",         SHIFT_JIS_2004},
+    {"EUC-JISX0213",           EUC_JISX0213},
+    {"EUC-JIS-2004",           EUC_JIS_2004},
+    {"UTF-8",                  UTF_8},
+    {"UTF-8N",                 UTF_8N},
+    {"UTF-8-BOM",              UTF_8_BOM},
+    {"UTF8-MAC",               UTF8_MAC},
+    {"UTF-8-MAC",              UTF8_MAC},
+    {"UTF-16",                 UTF_16},
+    {"UTF-16BE",               UTF_16BE},
+    {"UTF-16BE-BOM",           UTF_16BE_BOM},
+    {"UTF-16LE",               UTF_16LE},
+    {"UTF-16LE-BOM",           UTF_16LE_BOM},
+    {"UTF-32",                 UTF_32},
+    {"UTF-32BE",               UTF_32BE},
+    {"UTF-32BE-BOM",           UTF_32BE_BOM},
+    {"UTF-32LE",               UTF_32LE},
+    {"UTF-32LE-BOM",           UTF_32LE_BOM},
+    {"BINARY",                 BINARY},
+    {NULL,                     -1}
+};
+
+#if defined(DEFAULT_CODE_JIS)
+#define            DEFAULT_ENCIDX ISO_2022_JP
+#elif defined(DEFAULT_CODE_SJIS)
+#define            DEFAULT_ENCIDX SHIFT_JIS
+#elif defined(DEFAULT_CODE_EUC)
+#define            DEFAULT_ENCIDX EUC_JP
+#elif defined(DEFAULT_CODE_UTF8)
+#define            DEFAULT_ENCIDX UTF_8
+#endif
+
+
 #define                is_alnum(c)  \
             (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))
 
@@ -232,10 +283,6 @@ void  djgpp_setbinmode(FILE *fp)
     ((c > SP) && (c < DEL) && (c != '?') && (c != '=') && (c != '_') \
      && (c != '(') && (c != ')') && (c != '.') && (c != 0x22)))
 
-#define CP932_TABLE_BEGIN 0xFA
-#define CP932_TABLE_END   0xFC
-#define CP932INV_TABLE_BEGIN 0xED
-#define CP932INV_TABLE_END   0xEE
 #define is_ibmext_in_sjis(c2) (CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END)
 
 #define         HOLD_SIZE       1024
@@ -248,23 +295,12 @@ void  djgpp_setbinmode(FILE *fp)
 #define         DEFAULT_J       'B'
 #define         DEFAULT_R       'B'
 
-#define         SJ0162  0x00e1          /* 01 - 62 ku offset */
-#define         SJ6394  0x0161          /* 63 - 94 ku offset */
 
 #define         RANGE_NUM_MAX   18
 #define         GETA1   0x22
 #define         GETA2   0x2e
 
 
-#if defined(UTF8_OUTPUT_ENABLE) || defined(UTF8_INPUT_ENABLE)
-#define sizeof_euc_to_utf8_1byte 94
-#define sizeof_euc_to_utf8_2bytes 94
-#define sizeof_utf8_to_euc_C2 64
-#define sizeof_utf8_to_euc_E5B8 64
-#define sizeof_utf8_to_euc_2bytes 112
-#define sizeof_utf8_to_euc_3bytes 16
-#endif
-
 /* MIME preprocessor */
 
 #ifdef EASYWIN /*Easy Win */
@@ -283,10 +319,10 @@ struct input_code{
 };
 
 static char *input_codename = NULL; /* NULL: unestablished, "": BINARY */
+static nkf_encoding *input_encoding = NULL;
+static nkf_encoding *output_encoding = NULL;
+static void set_output_encoding(nkf_encoding *enc);
 
-#ifndef PERL_XS
-static const char *CopyRight = COPY_RIGHT;
-#endif
 #if !defined(PERL_XS) && !defined(WIN32DLL)
 static  nkf_char     noconvert(FILE *f);
 #endif
@@ -295,9 +331,7 @@ static  nkf_char     kanji_convert(FILE *f);
 static  nkf_char     h_conv(FILE *f,nkf_char c2,nkf_char c1);
 static  nkf_char     push_hold_buf(nkf_char c2);
 static  void    set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0));
-static  nkf_char     s_iconv(nkf_char c2,nkf_char c1,nkf_char c0);
 static  nkf_char     s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1);
-static  nkf_char     e_iconv(nkf_char c2,nkf_char c1,nkf_char c0);
 #if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
 /* UCS Mapping
  * 0: Shift_JIS, eucJP-ascii
@@ -326,9 +360,6 @@ static  void    encode_fallback_perl(nkf_char c);
 static  void    encode_fallback_subchar(nkf_char c);
 static  void    (*encode_fallback)(nkf_char c) = NULL;
 static  nkf_char     w2e_conv(nkf_char c2,nkf_char c1,nkf_char c0,nkf_char *p2,nkf_char *p1);
-static  nkf_char     w_iconv(nkf_char c2,nkf_char c1,nkf_char c0);
-static  nkf_char     w_iconv16(nkf_char c2,nkf_char c1,nkf_char c0);
-static  nkf_char     w_iconv32(nkf_char c2,nkf_char c1,nkf_char c0);
 static  nkf_char       unicode_to_jis_common(nkf_char c2,nkf_char c1,nkf_char c0,nkf_char *p2,nkf_char *p1);
 static  nkf_char       w_iconv_common(nkf_char c1,nkf_char c0,const unsigned short *const *pp,nkf_char psize,nkf_char *p2,nkf_char *p1);
 static  void    w16w_conv(nkf_char val, nkf_char *p2, nkf_char *p1, nkf_char *p0);
@@ -340,14 +371,8 @@ static  void    w_status(struct input_code *, nkf_char);
 static  int     output_bom_f = FALSE;
 static  int     output_endian = ENDIAN_BIG;
 static  nkf_char     e2w_conv(nkf_char c2,nkf_char c1);
-static  void    w_oconv(nkf_char c2,nkf_char c1);
-static  void    w_oconv16(nkf_char c2,nkf_char c1);
-static  void    w_oconv32(nkf_char c2,nkf_char c1);
 #endif
-static  void    e_oconv(nkf_char c2,nkf_char c1);
 static  nkf_char     e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1);
-static  void    s_oconv(nkf_char c2,nkf_char c1);
-static  void    j_oconv(nkf_char c2,nkf_char c1);
 static  void    fold_conv(nkf_char c2,nkf_char c1);
 static  void    nl_conv(nkf_char c2,nkf_char c1);
 static  void    z_conv(nkf_char c2,nkf_char c1);
@@ -388,7 +413,6 @@ static  void    eof_mime(void);
 static  void    mimeout_addchar(nkf_char c);
 #ifndef PERL_XS
 static  void    usage(void);
-static  void    version(void);
 static  void    show_configuration(void);
 #endif
 static  void    options(unsigned char *c);
@@ -421,7 +445,6 @@ static int             nop_f = FALSE;
 static int             binmode_f = TRUE;       /* binary mode */
 static int             rot_f = FALSE;          /* rot14/43 mode */
 static int             hira_f = FALSE;          /* hira/kata henkan */
-static int             input_f = FALSE;        /* non fixed input code  */
 static int             alpha_f = FALSE;        /* convert JIx0208 alphbet to ASCII */
 static int             mime_f = MIME_DECODE_DEFAULT;   /* convert MIME B base64 or Q */
 static int             mime_decode_f = FALSE;  /* mime decode is explicitly on */
@@ -454,11 +477,6 @@ static nkf_char url_getc(FILE *f);
 static nkf_char url_ungetc(nkf_char c,FILE *f);
 #endif
 
-#if defined(INT_IS_SHORT)
-#define NKF_INT32_C(n)   (n##L)
-#else
-#define NKF_INT32_C(n)   (n)
-#endif
 #define PREFIX_EUCG3   NKF_INT32_C(0x8F00)
 #define CLASS_MASK     NKF_INT32_C(0xFF000000)
 #define CLASS_UNICODE  NKF_INT32_C(0x01000000)
@@ -557,27 +575,9 @@ static unsigned char   ascii_intro = DEFAULT_R;
 
 static int             fold_margin  = FOLD_MARGIN;
 
-/* converters */
-
-#ifdef DEFAULT_CODE_JIS
-#   define  DEFAULT_CONV j_oconv
-#endif
-#ifdef DEFAULT_CODE_SJIS
-#   define  DEFAULT_CONV s_oconv
-#endif
-#ifdef DEFAULT_CODE_EUC
-#   define  DEFAULT_CONV e_oconv
-#endif
-#ifdef DEFAULT_CODE_UTF8
-#   define  DEFAULT_CONV w_oconv
-#endif
-
 /* process default */
-static void (*output_conv)(nkf_char c2,nkf_char c1) = DEFAULT_CONV;
-
-static void (*oconv)(nkf_char c2,nkf_char c1) = no_connection;
-/* s_iconv or oconv */
 static nkf_char (*iconv)(nkf_char c2,nkf_char c1,nkf_char c0) = no_connection2;
+static void (*oconv)(nkf_char c2,nkf_char c1) = no_connection;
 
 static void (*o_zconv)(nkf_char c2,nkf_char c1) = no_connection;
 static void (*o_fconv)(nkf_char c2,nkf_char c1) = no_connection;
@@ -719,6 +719,105 @@ static int             end_check;
 nkf_char std_gc_buf[STD_GC_BUFSIZE];
 nkf_char std_gc_ndx;
 
+char* nkf_strcpy(const char *str)
+{
+    char* result = malloc(strlen(str) + 1);
+    if (!result){
+       perror(str);
+       return "";
+    }
+    strcpy(result, str);
+    return result;
+}
+
+static void nkf_str_upcase(const char *src, char *dest, size_t length)
+{
+    int i = 0;
+    for (; i < length && src[i]; i++) {
+       dest[i] = nkf_toupper(src[i]);
+    }
+    dest[i] = 0;
+}
+
+static nkf_encoding *nkf_enc_from_index(int idx)
+{
+    if (idx < 0 || NKF_ENCODING_TABLE_SIZE <= idx) {
+       return 0;
+    }
+    return &nkf_encoding_table[idx];
+}
+
+static int nkf_enc_find_index(const char *name)
+{
+    int i, index = -1;
+    if (*name == 'X' && *(name+1) == '-') name += 2;
+    for (i = 0; encoding_name_to_id_table[i].id >= 0; i++) {
+       if (strcmp(name, encoding_name_to_id_table[i].name) == 0) {
+           return encoding_name_to_id_table[i].id;
+       }
+    }
+    return index;
+}
+
+static nkf_encoding *nkf_enc_find(const char *name)
+{
+    int idx = -1;
+    idx = nkf_enc_find_index(name);
+    if (idx < 0) return 0;
+    return nkf_enc_from_index(idx);
+}
+
+#define nkf_enc_name(enc) (enc)->name
+#define nkf_enc_to_index(enc) (enc)->id
+#define nkf_enc_to_base_encoding(enc) (enc)->base_encoding
+#define nkf_enc_to_iconv(enc) nkf_enc_to_base_encoding(enc)->iconv
+#define nkf_enc_to_oconv(enc) nkf_enc_to_base_encoding(enc)->oconv
+#define nkf_enc_asciicompat(enc) (\
+    nkf_enc_to_base_encoding(enc) == &NkfEncodingASCII ||\
+    nkf_enc_to_base_encoding(enc) == &NkfEncodingISO_2022_JP)
+#define nkf_enc_unicode_p(enc) (\
+    nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_8 ||\
+    nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_16 ||\
+    nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_32)
+#define nkf_enc_cp5022x_p(enc) (\
+    nkf_enc_to_index(enc) == CP50220 ||\
+    nkf_enc_to_index(enc) == CP50221 ||\
+    nkf_enc_to_index(enc) == CP50222)
+
+#ifndef DEFAULT_ENCIDX
+static char* nkf_locale_charmap()
+{
+#ifdef HAVE_LANGINFO_H
+    return nl_langinfo(CODESET);
+#elif defined(__WIN32__)
+    return sprintf("CP%d", GetACP());
+#else
+    return NULL;
+#endif
+}
+
+static nkf_encoding* nkf_locale_encoding()
+{
+    nkf_encoding *enc = 0;
+    char *encname = nkf_locale_charmap();
+    if (encname)
+       enc = nkf_enc_find(encname);
+    if (enc < 0) enc = 0;
+    return enc;
+}
+#endif
+
+static nkf_encoding* nkf_default_encoding()
+{
+#ifdef DEFAULT_ENCIDX
+    return nkf_enc_from_index(DEFAULT_ENCIDX);
+#else
+    nkf_encoding *enc = nkf_locale_encoding();
+    if (enc <= 0) enc = nkf_enc_from_index(ISO_2022_JP);
+    return enc;
+#endif
+}
+
 #ifdef WIN32DLL
 #include "nkf32dll.c"
 #elif defined(PERL_XS)
@@ -734,36 +833,11 @@ int main(int argc, char **argv)
 #ifdef EASYWIN /*Easy Win */
     _BufferSize.y = 400;/*Set Scroll Buffer Size*/
 #endif
+    setlocale(LC_CTYPE, "");
 
     for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
         cp = (unsigned char *)*argv;
         options(cp);
-        if (guess_f) {
-#ifdef CHECK_OPTION
-           int debug_f_back = debug_f;
-#endif
-#ifdef EXEC_IO
-           int exec_f_back = exec_f;
-#endif
-#ifdef X0212_ENABLE
-           int x0212_f_back = x0212_f;
-#endif
-           int x0213_f_back = x0213_f;
-           int guess_f_back = guess_f;
-           reinit();
-           guess_f = guess_f_back;
-           mime_f = FALSE;
-#ifdef CHECK_OPTION
-           debug_f = debug_f_back;
-#endif
-#ifdef EXEC_IO
-            exec_f = exec_f_back;
-#endif
-#ifdef X0212_ENABLE
-           x0212_f = x0212_f_back;
-#endif
-           x0213_f = x0213_f_back;
-       }
 #ifdef EXEC_IO
         if (exec_f){
             int fds[2], pid;
@@ -793,6 +867,33 @@ int main(int argc, char **argv)
 #endif
     }
 
+    if (guess_f) {
+#ifdef CHECK_OPTION
+       int debug_f_back = debug_f;
+#endif
+#ifdef EXEC_IO
+       int exec_f_back = exec_f;
+#endif
+#ifdef X0212_ENABLE
+       int x0212_f_back = x0212_f;
+#endif
+       int x0213_f_back = x0213_f;
+       int guess_f_back = guess_f;
+       reinit();
+       guess_f = guess_f_back;
+       mime_f = FALSE;
+#ifdef CHECK_OPTION
+       debug_f = debug_f_back;
+#endif
+#ifdef EXEC_IO
+       exec_f = exec_f_back;
+#endif
+#ifdef X0212_ENABLE
+       x0212_f = x0212_f_back;
+#endif
+       x0213_f = x0213_f_back;
+    }
+
     if (binmode_f == TRUE)
 #if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__))
     if (freopen("","wb",stdout) == NULL)
@@ -830,8 +931,7 @@ int main(int argc, char **argv)
            iconv_for_check = 0;
 #endif
           if ((fin = fopen((origfname = *argv++), "r")) == NULL) {
-              perror(*--argv);
-               *argv++;
+               perror(*(argv-1));
                is_argument_error = TRUE;
                continue;
           } else {
@@ -1064,7 +1164,7 @@ static const struct {
     {"katakana","h2"},
     {"katakana-hiragana","h3"},
     {"guess=", ""},
-    {"guess", "g"},
+    {"guess", "g2"},
     {"cp932", ""},
     {"no-cp932", ""},
 #ifdef X0212_ENABLE
@@ -1118,336 +1218,309 @@ static const struct {
     {"prefix=", ""},
 };
 
-static int option_mode = 0;
-
-void options(unsigned char *cp)
+static void set_input_encoding(nkf_encoding *enc)
 {
-    nkf_char i, j;
-    unsigned char *p;
-    unsigned char *cp_back = NULL;
-    char codeset[32];
-
-    if (option_mode==1)
-       return;
-    while(*cp && *cp++!='-');
-    while (*cp || cp_back) {
-       if(!*cp){
-           cp = cp_back;
-           cp_back = NULL;
-           continue;
-       }
-       p = 0;
-        switch (*cp++) {
-        case '-':  /* literal options */
-           if (!*cp || *cp == SP) {        /* ignore the rest of arguments */
-               option_mode = 1;
-               return;
-           }
-            for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
-                p = (unsigned char *)long_option[i].name;
-                for (j=0;*p && *p != '=' && *p == cp[j];p++, j++);
-               if (*p == cp[j] || cp[j] == SP){
-                   p = &cp[j] + 1;
-                   break;
-               }
-               p = 0;
-            }
-           if (p == 0) {
-               fprintf(stderr, "unknown long option: --%s\n", cp);
-               return;
-           }
-           while(*cp && *cp != SP && cp++);
-            if (long_option[i].alias[0]){
-               cp_back = cp;
-               cp = (unsigned char *)long_option[i].alias;
-           }else{
-                if (strcmp(long_option[i].name, "ic=") == 0){
-                   for (i=0; i < 16 && SP < p[i] && p[i] < DEL; i++){
-                       codeset[i] = nkf_toupper(p[i]);
-                   }
-                   codeset[i] = 0;
-                   if(strcmp(codeset, "ISO-2022-JP") == 0){
-                       input_f = JIS_INPUT;
-                   }else if(strcmp(codeset, "X-ISO2022JP-CP932") == 0 ||
-                     strcmp(codeset, "CP50220") == 0 ||
-                     strcmp(codeset, "CP50221") == 0 ||
-                     strcmp(codeset, "CP50222") == 0){
-                       input_f = JIS_INPUT;
+    switch (nkf_enc_to_index(enc)) {
+    case CP50220:
+    case CP50221:
+    case CP50222:
 #ifdef SHIFTJIS_CP932
-                       cp51932_f = TRUE;
+       cp51932_f = TRUE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_CP932;
+       ms_ucs_map_f = UCS_MAP_CP932;
 #endif
-                   }else if(strcmp(codeset, "ISO-2022-JP-1") == 0){
-                       input_f = JIS_INPUT;
+       break;
+    case ISO_2022_JP_1:
 #ifdef X0212_ENABLE
-                       x0212_f = TRUE;
+       x0212_f = TRUE;
 #endif
-                   }else if(strcmp(codeset, "ISO-2022-JP-3") == 0){
-                       input_f = JIS_INPUT;
+       break;
+    case ISO_2022_JP_3:
 #ifdef X0212_ENABLE
-                       x0212_f = TRUE;
-#endif
-                       x0213_f = TRUE;
-                   }else if(strcmp(codeset, "SHIFT_JIS") == 0){
-                       input_f = SJIS_INPUT;
-                   }else if(strcmp(codeset, "WINDOWS-31J") == 0 ||
-                            strcmp(codeset, "CSWINDOWS31J") == 0 ||
-                            strcmp(codeset, "CP932") == 0 ||
-                            strcmp(codeset, "MS932") == 0){
-                       input_f = SJIS_INPUT;
+       x0212_f = TRUE;
+#endif
+       x0213_f = TRUE;
+       break;
+    case SHIFT_JIS:
+       break;
+    case WINDOWS_31J:
 #ifdef SHIFTJIS_CP932
-                       cp51932_f = TRUE;
+       cp51932_f = TRUE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_CP932;
+       ms_ucs_map_f = UCS_MAP_CP932;
 #endif
-                   }else if(strcmp(codeset, "CP10001") == 0){
-                       input_f = SJIS_INPUT;
+       break;
+    case EUC_JP:
+       break;
+    case CP10001:
 #ifdef SHIFTJIS_CP932
-                       cp51932_f = TRUE;
+       cp51932_f = TRUE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_CP10001;
+       ms_ucs_map_f = UCS_MAP_CP10001;
 #endif
-                   }else if(strcmp(codeset, "EUCJP") == 0 ||
-                            strcmp(codeset, "EUC-JP") == 0){
-                       input_f = EUC_INPUT;
-                   }else if(strcmp(codeset, "CP51932") == 0){
-                       input_f = EUC_INPUT;
+       break;
+    case CP51932:
 #ifdef SHIFTJIS_CP932
-                       cp51932_f = TRUE;
+       cp51932_f = TRUE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_CP932;
+       ms_ucs_map_f = UCS_MAP_CP932;
 #endif
-                   }else if(strcmp(codeset, "EUC-JP-MS") == 0 ||
-                            strcmp(codeset, "EUCJP-MS") == 0 ||
-                            strcmp(codeset, "EUCJPMS") == 0){
-                       input_f = EUC_INPUT;
+       break;
+    case EUCJP_MS:
 #ifdef SHIFTJIS_CP932
-                       cp51932_f = FALSE;
+       cp51932_f = FALSE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_MS;
+       ms_ucs_map_f = UCS_MAP_MS;
 #endif
-                   }else if(strcmp(codeset, "EUC-JP-ASCII") == 0 ||
-                            strcmp(codeset, "EUCJP-ASCII") == 0){
-                       input_f = EUC_INPUT;
+       break;
+    case EUCJP_ASCII:
 #ifdef SHIFTJIS_CP932
-                       cp51932_f = FALSE;
+       cp51932_f = FALSE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_ASCII;
+       ms_ucs_map_f = UCS_MAP_ASCII;
 #endif
-                   }else if(strcmp(codeset, "SHIFT_JISX0213") == 0 ||
-                            strcmp(codeset, "SHIFT_JIS-2004") == 0){
-                       input_f = SJIS_INPUT;
-                       x0213_f = TRUE;
+       break;
+    case SHIFT_JISX0213:
+    case SHIFT_JIS_2004:
+       x0213_f = TRUE;
 #ifdef SHIFTJIS_CP932
-                       cp51932_f = FALSE;
+       cp51932_f = FALSE;
 #endif
-                   }else if(strcmp(codeset, "EUC-JISX0213") == 0 ||
-                            strcmp(codeset, "EUC-JIS-2004") == 0){
-                       input_f = EUC_INPUT;
-                       x0213_f = TRUE;
+       break;
+    case EUC_JISX0213:
+    case EUC_JIS_2004:
+       x0213_f = TRUE;
 #ifdef SHIFTJIS_CP932
-                       cp51932_f = FALSE;
+       cp51932_f = FALSE;
 #endif
+       break;
 #ifdef UTF8_INPUT_ENABLE
-                   }else if(strcmp(codeset, "UTF-8") == 0 ||
-                            strcmp(codeset, "UTF-8N") == 0 ||
-                            strcmp(codeset, "UTF-8-BOM") == 0){
-                       input_f = UTF8_INPUT;
 #ifdef UNICODE_NORMALIZATION
-                   }else if(strcmp(codeset, "UTF8-MAC") == 0 ||
-                            strcmp(codeset, "UTF-8-MAC") == 0){
-                       input_f = UTF8_INPUT;
-                       nfc_f = TRUE;
-#endif
-                   }else if(strcmp(codeset, "UTF-16") == 0 ||
-                            strcmp(codeset, "UTF-16BE") == 0 ||
-                            strcmp(codeset, "UTF-16BE-BOM") == 0){
-                       input_f = UTF16_INPUT;
-                       input_endian = ENDIAN_BIG;
-                   }else if(strcmp(codeset, "UTF-16LE") == 0 ||
-                            strcmp(codeset, "UTF-16LE-BOM") == 0){
-                       input_f = UTF16_INPUT;
-                       input_endian = ENDIAN_LITTLE;
-                   }else if(strcmp(codeset, "UTF-32") == 0 ||
-                            strcmp(codeset, "UTF-32BE") == 0 ||
-                            strcmp(codeset, "UTF-32BE-BOM") == 0){
-                       input_f = UTF32_INPUT;
-                       input_endian = ENDIAN_BIG;
-                   }else if(strcmp(codeset, "UTF-32LE") == 0 ||
-                            strcmp(codeset, "UTF-32LE-BOM") == 0){
-                       input_f = UTF32_INPUT;
-                       input_endian = ENDIAN_LITTLE;
-#endif
-                   } else {
-                       fprintf(stderr, "unknown input encoding: %s\n", codeset);
-                   }
-                    continue;
-               }
-                if (strcmp(long_option[i].name, "oc=") == 0){
-                   x0201_f = FALSE;
-                   for (i=0; i < 16 && SP < p[i] && p[i] < DEL; i++){
-                       codeset[i] = nkf_toupper(p[i]);
-                   }
-                   codeset[i] = 0;
-                   if(strcmp(codeset, "ISO-2022-JP") == 0){
-                       output_conv = j_oconv;
-                   }else if(strcmp(codeset, "X-ISO2022JP-CP932") == 0){
-                       output_conv = j_oconv;
-                       no_cp932ext_f = TRUE;
-#ifdef SHIFTJIS_CP932
-                       cp932inv_f = FALSE;
+    case UTF8_MAC:
+       nfc_f = TRUE;
+       break;
 #endif
-#ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_CP932;
+    case UTF_16:
+    case UTF_16BE:
+    case UTF_16BE_BOM:
+       input_endian = ENDIAN_BIG;
+       break;
+    case UTF_16LE:
+    case UTF_16LE_BOM:
+       input_endian = ENDIAN_LITTLE;
+       break;
+    case UTF_32:
+    case UTF_32BE:
+    case UTF_32BE_BOM:
+       input_endian = ENDIAN_BIG;
+       break;
+    case UTF_32LE:
+    case UTF_32LE_BOM:
+       input_endian = ENDIAN_LITTLE;
+       break;
 #endif
-                   }else if(strcmp(codeset, "CP50220") == 0){
-                       output_conv = j_oconv;
-                       x0201_f = TRUE;
+    }
+}
+
+static void set_output_encoding(nkf_encoding *enc)
+{
+    switch (nkf_enc_to_index(enc)) {
+    case CP50220:
+       x0201_f = TRUE;
 #ifdef SHIFTJIS_CP932
-                       cp932inv_f = FALSE;
+       if (cp932inv_f == TRUE) cp932inv_f = FALSE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_CP932;
+       ms_ucs_map_f = UCS_MAP_CP932;
 #endif
-                   }else if(strcmp(codeset, "CP50221") == 0){
-                       output_conv = j_oconv;
+       break;
+    case CP50221:
 #ifdef SHIFTJIS_CP932
-                       cp932inv_f = FALSE;
+       if (cp932inv_f == TRUE) cp932inv_f = FALSE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_CP932;
+       ms_ucs_map_f = UCS_MAP_CP932;
 #endif
-                   }else if(strcmp(codeset, "ISO-2022-JP-1") == 0){
-                       output_conv = j_oconv;
+       break;
+    case ISO_2022_JP_1:
 #ifdef X0212_ENABLE
-                       x0212_f = TRUE;
+       x0212_f = TRUE;
 #endif
 #ifdef SHIFTJIS_CP932
-                       cp932inv_f = FALSE;
+       if (cp932inv_f == TRUE) cp932inv_f = FALSE;
 #endif
-                   }else if(strcmp(codeset, "ISO-2022-JP-3") == 0){
-                       output_conv = j_oconv;
+       break;
+    case ISO_2022_JP_3:
 #ifdef X0212_ENABLE
-                       x0212_f = TRUE;
+       x0212_f = TRUE;
 #endif
-                       x0213_f = TRUE;
+       x0213_f = TRUE;
 #ifdef SHIFTJIS_CP932
-                       cp932inv_f = FALSE;
-#endif
-                   }else if(strcmp(codeset, "SHIFT_JIS") == 0){
-                       output_conv = s_oconv;
-                   }else if(strcmp(codeset, "WINDOWS-31J") == 0 ||
-                            strcmp(codeset, "CSWINDOWS31J") == 0 ||
-                            strcmp(codeset, "CP932") == 0 ||
-                            strcmp(codeset, "MS932") == 0){
-                       output_conv = s_oconv;
+       if (cp932inv_f == TRUE) cp932inv_f = FALSE;
+#endif
+       break;
+    case SHIFT_JIS:
+       break;
+    case WINDOWS_31J:
+#ifdef UTF8_OUTPUT_ENABLE
+       ms_ucs_map_f = UCS_MAP_CP932;
+#endif
+       break;
+    case CP10001:
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_CP932;
+       ms_ucs_map_f = UCS_MAP_CP10001;
+#endif
+       break;
+    case EUC_JP:
+       x0212_f = TRUE;
+#ifdef SHIFTJIS_CP932
+       if (cp932inv_f == TRUE) cp932inv_f = FALSE;
 #endif
-                   }else if(strcmp(codeset, "CP10001") == 0){
-                       output_conv = s_oconv;
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_CP10001;
+       ms_ucs_map_f = UCS_MAP_CP932;
 #endif
-                   }else if(strcmp(codeset, "EUCJP") == 0 ||
-                            strcmp(codeset, "EUC-JP") == 0){
-                       output_conv = e_oconv;
-                   }else if(strcmp(codeset, "CP51932") == 0){
-                       output_conv = e_oconv;
+       break;
+    case CP51932:
 #ifdef SHIFTJIS_CP932
-                       cp932inv_f = FALSE;
+       if (cp932inv_f == TRUE) cp932inv_f = FALSE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_CP932;
+       ms_ucs_map_f = UCS_MAP_CP932;
 #endif
-                   }else if(strcmp(codeset, "EUC-JP-MS") == 0 ||
-                            strcmp(codeset, "EUCJP-MS") == 0 ||
-                            strcmp(codeset, "EUCJPMS") == 0){
-                       output_conv = e_oconv;
+       break;
+    case EUCJP_MS:
 #ifdef X0212_ENABLE
-                       x0212_f = TRUE;
+       x0212_f = TRUE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_MS;
+       ms_ucs_map_f = UCS_MAP_MS;
 #endif
-                   }else if(strcmp(codeset, "EUC-JP-ASCII") == 0 ||
-                            strcmp(codeset, "EUCJP-ASCII") == 0){
-                       output_conv = e_oconv;
+       break;
+    case EUCJP_ASCII:
 #ifdef X0212_ENABLE
-                       x0212_f = TRUE;
+       x0212_f = TRUE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
-                       ms_ucs_map_f = UCS_MAP_ASCII;
+       ms_ucs_map_f = UCS_MAP_ASCII;
 #endif
-                   }else if(strcmp(codeset, "SHIFT_JISX0213") == 0 ||
-                            strcmp(codeset, "SHIFT_JIS-2004") == 0){
-                       output_conv = s_oconv;
-                       x0213_f = TRUE;
+       break;
+    case SHIFT_JISX0213:
+    case SHIFT_JIS_2004:
+       x0213_f = TRUE;
 #ifdef SHIFTJIS_CP932
-                       cp932inv_f = FALSE;
+       if (cp932inv_f == TRUE) cp932inv_f = FALSE;
 #endif
-                   }else if(strcmp(codeset, "EUC-JISX0213") == 0 ||
-                            strcmp(codeset, "EUC-JIS-2004") == 0){
-                       output_conv = e_oconv;
+       break;
+    case EUC_JISX0213:
+    case EUC_JIS_2004:
 #ifdef X0212_ENABLE
-                       x0212_f = TRUE;
+       x0212_f = TRUE;
 #endif
-                       x0213_f = TRUE;
+       x0213_f = TRUE;
 #ifdef SHIFTJIS_CP932
-                       cp932inv_f = FALSE;
+       if (cp932inv_f == TRUE) cp932inv_f = FALSE;
 #endif
+       break;
 #ifdef UTF8_OUTPUT_ENABLE
-                   }else if(strcmp(codeset, "UTF-8") == 0){
-                       output_conv = w_oconv;
-                   }else if(strcmp(codeset, "UTF-8N") == 0){
-                       output_conv = w_oconv;
-                   }else if(strcmp(codeset, "UTF-8-BOM") == 0){
-                       output_conv = w_oconv;
-                       output_bom_f = TRUE;
-                   }else if(strcmp(codeset, "UTF-16BE") == 0){
-                       output_conv = w_oconv16;
-                   }else if(strcmp(codeset, "UTF-16") == 0 ||
-                            strcmp(codeset, "UTF-16BE-BOM") == 0){
-                       output_conv = w_oconv16;
-                       output_bom_f = TRUE;
-                   }else if(strcmp(codeset, "UTF-16LE") == 0){
-                       output_conv = w_oconv16;
-                       output_endian = ENDIAN_LITTLE;
-                   }else if(strcmp(codeset, "UTF-16LE-BOM") == 0){
-                       output_conv = w_oconv16;
-                       output_endian = ENDIAN_LITTLE;
-                       output_bom_f = TRUE;
-                   }else if(strcmp(codeset, "UTF-32") == 0 ||
-                            strcmp(codeset, "UTF-32BE") == 0){
-                       output_conv = w_oconv32;
-                   }else if(strcmp(codeset, "UTF-32BE-BOM") == 0){
-                       output_conv = w_oconv32;
-                       output_bom_f = TRUE;
-                   }else if(strcmp(codeset, "UTF-32LE") == 0){
-                       output_conv = w_oconv32;
-                       output_endian = ENDIAN_LITTLE;
-                   }else if(strcmp(codeset, "UTF-32LE-BOM") == 0){
-                       output_conv = w_oconv32;
-                       output_endian = ENDIAN_LITTLE;
-                       output_bom_f = TRUE;
+    case UTF_8_BOM:
+       output_bom_f = TRUE;
+       break;
+    case UTF_16:
+    case UTF_16BE_BOM:
+       output_bom_f = TRUE;
+       break;
+    case UTF_16LE:
+       output_endian = ENDIAN_LITTLE;
+       output_bom_f = FALSE;
+       break;
+    case UTF_16LE_BOM:
+       output_endian = ENDIAN_LITTLE;
+       output_bom_f = TRUE;
+       break;
+    case UTF_32BE_BOM:
+       output_bom_f = TRUE;
+       break;
+    case UTF_32LE:
+       output_endian = ENDIAN_LITTLE;
+       output_bom_f = FALSE;
+       break;
+    case UTF_32LE_BOM:
+       output_endian = ENDIAN_LITTLE;
+       output_bom_f = TRUE;
+       break;
 #endif
-                   } else {
-                       fprintf(stderr, "unknown output encoding: %s\n", codeset);
-                   }
+    }
+}
+
+static int option_mode = 0;
+
+void options(unsigned char *cp)
+{
+    nkf_char i, j;
+    unsigned char *p;
+    unsigned char *cp_back = NULL;
+    char codeset[32];
+    nkf_encoding *enc;
+
+    if (option_mode==1)
+       return;
+    while(*cp && *cp++!='-');
+    while (*cp || cp_back) {
+       if(!*cp){
+           cp = cp_back;
+           cp_back = NULL;
+           continue;
+       }
+       p = 0;
+        switch (*cp++) {
+        case '-':  /* literal options */
+           if (!*cp || *cp == SP) {        /* ignore the rest of arguments */
+               option_mode = 1;
+               return;
+           }
+            for (i=0;i<sizeof(long_option)/sizeof(long_option[0]);i++) {
+                p = (unsigned char *)long_option[i].name;
+                for (j=0;*p && *p != '=' && *p == cp[j];p++, j++);
+               if (*p == cp[j] || cp[j] == SP){
+                   p = &cp[j] + 1;
+                   break;
+               }
+               p = 0;
+            }
+           if (p == 0) {
+               fprintf(stderr, "unknown long option: --%s\n", cp);
+               return;
+           }
+           while(*cp && *cp != SP && cp++);
+            if (long_option[i].alias[0]){
+               cp_back = cp;
+               cp = (unsigned char *)long_option[i].alias;
+           }else{
+                if (strcmp(long_option[i].name, "ic=") == 0){
+                   nkf_str_upcase((char *)p, codeset, 32);
+                   enc = nkf_enc_find(codeset);
+                   if (!enc) continue;
+                   input_encoding = enc;
+                    continue;
+               }
+                if (strcmp(long_option[i].name, "oc=") == 0){
+                   nkf_str_upcase((char *)p, codeset, 32);
+                   enc = nkf_enc_find(codeset);
+                   if (enc <= 0) continue;
+                   output_encoding = enc;
                     continue;
                }
                 if (strcmp(long_option[i].name, "guess=") == 0){
-                   if (p[0] == '1') {
-                       guess_f = 2;
-                   } else {
+                   if (p[0] == '0' || p[0] == '1') {
                        guess_f = 1;
+                   } else {
+                       guess_f = 2;
                    }
                     continue;
                 }
@@ -1512,7 +1585,7 @@ void options(unsigned char *cp)
                 if (strcmp(long_option[i].name, "cp932") == 0){
 #ifdef SHIFTJIS_CP932
                     cp51932_f = TRUE;
-                    cp932inv_f = TRUE;
+                    cp932inv_f = -TRUE;
 #endif
 #ifdef UTF8_OUTPUT_ENABLE
                     ms_ucs_map_f = UCS_MAP_CP932;
@@ -1531,7 +1604,7 @@ void options(unsigned char *cp)
                 }
 #ifdef SHIFTJIS_CP932
                 if (strcmp(long_option[i].name, "cp932inv") == 0){
-                    cp932inv_f = TRUE;
+                    cp932inv_f = -TRUE;
                     continue;
                 }
 #endif
@@ -1621,7 +1694,6 @@ void options(unsigned char *cp)
 #endif
 #ifdef UNICODE_NORMALIZATION
                if (strcmp(long_option[i].name, "utf8mac-input") == 0){
-                   input_f = UTF8_INPUT;
                    nfc_f = TRUE;
                    continue;
                }
@@ -1645,8 +1717,8 @@ void options(unsigned char *cp)
         case 't':           /* transparent mode */
             if (*cp=='1') {
                /* alias of -t */
+               cp++;
                nop_f = TRUE;
-               *cp++;
            } else if (*cp=='2') {
                /*
                 * -t with put/get
@@ -1654,25 +1726,24 @@ void options(unsigned char *cp)
                 * nkf -t2MB hoge.bin | nkf -t2mB | diff -s - hoge.bin
                 *
                 */
+               cp++;
                nop_f = 2;
-               *cp++;
             } else
                nop_f = TRUE;
             continue;
         case 'j':           /* JIS output */
         case 'n':
-            output_conv = j_oconv;
+            output_encoding = nkf_enc_from_index(ISO_2022_JP);
             continue;
         case 'e':           /* AT&T EUC output */
-            output_conv = e_oconv;
-            cp932inv_f = FALSE;
+            output_encoding = nkf_enc_from_index(EUC_JP);
             continue;
         case 's':           /* SJIS output */
-            output_conv = s_oconv;
+            output_encoding = nkf_enc_from_index(WINDOWS_31J);
             continue;
         case 'l':           /* ISO8859 Latin-1 support, no conversion */
             iso8859_f = TRUE;  /* Only compatible with ISO-2022-JP */
-            input_f = LATIN1_INPUT;
+            input_encoding = nkf_enc_from_index(ISO_8859_1);
             continue;
         case 'i':           /* Kanji IN ESC-$-@/B */
             if (*cp=='@'||*cp=='B')
@@ -1713,19 +1784,24 @@ void options(unsigned char *cp)
 #ifdef UTF8_OUTPUT_ENABLE
         case 'w':           /* UTF-8 output */
             if (cp[0] == '8') {
-               output_conv = w_oconv; cp++;
+               cp++;
                if (cp[0] == '0'){
                    cp++;
+                   output_encoding = nkf_enc_from_index(UTF_8N);
                } else {
                    output_bom_f = TRUE;
+                   output_encoding = nkf_enc_from_index(UTF_8_BOM);
                }
            } else {
+               int enc_idx;
                if ('1'== cp[0] && '6'==cp[1]) {
-                   output_conv = w_oconv16; cp+=2;
+                   cp += 2;
+                   enc_idx = UTF_16;
                } else if ('3'== cp[0] && '2'==cp[1]) {
-                   output_conv = w_oconv32; cp+=2;
+                   cp += 2;
+                   enc_idx = UTF_32;
                } else {
-                   output_conv = w_oconv;
+                   output_encoding = nkf_enc_from_index(UTF_8);
                    continue;
                }
                if (cp[0]=='L') {
@@ -1734,13 +1810,21 @@ void options(unsigned char *cp)
                } else if (cp[0] == 'B') {
                    cp++;
                 } else {
+                   output_encoding = nkf_enc_from_index(enc_idx);
                    continue;
                 }
                if (cp[0] == '0'){
                    cp++;
+                   enc_idx = enc_idx == UTF_16
+                       ? (output_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
+                       : (output_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE);
                } else {
                    output_bom_f = TRUE;
+                   enc_idx = enc_idx == UTF_16
+                       ? (output_endian == ENDIAN_LITTLE ? UTF_16LE_BOM : UTF_16BE_BOM)
+                       : (output_endian == ENDIAN_LITTLE ? UTF_32LE_BOM : UTF_32BE_BOM);
                }
+               output_encoding = nkf_enc_from_index(enc_idx);
            }
             continue;
 #endif
@@ -1748,18 +1832,19 @@ void options(unsigned char *cp)
         case 'W':           /* UTF input */
            if (cp[0] == '8') {
                cp++;
-               input_f = UTF8_INPUT;
+               input_encoding = nkf_enc_from_index(UTF_8);
            }else{
+               int enc_idx;
                if ('1'== cp[0] && '6'==cp[1]) {
                    cp += 2;
-                   input_f = UTF16_INPUT;
                    input_endian = ENDIAN_BIG;
+                   enc_idx = UTF_16;
                } else if ('3'== cp[0] && '2'==cp[1]) {
                    cp += 2;
-                   input_f = UTF32_INPUT;
                    input_endian = ENDIAN_BIG;
+                   enc_idx = UTF_32;
                } else {
-                   input_f = UTF8_INPUT;
+                   input_encoding = nkf_enc_from_index(UTF_8);
                    continue;
                }
                if (cp[0]=='L') {
@@ -1767,20 +1852,25 @@ void options(unsigned char *cp)
                    input_endian = ENDIAN_LITTLE;
                } else if (cp[0] == 'B') {
                    cp++;
+                   input_endian = ENDIAN_BIG;
                }
+               enc_idx = enc_idx == UTF_16
+                   ? (output_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
+                   : (output_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE);
+               input_encoding = nkf_enc_from_index(enc_idx);
            }
             continue;
 #endif
         /* Input code assumption */
-        case 'J':   /* JIS input */
-            input_f = JIS_INPUT;
-            continue;
-        case 'E':   /* AT&T EUC input */
-            input_f = EUC_INPUT;
-            continue;
-        case 'S':   /* MS Kanji input */
-            input_f = SJIS_INPUT;
-            continue;
+       case 'J':   /* ISO-2022-JP input */
+           input_encoding = nkf_enc_from_index(ISO_2022_JP);
+           continue;
+       case 'E':   /* EUC-JP input */
+           input_encoding = nkf_enc_from_index(EUC_JP);
+           continue;
+       case 'S':   /* Windows-31J input */
+           input_encoding = nkf_enc_from_index(WINDOWS_31J);
+           continue;
         case 'Z':   /* Convert X0208 alphabet to asii */
             /* alpha_f
               bit:0   Convert JIS X 0208 Alphabet to ASCII
@@ -1842,6 +1932,8 @@ void options(unsigned char *cp)
             } else if (*cp=='0') {
                 mime_decode_f = FALSE;
                 mime_f = FALSE; cp++;
+            } else {
+                mime_f = STRICT_MIME;
             }
             continue;
         case 'M':   /* MIME output */
@@ -1892,10 +1984,10 @@ void options(unsigned char *cp)
             continue;
 #ifndef PERL_XS
         case 'g':
-            if (*cp == '1') {
+            if ('2' <= *cp && *cp <= '9') {
                 guess_f = 2;
                 cp++;
-            } else if (*cp == '0') {
+            } else if (*cp == '0' || *cp == '1') {
                guess_f = 1;
                 cp++;
             } else {
@@ -1932,7 +2024,7 @@ struct input_code * find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf
 void set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0))
 {
 #ifdef INPUT_CODE_FIX
-    if (f || !input_f)
+    if (f || !input_encoding)
 #endif
         if (estab_f != f){
             estab_f = f;
@@ -1940,7 +2032,7 @@ void set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_ch
 
     if (iconv_func
 #ifdef INPUT_CODE_FIX
-        && (f == -TRUE || !input_f) /* -TRUE means "FORCE" */
+        && (f == -TRUE || !input_encoding) /* -TRUE means "FORCE" */
 #endif
         ){
         iconv = iconv_func;
@@ -2320,7 +2412,12 @@ nkf_char noconvert(FILE *f)
 
 void module_connection(void)
 {
-    oconv = output_conv;
+    if (input_encoding) set_input_encoding(input_encoding);
+    if (!output_encoding) {
+       output_encoding = nkf_default_encoding();
+    }
+    set_output_encoding(output_encoding);
+    oconv = nkf_enc_to_oconv(output_encoding);
     o_putc = std_putc;
 
     /* replace continucation module, from output side */
@@ -2380,7 +2477,7 @@ void module_connection(void)
     }
 #endif
 #ifdef UNICODE_NORMALIZATION
-    if (nfc_f && input_f == UTF8_INPUT){
+    if (nfc_f){
         i_nfc_getc = i_getc; i_getc = nfc_getc;
         i_nfc_ungetc = i_ungetc; i_ungetc= nfc_ungetc;
     }
@@ -2393,18 +2490,8 @@ void module_connection(void)
        i_bgetc = i_getc; i_getc = broken_getc;
        i_bungetc = i_ungetc; i_ungetc = broken_ungetc;
     }
-    if (input_f == JIS_INPUT || input_f == EUC_INPUT || input_f == LATIN1_INPUT) {
-        set_iconv(-TRUE, e_iconv);
-    } else if (input_f == SJIS_INPUT) {
-        set_iconv(-TRUE, s_iconv);
-#ifdef UTF8_INPUT_ENABLE
-    } else if (input_f == UTF8_INPUT) {
-        set_iconv(-TRUE, w_iconv);
-    } else if (input_f == UTF16_INPUT) {
-        set_iconv(-TRUE, w_iconv16);
-    } else if (input_f == UTF32_INPUT) {
-        set_iconv(-TRUE, w_iconv32);
-#endif
+    if (input_encoding) {
+        set_iconv(-TRUE, nkf_enc_to_iconv(input_encoding));
     } else {
         set_iconv(FALSE, e_iconv);
     }
@@ -2428,7 +2515,7 @@ void check_bom(FILE *f)
        if((c2 = (*i_getc)(f)) == 0x00){
            if((c2 = (*i_getc)(f)) == 0xFE){
                if((c2 = (*i_getc)(f)) == 0xFF){
-                   if(!input_f){
+                   if(!input_encoding){
                        set_iconv(TRUE, w_iconv32);
                    }
                    if (iconv == w_iconv32) {
@@ -2440,7 +2527,7 @@ void check_bom(FILE *f)
                (*i_ungetc)(0xFE,f);
            }else if(c2 == 0xFF){
                if((c2 = (*i_getc)(f)) == 0xFE){
-                   if(!input_f){
+                   if(!input_encoding){
                        set_iconv(TRUE, w_iconv32);
                    }
                    if (iconv == w_iconv32) {
@@ -2458,7 +2545,7 @@ void check_bom(FILE *f)
     case 0xEF:
        if((c2 = (*i_getc)(f)) == 0xBB){
            if((c2 = (*i_getc)(f)) == 0xBF){
-               if(!input_f){
+               if(!input_encoding){
                    set_iconv(TRUE, w_iconv);
                }
                if (iconv == w_iconv) {
@@ -2474,7 +2561,7 @@ void check_bom(FILE *f)
        if((c2 = (*i_getc)(f)) == 0xFF){
            if((c2 = (*i_getc)(f)) == 0x00){
                if((c2 = (*i_getc)(f)) == 0x00){
-                   if(!input_f){
+                   if(!input_encoding){
                        set_iconv(TRUE, w_iconv32);
                    }
                    if (iconv == w_iconv32) {
@@ -2485,7 +2572,7 @@ void check_bom(FILE *f)
                }else (*i_ungetc)(c2,f);
                (*i_ungetc)(0x00,f);
            }else (*i_ungetc)(c2,f);
-           if(!input_f){
+           if(!input_encoding){
                set_iconv(TRUE, w_iconv16);
            }
            if (iconv == w_iconv16) {
@@ -2500,7 +2587,7 @@ void check_bom(FILE *f)
        if((c2 = (*i_getc)(f)) == 0xFE){
            if((c2 = (*i_getc)(f)) == 0x00){
                if((c2 = (*i_getc)(f)) == 0x00){
-                   if(!input_f){
+                   if(!input_encoding){
                        set_iconv(TRUE, w_iconv32);
                    }
                    if (iconv == w_iconv32) {
@@ -2511,7 +2598,7 @@ void check_bom(FILE *f)
                }else (*i_ungetc)(c2,f);
                (*i_ungetc)(0x00,f);
            }else (*i_ungetc)(c2,f);
-           if(!input_f){
+           if(!input_encoding){
                set_iconv(TRUE, w_iconv16);
            }
            if (iconv == w_iconv16) {
@@ -2537,11 +2624,7 @@ nkf_char kanji_convert(FILE *f)
     nkf_char    c3, c2=0, c1, c0=0;
     int is_8bit = FALSE;
 
-    if(input_f == SJIS_INPUT || input_f == EUC_INPUT
-#ifdef UTF8_INPUT_ENABLE
-       || input_f == UTF8_INPUT || input_f == UTF16_INPUT
-#endif
-      ){
+    if (input_encoding && !nkf_enc_asciicompat(input_encoding)) {
        is_8bit = TRUE;
     }
 
@@ -2558,12 +2641,12 @@ nkf_char kanji_convert(FILE *f)
 
     while ((c1 = (*i_getc)(f)) != EOF) {
 #ifdef INPUT_CODE_FIX
-       if (!input_f)
+       if (!input_encoding)
 #endif
            code_status(c1);
         if (c2) {
             /* second byte */
-            if (c2 > ((input_f == JIS_INPUT && ms_ucs_map_f) ? 0x92 : DEL)) {
+            if (c2 > ((input_encoding && nkf_enc_cp5022x_p(input_encoding)) ? 0x92 : DEL)) {
                 /* in case of 8th bit is on */
                 if (!estab_f&&!mime_decode_mode) {
                     /* in case of not established yet */
@@ -2652,7 +2735,7 @@ nkf_char kanji_convert(FILE *f)
                 SEND;
            } else
 #endif
-           if (c1 > ((input_f == JIS_INPUT && ms_ucs_map_f) ? 0x92 : DEL)) {
+           if (c1 > ((input_encoding && nkf_enc_cp5022x_p(input_encoding)) ? 0x92 : DEL)) {
                 /* 8 bit code */
                 if (!estab_f && !iso8859_f) {
                     /* not established yet */
@@ -2660,7 +2743,7 @@ nkf_char kanji_convert(FILE *f)
                     NEXT;
                 } else { /* estab_f==TRUE */
                     if (iso8859_f) {
-                        c2 = ISO8859_1;
+                        c2 = ISO_8859_1;
                         c1 &= 0x7f;
                         SEND;
                     } else if (SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
@@ -2669,7 +2752,7 @@ nkf_char kanji_convert(FILE *f)
                             (*oconv)(GETA1, GETA2);
                             NEXT;
                         } else {
-                           c2 = X0201;
+                           c2 = JIS_X_0201;
                            c1 &= 0x7f;
                            SEND;
                        }
@@ -2682,7 +2765,7 @@ nkf_char kanji_convert(FILE *f)
                                (*oconv)(GETA1, GETA2);
                                NEXT;
                            } else {
-                               c2 = X0201;
+                               c2 = JIS_X_0201;
                                c1 &= 0x7f;
                                SEND;
                            }
@@ -2692,7 +2775,7 @@ nkf_char kanji_convert(FILE *f)
                    } else if (ms_ucs_map_f == UCS_MAP_CP10001 &&
                               (c1 == 0xFD || c1 == 0xFE)) {
                        /* CP10001 */
-                       c2 = X0201;
+                       c2 = JIS_X_0201;
                        c1 &= 0x7f;
                        SEND;
                     } else {
@@ -2706,7 +2789,7 @@ nkf_char kanji_convert(FILE *f)
                 if (shift_mode) {
                     /* output 1 shifted byte */
                     if (iso8859_f) {
-                        c2 = ISO8859_1;
+                        c2 = ISO_8859_1;
                         SEND;
                     } else if (SP <= c1 && c1 < (0xe0&0x7f)){
                       /* output 1 shifted byte */
@@ -2714,15 +2797,15 @@ nkf_char kanji_convert(FILE *f)
                            (*oconv)(GETA1, GETA2);
                            NEXT;
                        } else {
-                           c2 = X0201;
+                           c2 = JIS_X_0201;
                            SEND;
                        }
                     } else {
                         /* look like bogus code */
                         NEXT;
                     }
-                } else if (input_mode == X0208 || input_mode == X0212 ||
-                          input_mode == X0213_1 || input_mode == X0213_2) {
+                } else if (input_mode == JIS_X_0208 || input_mode == JIS_X_0212 ||
+                          input_mode == JIS_X_0213_1 || input_mode == JIS_X_0213_2) {
                     /* in case of Kanji shifted */
                     c2 = c1;
                     NEXT;
@@ -2770,7 +2853,7 @@ nkf_char kanji_convert(FILE *f)
                         LAST;
                     } else if (c1 == '@'|| c1 == 'B') {
                         /* This is kanji introduction */
-                        input_mode = X0208;
+                        input_mode = JIS_X_0208;
                         shift_mode = FALSE;
                         set_input_codename("ISO-2022-JP");
 #ifdef CHECK_OPTION
@@ -2787,21 +2870,21 @@ nkf_char kanji_convert(FILE *f)
                             LAST;
                         } else if (c1 == '@'|| c1 == 'B') {
                             /* This is kanji introduction */
-                            input_mode = X0208;
+                            input_mode = JIS_X_0208;
                             shift_mode = FALSE;
                             NEXT;
 #ifdef X0212_ENABLE
                         } else if (c1 == 'D'){
-                            input_mode = X0212;
+                            input_mode = JIS_X_0212;
                             shift_mode = FALSE;
                             NEXT;
 #endif /* X0212_ENABLE */
-                        } else if (c1 == (X0213_1&0x7F)){
-                            input_mode = X0213_1;
+                        } else if (c1 == 0x4F){
+                            input_mode = JIS_X_0213_1;
                             shift_mode = FALSE;
                             NEXT;
-                        } else if (c1 == (X0213_2&0x7F)){
-                            input_mode = X0213_2;
+                        } else if (c1 == 0x50){
+                            input_mode = JIS_X_0213_2;
                             shift_mode = FALSE;
                             NEXT;
                         } else {
@@ -2814,7 +2897,7 @@ nkf_char kanji_convert(FILE *f)
                         }
                     } else if (broken_f&0x2) {
                         /* accept any ESC-(-x as broken code ... */
-                        input_mode = X0208;
+                        input_mode = JIS_X_0208;
                         shift_mode = FALSE;
                         NEXT;
                     } else {
@@ -2832,7 +2915,7 @@ nkf_char kanji_convert(FILE *f)
                     } else {
                         if (c1 == 'I') {
                             /* This is X0201 kana introduction */
-                            input_mode = X0201; shift_mode = X0201;
+                            input_mode = JIS_X_0201; shift_mode = JIS_X_0201;
                             NEXT;
                         } else if (c1 == 'B' || c1 == 'J' || c1 == 'H') {
                             /* This is X0208 kanji introduction */
@@ -2853,7 +2936,7 @@ nkf_char kanji_convert(FILE *f)
                    c3 = (*i_getc)(f);  /* skip SS2 */
                    if ( (SP<=c3 && c3 < 0x60) || (0xa0<=c3 && c3 < 0xe0)){
                        c1 = c3;
-                       c2 = X0201;
+                       c2 = JIS_X_0201;
                        SEND;
                    }else{
                        (*i_ungetc)(c3, f);
@@ -2937,7 +3020,7 @@ nkf_char kanji_convert(FILE *f)
                        SEND;
                    }
                }
-           } else if (c1 == DEL && input_mode == X0208) {
+           } else if (c1 == DEL && input_mode == JIS_X_0208) {
                /* CP5022x */
                c2 = c1;
                NEXT;
@@ -2968,8 +3051,8 @@ nkf_char kanji_convert(FILE *f)
                break;
            }
            break;
-       case X0208:
-       case X0213_1:
+       case JIS_X_0208:
+       case JIS_X_0213_1:
            if (ms_ucs_map_f &&
                0x7F <= c2 && c2 <= 0x92 &&
                0x21 <= c1 && c1 <= 0x7E) {
@@ -2981,11 +3064,11 @@ nkf_char kanji_convert(FILE *f)
            (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
            break;
 #ifdef X0212_ENABLE
-       case X0212:
+       case JIS_X_0212:
            (*oconv)(PREFIX_EUCG3 | c2, c1);
            break;
 #endif /* X0212_ENABLE */
-       case X0213_2:
+       case JIS_X_0213_2:
            (*oconv)(PREFIX_EUCG3 | c2, c1);
            break;
        default:
@@ -3081,7 +3164,7 @@ h_conv(FILE *f, nkf_char c2, nkf_char c1)
             (*iconv)(0, c2, 0);
             continue;
         }else if (iconv == s_iconv && 0xa1 <= c2 && c2 <= 0xdf){
-            (*iconv)(X0201, c2, 0);
+            (*iconv)(JIS_X_0201, c2, 0);
             continue;
         }
         if (hold_index < hold_count){
@@ -3192,6 +3275,8 @@ nkf_char s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
                if (0x9E < c1) c2++;
            }
        }else{
+#define         SJ0162  0x00e1          /* 01 - 62 ku offset */
+#define         SJ6394  0x0161          /* 63 - 94 ku offset */
            c2 = c2 + c2 - ((c2 <= 0x9F) ? SJ0162 : SJ6394);
            if (0x9E < c1) c2++;
        }
@@ -3212,7 +3297,7 @@ nkf_char s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
 
 nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
 {
-    if (c2 == X0201) {
+    if (c2 == JIS_X_0201) {
        c1 &= 0x7f;
     } else if ((c2 == EOF) || (c2 == 0) || c2 < SP) {
         /* NOP */
@@ -3231,7 +3316,7 @@ nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
 
 nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
 {
-    if (c2 == X0201) {
+    if (c2 == JIS_X_0201) {
        c1 &= 0x7f;
 #ifdef X0212_ENABLE
     }else if (c2 == 0x8f){
@@ -3260,7 +3345,7 @@ nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0)
         }
 #endif /* X0212_ENABLE */
     } else if (c2 == SSO){
-        c2 = X0201;
+        c2 = JIS_X_0201;
         c1 &= 0x7f;
     } else if ((c2 == EOF) || (c2 == 0) || c2 < SP) {
         /* NOP */
@@ -3678,7 +3763,7 @@ nkf_char w_iconv_common(nkf_char c1, nkf_char c0, const unsigned short *const *p
         c2 &= 0x7f;
         c2 |= PREFIX_EUCG3;
     }
-    if (c2 == SO) c2 = X0201;
+    if (c2 == SO) c2 = JIS_X_0201;
     c1 = val & 0x7f;
     if (p2) *p2 = c2;
     if (p1) *p1 = c1;
@@ -3778,7 +3863,7 @@ nkf_char e2w_conv(nkf_char c2, nkf_char c1)
 {
     const unsigned short *p;
 
-    if (c2 == X0201) {
+    if (c2 == JIS_X_0201) {
        if (ms_ucs_map_f == UCS_MAP_CP10001) {
            switch (c1) {
            case 0x20:
@@ -3859,11 +3944,11 @@ void w_oconv(nkf_char c2, nkf_char c1)
     if (c2 == 0) {
        output_mode = ASCII;
         (*o_putc)(c1);
-    } else if (c2 == ISO8859_1) {
-       output_mode = UTF8;
+    } else if (c2 == ISO_8859_1) {
+       output_mode = UTF_8;
         (*o_putc)(c1 | 0x080);
     } else {
-        output_mode = UTF8;
+        output_mode = UTF_8;
        val = e2w_conv(c2, c1);
         if (val){
             w16w_conv(val, &c2, &c1, &c0);
@@ -3894,7 +3979,7 @@ void w_oconv16(nkf_char c2, nkf_char c1)
         return;
     }
 
-    if (c2 == ISO8859_1) {
+    if (c2 == ISO_8859_1) {
         c2 = 0;
         c1 |= 0x80;
 #ifdef NUMCHAR_OPTION
@@ -3959,7 +4044,7 @@ void w_oconv32(nkf_char c2, nkf_char c1)
         return;
     }
 
-    if (c2 == ISO8859_1) {
+    if (c2 == ISO_8859_1) {
         c1 |= 0x80;
 #ifdef NUMCHAR_OPTION
     } else if (c2 == 0 && is_unicode_capsule(c1)) {
@@ -4018,15 +4103,15 @@ void e_oconv(nkf_char c2, nkf_char c1)
     } else if (c2 == 0) {
        output_mode = ASCII;
         (*o_putc)(c1);
-    } else if (c2 == X0201) {
-       output_mode = JAPANESE_EUC;
+    } else if (c2 == JIS_X_0201) {
+       output_mode = EUC_JP;
         (*o_putc)(SSO); (*o_putc)(c1|0x80);
-    } else if (c2 == ISO8859_1) {
-       output_mode = ISO8859_1;
+    } else if (c2 == ISO_8859_1) {
+       output_mode = ISO_8859_1;
         (*o_putc)(c1 | 0x080);
 #ifdef X0212_ENABLE
     } else if (is_eucg3(c2)){
-       output_mode = JAPANESE_EUC;
+       output_mode = EUC_JP;
 #ifdef SHIFTJIS_CP932
         if (!cp932inv_f){
             nkf_char s2, s1;
@@ -4054,7 +4139,7 @@ void e_oconv(nkf_char c2, nkf_char c1)
             set_iconv(FALSE, 0);
             return; /* too late to rescue this char */
         }
-       output_mode = JAPANESE_EUC;
+       output_mode = EUC_JP;
         (*o_putc)(c2 | 0x080);
         (*o_putc)(c1 | 0x080);
     }
@@ -4142,7 +4227,7 @@ void s_oconv(nkf_char c2, nkf_char c1)
            if (!x0213_f && 0xE000 <= c2 && c2 <= 0xE757) {
                /* CP932 UDC */
                c1 &= 0xFFF;
-               c2 = c1 / 188 + 0xF0;
+               c2 = c1 / 188 + (cp932inv_f ? 0xF0 : 0xEB);
                c1 = c1 % 188;
                c1 += 0x40 + (c1 > 0x3e);
                (*o_putc)(c2);
@@ -4161,11 +4246,11 @@ void s_oconv(nkf_char c2, nkf_char c1)
     } else if (c2 == 0) {
        output_mode = ASCII;
         (*o_putc)(c1);
-    } else if (c2 == X0201) {
+    } else if (c2 == JIS_X_0201) {
        output_mode = SHIFT_JIS;
         (*o_putc)(c1|0x80);
-    } else if (c2 == ISO8859_1) {
-       output_mode = ISO8859_1;
+    } else if (c2 == ISO_8859_1) {
+       output_mode = ISO_8859_1;
         (*o_putc)(c1 | 0x080);
 #ifdef X0212_ENABLE
     } else if (is_eucg3(c2)){
@@ -4222,7 +4307,7 @@ void j_oconv(nkf_char c2, nkf_char c1)
     }
 #endif
     if (c2 == EOF) {
-        if (output_mode !=ASCII && output_mode!=ISO8859_1) {
+        if (output_mode !=ASCII && output_mode!=ISO_8859_1) {
             (*o_putc)(ESC);
             (*o_putc)('(');
             (*o_putc)(ascii_intro);
@@ -4232,41 +4317,41 @@ void j_oconv(nkf_char c2, nkf_char c1)
 #ifdef X0212_ENABLE
     } else if (is_eucg3(c2)){
        if(x0213_f){
-           if(output_mode!=X0213_2){
-               output_mode = X0213_2;
+           if(output_mode!=JIS_X_0213_2){
+               output_mode = JIS_X_0213_2;
                (*o_putc)(ESC);
                (*o_putc)('$');
                (*o_putc)('(');
-               (*o_putc)(X0213_2&0x7F);
+               (*o_putc)(0x50);
            }
        }else{
-           if(output_mode!=X0212){
-               output_mode = X0212;
+           if(output_mode!=JIS_X_0212){
+               output_mode = JIS_X_0212;
                (*o_putc)(ESC);
                (*o_putc)('$');
                (*o_putc)('(');
-               (*o_putc)(X0212&0x7F);
+               (*o_putc)(0x44);
            }
         }
         (*o_putc)(c2 & 0x7f);
         (*o_putc)(c1);
 #endif
-    } else if (c2==X0201) {
-        if (output_mode!=X0201) {
-            output_mode = X0201;
+    } else if (c2==JIS_X_0201) {
+        if (output_mode!=JIS_X_0201) {
+            output_mode = JIS_X_0201;
             (*o_putc)(ESC);
             (*o_putc)('(');
             (*o_putc)('I');
         }
         (*o_putc)(c1);
-    } else if (c2==ISO8859_1) {
+    } else if (c2==ISO_8859_1) {
             /* iso8859 introduction, or 8th bit on */
             /* Can we convert in 7bit form using ESC-'-'-A ?
                Is this popular? */
-       output_mode = ISO8859_1;
+       output_mode = ISO_8859_1;
         (*o_putc)(c1|0x80);
     } else if (c2 == 0) {
-        if (output_mode !=ASCII && output_mode!=ISO8859_1) {
+        if (output_mode !=ASCII && output_mode!=ISO_8859_1) {
             (*o_putc)(ESC);
             (*o_putc)('(');
             (*o_putc)(ascii_intro);
@@ -4278,15 +4363,15 @@ void j_oconv(nkf_char c2, nkf_char c1)
           ? c2<0x20 || 0x92<c2 || c1<0x20 || 0x7e<c1
           : c2<0x20 || 0x7e<c2 || c1<0x20 || 0x7e<c1) return;
        if(x0213_f){
-           if (output_mode!=X0213_1) {
-               output_mode = X0213_1;
+           if (output_mode!=JIS_X_0213_1) {
+               output_mode = JIS_X_0213_1;
                (*o_putc)(ESC);
                (*o_putc)('$');
                (*o_putc)('(');
-               (*o_putc)(X0213_1&0x7F);
+               (*o_putc)(0x4F);
            }
-       }else if (output_mode != X0208) {
-            output_mode = X0208;
+       }else if (output_mode != JIS_X_0208) {
+            output_mode = JIS_X_0208;
             (*o_putc)(ESC);
             (*o_putc)('$');
             (*o_putc)(kanji_intro);
@@ -4315,7 +4400,7 @@ nkf_char broken_getc(FILE *f)
     }
     c= (*i_bgetc)(f);
     if (c=='$' && broken_last != ESC
-            && (input_mode==ASCII || input_mode==X0201)) {
+            && (input_mode==ASCII || input_mode==JIS_X_0201)) {
        c1= (*i_bgetc)(f);
        broken_last = 0;
        if (c1=='@'|| c1=='B') {
@@ -4327,7 +4412,7 @@ nkf_char broken_getc(FILE *f)
            return c;
        }
     } else if (c=='(' && broken_last != ESC
-            && (input_mode==X0208 || input_mode==X0201)) { /* ) */
+            && (input_mode==JIS_X_0208 || input_mode==JIS_X_0201)) { /* ) */
        c1= (*i_bgetc)(f);
        broken_last = 0;
        if (c1=='J'|| c1=='B') {
@@ -4362,7 +4447,7 @@ void nl_conv(nkf_char c2, nkf_char c1)
        else if (!input_newline) input_newline = CR;
        else if (input_newline != CR) input_newline = EOF;
     }
-    if (prev_cr || c2 == 0 && c1 == LF) {
+    if (prev_cr || (c2 == 0 && c1 == LF)) {
        prev_cr = 0;
        if (nlmode_f != LF) (*o_nlconv)(0, CR);
        if (nlmode_f != CR) (*o_nlconv)(0, LF);
@@ -4464,7 +4549,7 @@ void fold_conv(nkf_char c2, nkf_char c1)
     } else {
         prev0 = f_prev; /* we still need this one... , but almost done */
         f_prev = c1;
-        if (c2 || c2==X0201)
+        if (c2 || c2==JIS_X_0201)
             f_prev |= 0x80;  /* this is Japanese */
         f_line += char_size(c2,c1);
         if (f_line<=fold_len) {   /* normal case */
@@ -4473,7 +4558,7 @@ void fold_conv(nkf_char c2, nkf_char c1)
             if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */
                 f_line = char_size(c2,c1);
                 fold_state =  LF;       /* We can't wait, do fold now */
-            } else if (c2==X0201) {
+            } else if (c2==JIS_X_0201) {
             /* simple kinsoku rules  return 1 means no folding  */
                 if (c1==(0xde&0x7f)) fold_state = 1; /* \e$B!+\e(B*/
                 else if (c1==(0xdf&0x7f)) fold_state = 1; /* \e$B!,\e(B*/
@@ -4544,13 +4629,13 @@ void fold_conv(nkf_char c2, nkf_char c1)
     /* terminator process */
     switch(fold_state) {
         case LF:
-            (*o_fconv)(0,LF);
+            OCONV_NEWLINE((*o_fconv));
             (*o_fconv)(c2,c1);
             break;
         case 0:
             return;
         case CR:
-            (*o_fconv)(0,LF);
+            OCONV_NEWLINE((*o_fconv));
             break;
         case TAB:
         case SP:
@@ -4568,14 +4653,14 @@ void z_conv(nkf_char c2, nkf_char c1)
 
     /* if (c2) c1 &= 0x7f; assertion */
 
-    if (c2 == X0201 && (c1 == 0x20 || c1 == 0x7D || c1 == 0x7E)) {
+    if (c2 == JIS_X_0201 && (c1 == 0x20 || c1 == 0x7D || c1 == 0x7E)) {
        (*o_zconv)(c2,c1);
        return;
     }
 
     if (x0201_f) {
-       if (z_prev2 == X0201) {
-           if (c2 == X0201) {
+       if (z_prev2 == JIS_X_0201) {
+           if (c2 == JIS_X_0201) {
                if (c1 == (0xde&0x7f)) { /* \e$BByE@\e(B */
                    z_prev2 = 0;
                    (*o_zconv)(dv[(z_prev1-SP)*2], dv[(z_prev1-SP)*2+1]);
@@ -4589,7 +4674,7 @@ void z_conv(nkf_char c2, nkf_char c1)
            z_prev2 = 0;
            (*o_zconv)(cv[(z_prev1-SP)*2], cv[(z_prev1-SP)*2+1]);
        }
-       if (c2 == X0201) {
+       if (c2 == JIS_X_0201) {
            if (dv[(c1-SP)*2] || ev[(c1-SP)*2]) {
                /* wait for \e$BByE@\e(B or \e$BH>ByE@\e(B */
                z_prev1 = c1;
@@ -4681,7 +4766,7 @@ void z_conv(nkf_char c2, nkf_char c1)
                break;
            }
            if (c) {
-               (*o_zconv)(X0201, c);
+               (*o_zconv)(JIS_X_0201, c);
                return;
            }
        } else if (c2 == 0x25) {
@@ -4703,9 +4788,9 @@ void z_conv(nkf_char c2, nkf_char c1)
            };
            if (fullwidth_to_halfwidth[c1-0x20]){
                c2 = fullwidth_to_halfwidth[c1-0x20];
-               (*o_zconv)(X0201, c2>>8);
+               (*o_zconv)(JIS_X_0201, c2>>8);
                if (c2 & 0xFF) {
-                   (*o_zconv)(X0201, c2&0xFF);
+                   (*o_zconv)(JIS_X_0201, c2&0xFF);
                }
                return;
            }
@@ -4734,7 +4819,7 @@ void z_conv(nkf_char c2, nkf_char c1)
 
 void rot_conv(nkf_char c2, nkf_char c1)
 {
-    if (c2==0 || c2==X0201 || c2==ISO8859_1) {
+    if (c2==0 || c2==JIS_X_0201 || c2==ISO_8859_1) {
        c1 = rot13(c1);
     } else if (c2) {
        c1 = rot47(c1);
@@ -4751,7 +4836,7 @@ void hira_conv(nkf_char c2, nkf_char c1)
                 c2 = 0x24;
                 (*o_hira_conv)(c2,c1);
                 return;
-            } else if (c1 == 0x74 && (output_conv == w_oconv || output_conv == w_oconv16)) {
+            } else if (c1 == 0x74 && nkf_enc_unicode_p(output_encoding)) {
                 c2 = 0;
                 c1 = CLASS_UNICODE | 0x3094;
                 (*o_hira_conv)(c2,c1);
@@ -4852,9 +4937,9 @@ nkf_char (*mime_priority_func[])(nkf_char c2, nkf_char c1, nkf_char c0) = {
 };
 
 static const nkf_char mime_encode[] = {
-    JAPANESE_EUC, SHIFT_JIS,ISO8859_1, ISO8859_1, X0208, X0201,
+    EUC_JP, SHIFT_JIS, ISO_8859_1, ISO_8859_1, JIS_X_0208, JIS_X_0201,
 #if defined(UTF8_INPUT_ENABLE)
-    UTF8, UTF8,
+    UTF_8, UTF_8,
 #endif
     ASCII,
     0
@@ -5043,35 +5128,43 @@ void set_input_codename(char *codename)
     }
 }
 
+static char* get_guessed_code(void)
+{
+    if (input_codename && !*input_codename) {
+       input_codename = "BINARY";
+    } else {
+       struct input_code *p = find_inputcode_byfunc(iconv);
+       if (!input_codename) {
+           input_codename = "ASCII";
+       } else if (strcmp(input_codename, "Shift_JIS") == 0) {
+           if (p->score & (SCORE_DEPEND|SCORE_CP932))
+               input_codename = "CP932";
+       } else if (strcmp(input_codename, "EUC-JP") == 0) {
+           if (p->score & (SCORE_X0212))
+               input_codename = "EUCJP-MS";
+           else if (p->score & (SCORE_DEPEND|SCORE_CP932))
+               input_codename = "CP51932";
+       } else if (strcmp(input_codename, "ISO-2022-JP") == 0) {
+           if (p->score & (SCORE_KANA))
+               input_codename = "CP50221";
+           else if (p->score & (SCORE_DEPEND|SCORE_CP932))
+               input_codename = "CP50220";
+       }
+    }
+    return input_codename;
+}
+
 #if !defined(PERL_XS) && !defined(WIN32DLL)
 void print_guessed_code(char *filename)
 {
-    char *codename = "BINARY";
-    char *str_nlmode = NULL;
     if (filename != NULL) printf("%s: ", filename);
     if (input_codename && !*input_codename) {
        printf("BINARY\n");
     } else {
-       struct input_code *p = find_inputcode_byfunc(iconv);
+       input_codename = get_guessed_code();
        if (guess_f == 1) {
-           printf("%s\n", input_codename ? input_codename : "ASCII");
+           printf("%s\n", input_codename);
        } else {
-           if (!input_codename) {
-               input_codename = "ASCII";
-           } else if (strcmp(input_codename, "Shift_JIS") == 0) {
-               if (p->score & (SCORE_DEPEND|SCORE_CP932))
-                   input_codename = "CP932";
-           } else if (strcmp(input_codename, "EUC-JP") == 0) {
-               if (p->score & (SCORE_X0212))
-                   input_codename = "EUCJP-MS";
-               else if (p->score & (SCORE_DEPEND|SCORE_CP932))
-                   input_codename = "CP51932";
-           } else if (strcmp(input_codename, "ISO-2022-JP") == 0) {
-               if (p->score & (SCORE_KANA))
-                   input_codename = "CP50221";
-               else if (p->score & (SCORE_DEPEND|SCORE_CP932))
-                   input_codename = "CP50220";
-           }
            printf("%s%s\n",
                   input_codename,
                   input_newline == CR   ? " (CR)" :
@@ -5197,7 +5290,7 @@ nkf_char nfc_getc(FILE *f)
     nkf_char (*u)(nkf_char c ,FILE *f) = i_nfc_ungetc;
     int i=0, j, k=1, lower, upper;
     nkf_char buf[9];
-    const nkf_nfchar *array;
+    const unsigned char *array;
 
     buf[i] = (*g)(f);
     while (k > 0 && ((buf[i] & 0xc0) != 0x80)){
@@ -5577,7 +5670,7 @@ void open_mime(nkf_char mode)
             (*o_mputc)(mimeout_buf[i]);
            i++;
        }
-       (*o_mputc)(LF);
+       PUT_NEWLINE((*o_mputc));
        (*o_mputc)(SP);
        base64_count = 1;
        if (mimeout_buf_count>0
@@ -5690,14 +5783,14 @@ void mime_prechar(nkf_char c2, nkf_char c1)
         if (c2 == EOF){
             if (base64_count + mimeout_buf_count/3*4> 73){
                 (*o_base64conv)(EOF,0);
-                (*o_base64conv)(0,LF);
+                OCONV_NEWLINE((*o_base64conv));
                 (*o_base64conv)(0,SP);
                 base64_count = 1;
             }
         } else {
             if (base64_count + mimeout_buf_count/3*4> 66) {
                 (*o_base64conv)(EOF,0);
-                (*o_base64conv)(0,LF);
+                OCONV_NEWLINE((*o_base64conv));
                 (*o_base64conv)(0,SP);
                 base64_count = 1;
                 mimeout_mode = -1;
@@ -5705,10 +5798,10 @@ void mime_prechar(nkf_char c2, nkf_char c1)
         }
     } else if (c2) {
        if (c2 != EOF && base64_count + mimeout_buf_count/3*4> 60) {
-           mimeout_mode =  (output_mode==ASCII ||output_mode == ISO8859_1) ? 'Q' : 'B';
+           mimeout_mode =  (output_mode==ASCII ||output_mode == ISO_8859_1) ? 'Q' : 'B';
            open_mime(output_mode);
            (*o_base64conv)(EOF,0);
-           (*o_base64conv)(0,LF);
+           OCONV_NEWLINE((*o_base64conv));
            (*o_base64conv)(0,SP);
            base64_count = 1;
            mimeout_mode = -1;
@@ -5726,14 +5819,14 @@ void mime_putc(nkf_char c)
             if (base64_count > 71){
                 if (c!=CR && c!=LF) {
                     (*o_mputc)('=');
-                    (*o_mputc)(LF);
+                    PUT_NEWLINE((*o_mputc));
                 }
                 base64_count = 0;
             }
         }else{
             if (base64_count > 71){
                 eof_mime();
-                (*o_mputc)(LF);
+                PUT_NEWLINE((*o_mputc));
                 base64_count = 0;
             }
             if (c == EOF) { /* c==EOF */
@@ -5786,7 +5879,7 @@ void mime_putc(nkf_char c)
     }
 
     if (mimeout_mode=='Q') {
-        if (c <= DEL && (output_mode==ASCII ||output_mode == ISO8859_1)) {
+        if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
            if (c == CR || c == LF) {
                close_mime();
                (*o_mputc)(c);
@@ -5795,7 +5888,7 @@ void mime_putc(nkf_char c)
             } else if (c <= SP) {
                 close_mime();
                if (base64_count > 70) {
-                   (*o_mputc)(LF);
+                   PUT_NEWLINE((*o_mputc));
                    base64_count = 0;
                }
                if (!nkf_isblank(c)) {
@@ -5805,7 +5898,7 @@ void mime_putc(nkf_char c)
             } else {
                if (base64_count > 70) {
                    close_mime();
-                   (*o_mputc)(LF);
+                   PUT_NEWLINE((*o_mputc));
                    (*o_mputc)(SP);
                    base64_count = 1;
                    open_mime(output_mode);
@@ -5822,7 +5915,7 @@ void mime_putc(nkf_char c)
     }
 
     if (mimeout_mode <= 0) {
-        if (c <= DEL && (output_mode==ASCII ||output_mode == ISO8859_1)) {
+        if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
             if (nkf_isspace(c)) {
                int flag = 0;
                if (mimeout_mode == -1) {
@@ -5855,7 +5948,7 @@ void mime_putc(nkf_char c)
                 if (base64_count > 1
                     && base64_count + mimeout_buf_count > 76
                    && mimeout_buf[0] != CR && mimeout_buf[0] != LF){
-                    (*o_mputc)(LF);
+                    PUT_NEWLINE((*o_mputc));
                     base64_count = 0;
                     if (!nkf_isspace(mimeout_buf[0])){
                         (*o_mputc)(SP);
@@ -5888,7 +5981,7 @@ void mime_putc(nkf_char c)
         }
     }else{
         /* mimeout_mode == 'B', 1, 2 */
-        if ( c<=DEL && (output_mode==ASCII ||output_mode == ISO8859_1)) {
+        if ( c<=DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) {
             if (lastchar == CR || lastchar == LF){
                 if (nkf_isblank(c)) {
                     for (i=0;i<mimeout_buf_count;i++) {
@@ -5976,7 +6069,6 @@ void reinit(void)
     binmode_f = TRUE;
     rot_f = FALSE;
     hira_f = FALSE;
-    input_f = FALSE;
     alpha_f = FALSE;
     mime_f = MIME_DECODE_DEFAULT;
     mime_decode_f = FALSE;
@@ -6042,8 +6134,6 @@ void reinit(void)
     kanji_intro = DEFAULT_J;
     ascii_intro = DEFAULT_R;
     fold_margin  = FOLD_MARGIN;
-    output_conv = DEFAULT_CONV;
-    oconv = DEFAULT_CONV;
     o_zconv = no_connection;
     o_fconv = no_connection;
     o_nlconv = no_connection;
@@ -6077,6 +6167,8 @@ void reinit(void)
     iconv_for_check = 0;
 #endif
     input_codename = NULL;
+    input_encoding = NULL;
+    output_encoding = NULL;
 #ifdef WIN32DLL
     reinitdll();
 #endif /*WIN32DLL*/
@@ -6098,108 +6190,128 @@ nkf_char no_connection2(nkf_char c2, nkf_char c1, nkf_char c0)
 #ifdef WIN32DLL
 #define fprintf dllprintf
 #endif
+
+void version(void)
+{
+    fprintf(HELP_OUTPUT,"Network Kanji Filter Version " NKF_VERSION " (" NKF_RELEASE_DATE ") \n" COPY_RIGHT "\n");
+}
+
 void usage(void)
 {
-    fprintf(stderr,"USAGE:  nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
-    fprintf(stderr,"Flags:\n");
-    fprintf(stderr,"b,u      Output is buffered (DEFAULT),Output is unbuffered\n");
-#ifdef DEFAULT_CODE_SJIS
-    fprintf(stderr,"j,s,e,w  Output code is JIS 7 bit, Shift_JIS (DEFAULT), EUC-JP, UTF-8N\n");
-#endif
-#ifdef DEFAULT_CODE_JIS
-    fprintf(stderr,"j,s,e,w  Output code is JIS 7 bit (DEFAULT), Shift JIS, EUC-JP, UTF-8N\n");
-#endif
-#ifdef DEFAULT_CODE_EUC
-    fprintf(stderr,"j,s,e,w  Output code is JIS 7 bit, Shift JIS, EUC-JP (DEFAULT), UTF-8N\n");
-#endif
-#ifdef DEFAULT_CODE_UTF8
-    fprintf(stderr,"j,s,e,w  Output code is JIS 7 bit, Shift JIS, EUC-JP, UTF-8N (DEFAULT)\n");
-#endif
+    fprintf(HELP_OUTPUT,
+           "USAGE:  nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n"
+           "Flags:\n"
+           "b,u      Output is buffered (DEFAULT),Output is unbuffered\n"
+           "j,s,e,w  Output code is ISO-2022-JP, Shift JIS, EUC-JP, UTF-8N\n"
 #ifdef UTF8_OUTPUT_ENABLE
-    fprintf(stderr,"         After 'w' you can add more options. -w[ 8 [0], 16 [[BL] [0]] ]\n");
+           "         After 'w' you can add more options. -w[ 8 [0], 16 [[BL] [0]] ]\n"
 #endif
-    fprintf(stderr,"J,S,E,W  Input assumption is JIS 7 bit , Shift JIS, EUC-JP, UTF-8\n");
+           "J,S,E,W  Input assumption is JIS 7 bit , Shift JIS, EUC-JP, UTF-8\n"
 #ifdef UTF8_INPUT_ENABLE
-    fprintf(stderr,"         After 'W' you can add more options. -W[ 8, 16 [BL] ] \n");
-#endif
-    fprintf(stderr,"t        no conversion\n");
-    fprintf(stderr,"i[@B]    Specify the Esc Seq for JIS X 0208-1978/83 (DEFAULT B)\n");
-    fprintf(stderr,"o[BJH]   Specify the Esc Seq for ASCII/Roman        (DEFAULT B)\n");
-    fprintf(stderr,"r        {de/en}crypt ROT13/47\n");
-    fprintf(stderr,"h        1 katakana->hiragana, 2 hiragana->katakana, 3 both\n");
-    fprintf(stderr,"v        Show this usage. V: show version\n");
-    fprintf(stderr,"m[BQN0]  MIME decode [B:base64,Q:quoted,N:non-strict,0:no decode]\n");
-    fprintf(stderr,"M[BQ]    MIME encode [B:base64 Q:quoted]\n");
-    fprintf(stderr,"l        ISO8859-1 (Latin-1) support\n");
-    fprintf(stderr,"f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n");
-    fprintf(stderr,"Z[0-4]   Default/0: Convert JISX0208 Alphabet to ASCII\n");
-    fprintf(stderr,"         1: Kankaku to one space  2: to two spaces  3: HTML Entity\n");
-    fprintf(stderr,"         4: JISX0208 Katakana to JISX0201 Katakana\n");
-    fprintf(stderr,"X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
-    fprintf(stderr,"B[0-2]   Broken input  0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
+           "         After 'W' you can add more options. -W[ 8, 16 [BL] ] \n"
+#endif
+           "t        no conversion\n"
+           "i[@B]    Specify the Esc Seq for JIS X 0208-1978/83 (DEFAULT B)\n"
+           "o[BJH]   Specify the Esc Seq for ASCII/Roman        (DEFAULT B)\n"
+           "r        {de/en}crypt ROT13/47\n"
+           "h        1 katakana->hiragana, 2 hiragana->katakana, 3 both\n"
+           "m[BQSN0] MIME decode [B:base64,Q:quoted,S:strict,N:non-strict,0:no decode]\n"
+           "M[BQ]    MIME encode [B:base64 Q:quoted]\n"
+           "l        ISO8859-1 (Latin-1) support\n"
+           "f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n"
+           "Z[0-4]   Default/0: Convert JISX0208 Alphabet to ASCII\n"
+           "         1: Kankaku to one space  2: to two spaces  3: HTML Entity\n"
+           "         4: JISX0208 Katakana to JISX0201 Katakana\n"
+           "X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201\n"
+           "B[0-2]   Broken input  0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n"
 #ifdef MSDOS
-    fprintf(stderr,"T        Text mode output\n");
-#endif
-    fprintf(stderr,"O        Output to File (DEFAULT 'nkf.out')\n");
-    fprintf(stderr,"I        Convert non ISO-2022-JP charactor to GETA\n");
-    fprintf(stderr,"d,c      Convert line breaks  -d: LF  -c: CRLF\n");
-    fprintf(stderr,"-L[uwm]  line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n");
-    fprintf(stderr,"\n");
-    fprintf(stderr,"Long name options\n");
-    fprintf(stderr," --ic=<input codeset>  --oc=<output codeset>\n");
-    fprintf(stderr,"                   Specify the input or output codeset\n");
-    fprintf(stderr," --fj  --unix --mac  --windows\n");
-    fprintf(stderr," --jis  --euc  --sjis  --utf8  --utf16  --mime  --base64\n");
-    fprintf(stderr,"                   Convert for the system or code\n");
-    fprintf(stderr," --hiragana  --katakana  --katakana-hiragana\n");
-    fprintf(stderr,"                   To Hiragana/Katakana Conversion\n");
-    fprintf(stderr," --prefix=         Insert escape before troublesome characters of Shift_JIS\n");
+           "T        Text mode output\n"
+#endif
+           "O        Output to File (DEFAULT 'nkf.out')\n"
+           "I        Convert non ISO-2022-JP charactor to GETA\n"
+           "d,c      Convert line breaks  -d: LF  -c: CRLF\n"
+           "-L[uwm]  line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n"
+           "v, V     Show this usage. V: show configuration\n"
+           "\n"
+           "Long name options\n"
+           " --ic=<input codeset>  --oc=<output codeset>\n"
+           "                   Specify the input or output codeset\n"
+           " --fj  --unix --mac  --windows\n"
+           " --jis  --euc  --sjis  --utf8  --utf16  --mime  --base64\n"
+           "                   Convert for the system or code\n"
+           " --hiragana  --katakana  --katakana-hiragana\n"
+           "                   To Hiragana/Katakana Conversion\n"
+           " --prefix=         Insert escape before troublesome characters of Shift_JIS\n"
 #ifdef INPUT_OPTION
-    fprintf(stderr," --cap-input, --url-input  Convert hex after ':' or '%%'\n");
+           " --cap-input, --url-input  Convert hex after ':' or '%%'\n"
 #endif
 #ifdef NUMCHAR_OPTION
-    fprintf(stderr," --numchar-input   Convert Unicode Character Reference\n");
+           " --numchar-input   Convert Unicode Character Reference\n"
 #endif
 #ifdef UTF8_INPUT_ENABLE
-    fprintf(stderr," --fb-{skip, html, xml, perl, java, subchar}\n");
-    fprintf(stderr,"                   Specify how nkf handles unassigned characters\n");
+           " --fb-{skip, html, xml, perl, java, subchar}\n"
+           "                   Specify how nkf handles unassigned characters\n"
 #endif
 #ifdef OVERWRITE
-    fprintf(stderr," --in-place[=SUFFIX]  --overwrite[=SUFFIX]\n");
-    fprintf(stderr,"                   Overwrite original listed files by filtered result\n");
-    fprintf(stderr,"                   --overwrite preserves timestamp of original files\n");
-#endif
-    fprintf(stderr," -g  --guess       Guess the input code\n");
-    fprintf(stderr," --help  --version Show this help/the version\n");
-    fprintf(stderr,"                   For more information, see also man nkf\n");
-    fprintf(stderr,"\n");
+           " --in-place[=SUFFIX]  --overwrite[=SUFFIX]\n"
+           "                   Overwrite original listed files by filtered result\n"
+           "                   --overwrite preserves timestamp of original files\n"
+#endif
+           " -g  --guess       Guess the input code\n"
+           " --help  --version Show this help/the version\n"
+           "                   For more information, see also man nkf\n"
+           "\n");
     version();
 }
 
 void show_configuration(void)
 {
-    fprintf(stderr, "Summary of my nkf " NKF_VERSION " (" NKF_RELEASE_DATE ") configuration:\n");
-    fprintf(stderr, "  Compile-time options:\n");
-    fprintf(stderr, "    Default encoding: "
-#if defined(DEFAULT_CODE_JIS)
-           "ISO-2022-JP"
-#elif defined(DEFAULT_CODE_SJIS)
-           "Shift_JIS"
-#elif defined(DEFAULT_CODE_EUC)
-           "EUC-JP"
-#elif defined(DEFAULT_CODE_UTF8)
-           "UTF-8"
+    fprintf(HELP_OUTPUT,
+           "Summary of my nkf " NKF_VERSION " (" NKF_RELEASE_DATE ") configuration:\n"
+           "  nkf identity:\n"
+           "    " NKF_IDENT "\n"
+           "  Compile-time options:\n"
+           "    Compiled at:                 " __DATE__ " " __TIME__ "\n"
+          );
+    fprintf(HELP_OUTPUT,
+           "    Default output encoding:     "
+#ifdef DEFAULT_ENCIDX
+           "%s\n", nkf_enc_name(nkf_default_encoding())
+#else
+           "%s (%s)\n", nkf_locale_encoding() ? "LOCALE" : "DEFAULT",
+           nkf_enc_name(nkf_default_encoding())
+#endif
+          );
+    fprintf(HELP_OUTPUT,
+           "    Default output newline:      "
+#if DEFAULT_NEWLINE == CR
+           "CR"
+#elif DEFAULT_NEWLINE == CRLF
+           "CRLF"
 #else
-           "UNKOWN"
+           "LF"
+#endif
+           "\n"
+           "    Decode MIME encoded string:  "
+#if MIME_DECODE_DEFAULT
+           "ON"
+#else
+           "OFF"
+#endif
+           "\n"
+           "    Convert JIS X 0201 Katakana: "
+#if X0201_DEFAULT
+           "ON"
+#else
+           "OFF"
+#endif
+           "\n"
+           "    --help, --version output:    "
+#if HELP_OUTPUT_HELP_OUTPUT
+           "HELP_OUTPUT"
+#else
+           "STDOUT"
 #endif
            "\n");
-    fprintf(stderr, "    Decode MIME encoded string:  %s\n", MIME_DECODE_DEFAULT ? "ON" : "OFF");
-    fprintf(stderr, "    Convert JIS X 0201 Katakana: %s\n", X0201_DEFAULT ? "ON" : "OFF");
-
-}
-
-void version(void)
-{
-    fprintf(stderr,"Network Kanji Filter Version " NKF_VERSION " (" NKF_RELEASE_DATE ") \n" COPY_RIGHT "\n");
 }
 #endif /*PERL_XS*/