ext/nkf/nkf1.7/nkf.c


DEFINITIONS

This source file includes following functions.
  1. _
  2. _
  3. main
  4. arguments
  5. noconvert
  6. kanji_convert
  7. h_conv
  8. push_hold_buf
  9. s_iconv
  10. e_oconv
  11. s_oconv
  12. j_oconv
  13. line_fold
  14. pre_convert
  15. mime_begin
  16. mime_begin
  17. mime_getc
  18. mime_ungetc
  19. mime_integrity
  20. base64decode
  21. reinit
  22. usage


   1  /** Network Kanji Filter. (PDS Version)
   2  ************************************************************************
   3  ** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
   4  ** $BO"Mm@h!'(B $B!J3t!KIY;NDL8&5f=j!!%=%U%H#38&!!;T@n!!;j(B 
   5  ** $B!J(BE-Mail Address: ichikawa@flab.fujitsu.co.jp$B!K(B
   6  ** Copyright (C) 1996,1998
   7  ** $BO"Mm@h!'(B $BN05eBg3X>pJs9)3X2J(B $B2OLn(B $B??<#(B  mine/X0208 support
   8  ** $B!J(BE-Mail Address: kono@ie.u-ryukyu.ac.jp$B!K(B
   9  ** $BO"Mm@h!'(B COW for DOS & Win16 & Win32 & OS/2
  10  ** $B!J(BE-Mail Address: GHG00637@niftyserve.or.p$B!K(B
  11  **    $B$3$N%=!<%9$N$$$+$J$kJ#<L!$2~JQ!$=$@5$b5vBz$7$^$9!#$?$@$7!"(B
  12  **    $B$=$N:]$K$O!"C/$,9W8%$7$?$r<($9$3$NItJ,$r;D$9$3$H!#(B
  13  **    $B:FG[I[$d;(;o$NIUO?$J$I$NLd$$9g$o$;$bI,MW$"$j$^$;$s!#(B
  14  **    $B$3$N%W%m%0%i%`$K$D$$$F$OFC$K2?$NJ]>Z$b$7$J$$!"0-$7$+$i$:!#(B
  15  **    Everyone is permitted to do anything on this program 
  16  **    including copying, modifying, improving.
  17  **    as long as you don't try to pretend that you wrote it.
  18  **    i.e., the above copyright notice has to appear in all copies.
  19  **    You don't have to ask before copying or publishing.
  20  **    THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
  21  ***********************************************************************/
  22  
  23  static char *CopyRight =
  24        "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),1998 S. Kono, COW";
  25  static char *Version =
  26        "1.7";
  27  static char *Patchlevel =
  28        "0/9711/Shinji Kono";
  29  
  30  /*
  31  **
  32  **
  33  **
  34  ** USAGE:       nkf [flags] [file] 
  35  **
  36  ** Flags:
  37  ** b    Output is bufferred             (DEFAULT)
  38  ** u    Output is unbufferred
  39  **
  40  ** t    no operation
  41  **
  42  ** j    Outout code is JIS 7 bit        (DEFAULT SELECT) 
  43  ** s    Output code is MS Kanji         (DEFAULT SELECT) 
  44  ** e    Output code is AT&T JIS         (DEFAULT SELECT) 
  45  ** l    Output code is JIS 7bit and ISO8859-1 Latin-1
  46  **
  47  ** m    MIME conversion for ISO-2022-JP
  48  ** i_ Output sequence to designate JIS-kanji (DEFAULT_J)
  49  ** o_ Output sequence to designate single-byte roman characters (DEFAULT_R)
  50  **
  51  ** r  {de/en}crypt ROT13/47
  52  **
  53  ** v  display Version
  54  **
  55  ** T  Text mode output        (for MS-DOS)
  56  **
  57  ** x    Do not convert X0201 kana into X0208
  58  ** Z    Convert X0208 alphabet to ASCII
  59  **
  60  ** f60  fold option
  61  **
  62  ** m    MIME decode
  63  ** B    try to fix broken JIS, missing Escape
  64  ** B[1-9]  broken level
  65  **
  66  ** O   Output to 'nkf.out' file 
  67  ** d   Delete \r in line feed 
  68  ** c   Add \r in line feed 
  69  **/
  70  /******************************/
  71  /* $B%G%U%)%k%H$N=PNO%3!<%IA*Br(B */
  72  /* Select DEFAULT_CODE */
  73  #define DEFAULT_CODE_JIS
  74  /* #define DEFAULT_CODE_SJIS */
  75  /* #define DEFAULT_CODE_EUC */
  76  /******************************/
  77  
  78  #if (defined(__TURBOC__) || defined(LSI_C)) && !defined(MSDOS)
  79  #define MSDOS
  80  #endif
  81  
  82  #ifndef PERL_XS
  83  #include <stdio.h>
  84  #endif
  85  
  86  #if defined(MSDOS) || defined(__OS2__) 
  87  #include <stdlib.h>
  88  #include <fcntl.h>
  89  #include <io.h>
  90  #endif
  91  
  92  #ifdef MSDOS
  93  #ifdef LSI_C
  94  #define setbinmode(fp) fsetbin(fp)
  95  #else /* Microsoft C, Turbo C */
  96  #define setbinmode(fp) setmode(fileno(fp), O_BINARY)
  97  #endif
  98  #else /* UNIX,OS/2 */
  99  #define setbinmode(fp)
 100  #endif
 101  
 102  #ifdef _IOFBF /* SysV and MSDOS */
 103  #define       setvbuffer(fp, buf, size)       setvbuf(fp, buf, _IOFBF, size)
 104  #else /* BSD */
 105  #define       setvbuffer(fp, buf, size)       setbuffer(fp, buf, size)
 106  #endif
 107  
 108  /*Borland C++ 4.5 EasyWin*/
 109  #if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */
 110  #define         EASYWIN
 111  #include <windows.h>
 112  #endif
 113  
 114  #define         FALSE   0
 115  #define         TRUE    1
 116  
 117  /* state of output_mode and input_mode  */
 118  
 119  #define         ASCII           0
 120  #define         X0208           1
 121  #define         X0201           2
 122  #define         NO_X0201        3
 123  #define         JIS_INPUT       4
 124  #define         SJIS_INPUT      5
 125  #define         LATIN1_INPUT    6
 126  #define         FIXED_MIME      7
 127  #define         DOUBLE_SPACE    -2
 128  
 129  #define         NL      0x0a
 130  #define         ESC     0x1b
 131  #define         SPACE   0x20
 132  #define         AT      0x40
 133  #define         SSP     0xa0
 134  #define         DEL     0x7f
 135  #define         SI      0x0f
 136  #define         SO      0x0e
 137  #define         SSO     0x8e
 138  
 139  #define         HOLD_SIZE       32
 140  #define         IOBUF_SIZE      16384
 141  
 142  #define         DEFAULT_J       'B'
 143  #define         DEFAULT_R       'B'
 144  
 145  #define         SJ0162  0x00e1          /* 01 - 62 ku offset */
 146  #define         SJ6394  0x0161          /* 63 - 94 ku offset */
 147  
 148  
 149  /* MIME preprocessor */
 150  
 151  #undef STRICT_MIME       /* do stupid strict mime integrity check */
 152  #define GETC(p) ((!mime_mode)?getc(p):mime_getc(p))
 153  #define UNGETC(c,p)     ((!mime_mode)?ungetc(c,p):mime_ungetc(c))
 154  
 155  
 156  #ifdef EASYWIN /*Easy Win */
 157  extern POINT _BufferSize;
 158  #endif
 159  
 160  /*      function prototype  */
 161  
 162  #ifndef _
 163  # ifdef __STDC__
 164  #  define _(args) args
 165  # else
 166  #  define _(args) ()
 167  # endif
 168  #endif
 169  
 170  #ifndef PERL_XS
 171  static  void    noconvert _((FILE *f));
 172  static  int     mime_integrity _((FILE *f,unsigned char *p));
 173  static  int     usage _((void));
 174  static char            stdibuf[IOBUF_SIZE];
 175  static char            stdobuf[IOBUF_SIZE];
 176  static unsigned int            mime_input = 0; /* undecoded */
 177  static int             end_check;
 178  #endif
 179  
 180  static  void    kanji_convert _((FILE *f));
 181  static  void    h_conv _((FILE *f,int c2,int c1));
 182  static  int     push_hold_buf _((int c2,int c1));
 183  static  void    s_iconv _((int c2,int c1));
 184  static  void    e_oconv _((int c2,int c1));
 185  static  void    s_oconv _((int c2,int c1));
 186  static  void    j_oconv _((int c2,int c1));
 187  static  int     line_fold _((int c2,int c1));
 188  static  int     pre_convert _((int c1,int c2));
 189  static  int     mime_begin _((FILE *f));
 190  static  int     mime_getc _((FILE *f));
 191  static  int     mime_ungetc _((unsigned int c));
 192  static  int     base64decode _((int c));
 193  static  void    arguments _((char *c));
 194  static  void    reinit _((void));
 195  
 196  /* buffers */
 197  
 198  static unsigned char   hold_buf[HOLD_SIZE*2];
 199  static int             hold_count;
 200  
 201  /* MIME preprocessor fifo */
 202  
 203  #define MIME_BUF_SIZE   (1024)    /* 2^n ring buffer */
 204  #define MIME_BUF_MASK   (MIME_BUF_SIZE-1)   
 205  #define Fifo(n)         mime_buf[(n)&MIME_BUF_MASK]
 206  static unsigned char           mime_buf[MIME_BUF_SIZE];
 207  static unsigned int            mime_top = 0;
 208  static unsigned int            mime_last = 0;  /* decoded */
 209  
 210  /* flags */
 211  static int             unbuf_f = FALSE;
 212  static int             estab_f = FALSE;
 213  static int             nop_f = FALSE;
 214  static int             binmode_f = TRUE;       /* binary mode */
 215  static int             rot_f = FALSE;          /* rot14/43 mode */
 216  static int             input_f = FALSE;        /* non fixed input code  */
 217  static int             alpha_f = FALSE;        /* convert JIx0208 alphbet to ASCII */
 218  static int             mime_f = TRUE;         /* convert MIME B base64 or Q */
 219  static int             mimebuf_f = FALSE;      /* MIME buffered input */
 220  static int             broken_f = FALSE;       /* convert ESC-less broken JIS */
 221  static int             iso8859_f = FALSE;      /* ISO8859 through */
 222  #if defined(MSDOS) || defined(__OS2__) 
 223  static int             x0201_f = TRUE;         /* Assume JISX0201 kana */
 224  #else
 225  static int             x0201_f = NO_X0201;     /* Assume NO JISX0201 */
 226  #endif
 227  
 228  /* X0208 -> ASCII converter */
 229  
 230  static int             c1_return;
 231  
 232  /* fold parameter */
 233  static int line = 0;    /* chars in line */
 234  static int prev = 0;
 235  static int             fold_f  = FALSE;
 236  static int             fold_len  = 0;
 237  
 238  /* options */
 239  static char            kanji_intro = DEFAULT_J,
 240                  ascii_intro = DEFAULT_R;
 241  
 242  /* Folding */
 243  
 244  int line_fold();
 245  #define FOLD_MARGIN  10
 246  #define DEFAULT_FOLD 60
 247  
 248  /* converters */
 249  
 250  #ifdef DEFAULT_CODE_JIS
 251  #   define  DEFAULT_CONV j_oconv
 252  #endif
 253  #ifdef DEFAULT_CODE_SJIS
 254  #   define  DEFAULT_CONV s_oconv
 255  #endif
 256  #ifdef DEFAULT_CODE_EUC
 257  #   define  DEFAULT_CONV e_oconv
 258  #endif
 259  
 260  static void            (*iconv) _((int c2,int c1));
 261                                          /* s_iconv or oconv */
 262  static void            (*oconv) _((int c2,int c1)) = DEFAULT_CONV; 
 263                                            /* [ejs]_oconv */
 264  
 265  /* Global states */
 266  static int             output_mode = ASCII,    /* output kanji mode */
 267                  input_mode =  ASCII,    /* input kanji mode */
 268                  shift_mode =  FALSE;    /* TRUE shift out, or X0201  */
 269  static int             mime_mode =   FALSE;    /* MIME mode B base64, Q hex */
 270  
 271  /* X0201 / X0208 conversion tables */
 272  
 273  /* X0201 kana conversion table */
 274  /* 90-9F A0-DF */
 275  unsigned char cv[]= {
 276  0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
 277  0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
 278  0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
 279  0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43,
 280  0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26,
 281  0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d,
 282  0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35,
 283  0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d,
 284  0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46,
 285  0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c,
 286  0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52,
 287  0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e,
 288  0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62,
 289  0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69,
 290  0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d,
 291  0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c,
 292  0x00,0x00};
 293  
 294  
 295  /* X0201 kana conversion table for daguten */
 296  /* 90-9F A0-DF */
 297  unsigned char dv[]= { 
 298  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 299  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 300  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 301  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 302  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 303  0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e,
 304  0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36,
 305  0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e,
 306  0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47,
 307  0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
 308  0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53,
 309  0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00,
 310  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 311  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 312  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 313  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 314  0x00,0x00};
 315  
 316  /* X0201 kana conversion table for han-daguten */
 317  /* 90-9F A0-DF */
 318  unsigned char ev[]= { 
 319  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 320  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 321  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 322  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 323  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 324  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 325  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 326  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 327  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 328  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 329  0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54,
 330  0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00,
 331  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 332  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 333  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 334  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 335  0x00,0x00};
 336  
 337  
 338  /* X0208 kigou conversion table */
 339  /* 0x8140 - 0x819e */
 340  unsigned char fv[] = {
 341  
 342  0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
 343  0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
 344  0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
 345  0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f,
 346  0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27,
 347  0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d,
 348  0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00,
 349  0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00,
 350  0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00,
 351  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 352  0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40,
 353  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
 354  } ;
 355  
 356  
 357  static int             file_out = FALSE;
 358  static int             add_cr = FALSE;
 359  static int             del_cr = FALSE;
 360  
 361  #ifndef PERL_XS
 362  int
 363  main(argc, argv)
 364      int             argc;
 365      char          **argv;
 366  {
 367      FILE  *fin;
 368      char  *cp;
 369  
 370  #ifdef EASYWIN /*Easy Win */
 371      _BufferSize.y = 400;/*Set Scroll Buffer Size*/
 372  #endif
 373  
 374      for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
 375          cp = *argv;
 376          arguments(cp);
 377      }
 378  
 379      if(iso8859_f && (oconv != j_oconv || !x0201_f )) {
 380          fprintf(stderr,"Mixed ISO8859/JISX0201/SJIS/EUC output is not allowed.\n");
 381          exit(1);
 382      }
 383  
 384      if(binmode_f == TRUE)
 385  #ifdef __OS2__
 386      if(freopen("","wb",stdout) == NULL) 
 387          return (-1);
 388  #else
 389      setbinmode(stdout);
 390  #endif
 391  
 392      if(unbuf_f)
 393        setbuf(stdout, (char *) NULL);
 394      else
 395        setvbuffer(stdout, stdobuf, IOBUF_SIZE);
 396  
 397      if(argc == 0) {
 398        if(binmode_f == TRUE)
 399  #ifdef __OS2__
 400        if(freopen("","rb",stdin) == NULL) return (-1);
 401  #else
 402        setbinmode(stdin);
 403  #endif
 404        setvbuffer(stdin, stdibuf, IOBUF_SIZE);
 405        if(nop_f)
 406            noconvert(stdin);
 407        else
 408            kanji_convert(stdin);
 409      } else {
 410        while (argc--) {
 411            if((fin = fopen(*argv++, "r")) == NULL) {
 412                perror(*--argv);
 413                return(-1);
 414            } else {
 415  /* reopen file for stdout */
 416                if(file_out == TRUE){ 
 417                    if(argc == 1 ) {
 418                        if(freopen(*argv++, "w", stdout) == NULL) {
 419                            perror(*--argv);
 420                            return (-1);
 421                        }
 422                        argc--;
 423                    } else {
 424                        if(freopen("nkf.out", "w", stdout) == NULL) {
 425                           perror(*--argv);
 426                           return (-1);
 427                        }
 428                    }
 429                    if(binmode_f == TRUE) {
 430  #ifdef __OS2__
 431                        if(freopen("","wb",stdout) == NULL) 
 432                             return (-1);
 433  #else
 434                        setbinmode(stdout);
 435  #endif
 436                    }
 437                }
 438                if(binmode_f == TRUE)
 439  #ifdef __OS2__
 440                   if(freopen("","rb",fin) == NULL) 
 441                      return (-1);
 442  #else
 443                   setbinmode(fin);
 444  #endif 
 445                setvbuffer(fin, stdibuf, IOBUF_SIZE);
 446                if(nop_f)
 447                    noconvert(fin);
 448                else
 449                    kanji_convert(fin);
 450                fclose(fin);
 451            }
 452        }
 453      }
 454  #ifdef EASYWIN /*Easy Win */
 455      if(file_out == FALSE) 
 456          scanf("%d",&end_check);
 457      else 
 458          fclose(stdout);
 459  #else /* for Other OS */
 460      if(file_out == TRUE) 
 461          fclose(stdout);
 462  #endif 
 463      return (0);
 464  }
 465  #endif
 466  
 467  static void
 468  arguments(cp) 
 469      char *cp;
 470  {
 471      while (*cp) {
 472          switch (*cp++) {
 473          case 'b':           /* buffered mode */
 474              unbuf_f = FALSE;
 475              continue;
 476          case 'u':           /* non bufferd mode */
 477              unbuf_f = TRUE;
 478              continue;
 479          case 't':           /* transparent mode */
 480              nop_f = TRUE;
 481              continue;
 482          case 'j':           /* JIS output */
 483          case 'n':
 484              oconv = j_oconv;
 485              continue;
 486          case 'e':           /* AT&T EUC output */
 487              oconv = e_oconv;
 488              continue;
 489          case 's':           /* SJIS output */
 490              oconv = s_oconv;
 491              continue;
 492          case 'l':           /* ISO8859 Latin-1 support, no conversion */
 493              iso8859_f = TRUE;  /* Only compatible with ISO-2022-JP */
 494              input_f = LATIN1_INPUT;
 495              continue;
 496          case 'i':           /* Kanji IN ESC-$-@/B */
 497              if(*cp=='@'||*cp=='B') 
 498                  kanji_intro = *cp++;
 499              continue;
 500          case 'o':           /* ASCII IN ESC-(-J/B */
 501              if(*cp=='J'||*cp=='B'||*cp=='H') 
 502                  ascii_intro = *cp++;
 503              continue;
 504          case 'r':
 505              rot_f = TRUE;
 506              continue;
 507  #if defined(MSDOS) || defined(__OS2__) 
 508          case 'T':
 509              binmode_f = FALSE;
 510              continue;
 511  #endif
 512  #ifndef PERL_XS
 513          case 'v':
 514              usage();
 515              exit(1);
 516              break;
 517  #endif
 518          /* Input code assumption */
 519          case 'J':   /* JIS input */
 520          case 'E':   /* AT&T EUC input */
 521              input_f = JIS_INPUT;
 522              continue;
 523          case 'S':   /* MS Kanji input */
 524              input_f = SJIS_INPUT;
 525              if(x0201_f==NO_X0201) x0201_f=TRUE;
 526              continue;
 527          case 'Z':   /* Convert X0208 alphabet to asii */
 528              /*  bit:0   Convert X0208
 529                  bit:1   Convert Kankaku to one space
 530                  bit:2   Convert Kankaku to two spaces
 531              */
 532              if('9'>= *cp && *cp>='0') 
 533                  alpha_f |= 1<<(*cp++ -'0');
 534              else 
 535                  alpha_f |= TRUE;
 536              continue;
 537          case 'x':   /* Convert X0201 kana to X0208 or X0201 Conversion */
 538              x0201_f = FALSE;    /* No X0201->X0208 conversion */
 539              /* accept  X0201
 540                      ESC-(-I     in JIS, EUC, MS Kanji
 541                      SI/SO       in JIS, EUC, MS Kanji
 542                      SSO         in EUC, JIS, not in MS Kanji
 543                      MS Kanji (0xa0-0xdf) 
 544                 output  X0201
 545                      ESC-(-I     in JIS (0x20-0x5f)
 546                      SSO         in EUC (0xa0-0xdf)
 547                      0xa0-0xd    in MS Kanji (0xa0-0xdf) 
 548              */
 549              continue;
 550          case 'X':   /* Assume X0201 kana */
 551              /* Default value is NO_X0201 for EUC/MS-Kanji mix */
 552              x0201_f = TRUE;
 553              continue;
 554          case 'f':   /* folding -f60 or -f */
 555              fold_f = TRUE;
 556              fold_len = atoi(cp);
 557              if(!(0<fold_len && fold_len<BUFSIZ)) 
 558                  fold_len = DEFAULT_FOLD;
 559              while('0'<= *cp && *cp <='9') cp++;
 560              continue;
 561          case 'm':   /* MIME support */
 562              mime_f = TRUE;
 563              if(*cp=='B'||*cp=='Q') {
 564                  mime_mode = *cp++;
 565                  mimebuf_f = FIXED_MIME;
 566              } else if (*cp=='0') {
 567                  mime_f = FALSE;
 568              }
 569              continue;
 570          case 'M':   /* MIME output */
 571              oconv = j_oconv;    /* sorry... not yet done.. */
 572              continue;
 573          case 'B':   /* Broken JIS support */
 574              /*  bit:0   no ESC JIS
 575                  bit:1   allow any x on ESC-(-x or ESC-$-x
 576                  bit:2   reset to ascii on NL
 577              */
 578              if('9'>= *cp && *cp>='0') 
 579                  broken_f |= 1<<(*cp++ -'0');
 580              else 
 581                  broken_f |= TRUE;
 582              continue;
 583  #ifndef PERL_XS
 584          case 'O':/* for Output file */
 585              file_out = TRUE;
 586              continue;
 587  #endif
 588          case 'c':/* add cr code */
 589              add_cr = TRUE;
 590              continue;
 591          case 'd':/* delete cr code */
 592              del_cr = TRUE;
 593              continue;
 594          default:
 595              /* bogus option but ignored */
 596              continue;
 597          }
 598      }
 599  }
 600  
 601  #ifndef PERL_XS
 602  static void
 603  noconvert(f)
 604      FILE  *f;
 605  {
 606      int    c;
 607  
 608      while ((c = getc(f)) != EOF)
 609        putchar(c);
 610  }
 611  #endif
 612  
 613  
 614  static void
 615  kanji_convert(f)
 616      FILE  *f;
 617  {
 618      int    c1, c2;
 619  
 620      c2 = 0;
 621  
 622      if(input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
 623          estab_f = TRUE; iconv = oconv;
 624      } else if(input_f == SJIS_INPUT) {
 625          estab_f = TRUE;  iconv = s_iconv;
 626      } else {
 627          estab_f = FALSE; iconv = oconv;
 628      }
 629      input_mode = ASCII;
 630      output_mode = ASCII;
 631      shift_mode = FALSE;
 632  
 633  #define NEXT continue      /* no output, get next */
 634  #define SEND ;             /* output c1 and c2, get next */
 635  #define LAST break         /* end of loop, go closing  */
 636  
 637      while ((c1 = GETC(f)) != EOF) {
 638          if(c2) {
 639              /* second byte */
 640              if(c2 > DEL) {
 641                  /* in case of 8th bit is on */
 642                  if(!estab_f) {
 643                      /* in case of not established yet */
 644                      if(c1 > SSP) {
 645                          /* It is still ambiguious */
 646                          h_conv(f, c2, c1);
 647                          c2 = 0;
 648                          NEXT;
 649                      } else if(c1 < AT) {
 650                          /* ignore bogus code */
 651                          c2 = 0;
 652                          NEXT;
 653                      } else {
 654                          /* established */
 655                          /* it seems to be MS Kanji */
 656                          estab_f = TRUE;
 657                          iconv = s_iconv;
 658                          SEND;
 659                      }
 660                  } else
 661                      /* in case of already established */
 662                      if(c1 < AT) {
 663                          /* ignore bogus code */
 664                          c2 = 0;
 665                          NEXT;
 666                      } else
 667                          SEND;
 668              } else
 669                  /* 7 bit code */
 670                  /* it might be kanji shitfted */
 671                  if((c1 == DEL) || (c1 <= SPACE)) {
 672                      /* ignore bogus first code */
 673                      c2 = 0;
 674                      NEXT;
 675                  } else
 676                      SEND;
 677          } else {
 678              /* first byte */
 679              if(c1 > DEL) {
 680                  /* 8 bit code */
 681                  if(!estab_f && !iso8859_f) {
 682                      /* not established yet */
 683                      if(c1 < SSP) {
 684                          /* it seems to be MS Kanji */
 685                          estab_f = TRUE;
 686                          iconv = s_iconv;
 687                      } else if(c1 < 0xe0) {
 688                          /* it seems to be EUC */
 689                          estab_f = TRUE;
 690                          iconv = oconv;
 691                      } else {
 692                          /* still ambiguious */
 693                      }
 694                      c2 = c1;
 695                      NEXT;
 696                  } else { /* estab_f==TRUE */
 697                      if(iso8859_f) {
 698                          SEND;
 699                      } else if(SSP<=c1 && c1<0xe0 && iconv == s_iconv) {
 700                          /* SJIS X0201 Case... */
 701                          /* This is too arrogant, but ... */
 702                          if(x0201_f==NO_X0201) {
 703                              iconv = oconv;
 704                              c2 = c1;
 705                              NEXT;
 706                          } else 
 707                          if(x0201_f) {
 708                              if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
 709                              /* look ahead for X0201/X0208conversion */
 710                                  if((c2 = GETC(f)) == EOF) {
 711                                      (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
 712                                      LAST;
 713                                  } else if(c2==(0xde)) { /* $BByE@(B */
 714                                      (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
 715                                      c2=0; 
 716                                      NEXT;
 717                                  } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) { 
 718                                      /* $BH>ByE@(B */
 719                                      (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
 720                                      c2=0; 
 721                                      NEXT;
 722                                  } 
 723                                  UNGETC(c2,f); c2 = 0;
 724                              }
 725                              (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
 726                              NEXT;
 727                          } else
 728                              SEND;
 729                      } else if(c1==SSO && iconv != s_iconv) {
 730                          /* EUC X0201 Case */
 731                          /* This is too arrogant
 732                          if(x0201_f == NO_X0201) {
 733                              estab_f = FALSE; 
 734                              c2 = 0;  
 735                              NEXT;
 736                          } */
 737                          c1 = GETC(f);  /* skip SSO */
 738                          euc_1byte_check:
 739                          if(x0201_f && SSP<=c1 && c1<0xe0) {
 740                              if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
 741                                  if((c2 = GETC(f)) == EOF) {
 742                                      (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
 743                                      LAST;
 744                                  }
 745                                  /* forward lookup $BByE@(B/$BH>ByE@(B */
 746                                  if(c2 != SSO) {
 747                                      UNGETC(c2,f); c2 = 0; 
 748                                      (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
 749                                      NEXT;
 750                                  } else if((c2 = GETC(f)) == EOF) {
 751                                      (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
 752                                      (*oconv)(0,SSO); 
 753                                      LAST;
 754                                  } else if(c2==(0xde)) { /* $BByE@(B */
 755                                      (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
 756                                      c2=0; 
 757                                      NEXT;
 758                                  } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) { 
 759                                      /* $BH>ByE@(B */
 760                                      (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
 761                                      c2=0; 
 762                                      NEXT;
 763                                  } else {
 764                                      (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
 765                                      /* we have to check this c2 */
 766                                      /* and no way to push back SSO */
 767                                      c1 = c2; c2 = 0;
 768                                      goto euc_1byte_check;
 769                                  }
 770                              }
 771                              (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
 772                              NEXT;
 773                          } else 
 774                              SEND;
 775                      } else if(c1 < SSP && iconv != s_iconv) {
 776                          /* strange code in EUC */
 777                          iconv = s_iconv;  /* try SJIS */
 778                          c2 = c1;
 779                          NEXT;
 780                      } else {
 781                         /* already established */
 782                         c2 = c1;
 783                         NEXT;
 784                      }
 785                  }
 786              } else if((c1 > SPACE) && (c1 != DEL)) {
 787                  /* in case of Roman characters */
 788                  if(shift_mode) { 
 789                      c1 |= 0x80;
 790                      /* output 1 shifted byte */
 791                      if(x0201_f && (!iso8859_f||input_mode==X0201) && 
 792                              SSP<=c1 && c1<0xe0 ) {
 793                          if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
 794                              if((c2 = GETC(f)) == EOF) {
 795                                  (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
 796                                  LAST;
 797                              } else if(c2==(0xde&0x7f)) { /* $BByE@(B */
 798                                  (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
 799                                  c2=0; 
 800                                  NEXT;
 801                              } else if(c2==(0xdf&0x7f)&&ev[(c1-SSP)*2]) {  
 802                                  /* $BH>ByE@(B */
 803                                  (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
 804                                  c2=0; 
 805                                  NEXT;
 806                              }
 807                              UNGETC(c2,f); c2 = 0;
 808                          }
 809                          (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
 810                          NEXT;
 811                      } else
 812                          SEND;
 813                  } else if(c1 == '(' && broken_f && input_mode == X0208
 814                          && !mime_mode ) {
 815                      /* Try to recover missing escape */
 816                      if((c1 = GETC(f)) == EOF) {
 817                          (*oconv)(0, '(');
 818                          LAST;
 819                      } else {
 820                          if(c1 == 'B' || c1 == 'J' || c1 == 'H') {
 821                              input_mode = ASCII; shift_mode = FALSE;
 822                              NEXT;
 823                          } else {
 824                              (*oconv)(0, '(');
 825                              /* do not modify various input_mode */
 826                              /* It can be vt100 sequence */
 827                              SEND;
 828                          }
 829                      }
 830                  } else if(input_mode == X0208) {
 831                      /* in case of Kanji shifted */
 832                      c2 = c1;
 833                      NEXT;
 834                      /* goto next_byte */
 835                  } else if(c1 == '=' && mime_f && !mime_mode ) {
 836                      if((c1 = getc(f)) == EOF) {
 837                          (*oconv)(0, '=');
 838                          LAST;
 839                      } else if(c1 == '?') {
 840                          /* =? is mime conversiooon start sequence */
 841                          if(mime_begin(f) == EOF) /* check in detail */
 842                              LAST;
 843                          else
 844                              NEXT;
 845                      } else {
 846                          (*oconv)(0, '=');
 847                          ungetc(c1,f);
 848                          NEXT;
 849                      }
 850                  } else if(c1 == '$' && broken_f && !mime_mode) {
 851                      /* try to recover missing escape */
 852                      if((c1 = GETC(f)) == EOF) {
 853                          (*oconv)(0, '$');
 854                          LAST;
 855                      } else if(c1 == '@'|| c1 == 'B') {
 856                          /* in case of Kanji in ESC sequence */
 857                          input_mode = X0208;
 858                          shift_mode = FALSE;
 859                          NEXT;
 860                      } else {
 861                          /* sorry */
 862                          (*oconv)(0, '$');
 863                          (*oconv)(0, c1);
 864                          NEXT;
 865                      }
 866                  } else
 867                      SEND;
 868              } else if(c1 == SI) {
 869                  shift_mode = FALSE; 
 870                  NEXT;
 871              } else if(c1 == SO) {
 872                  shift_mode = TRUE; 
 873                  NEXT;
 874              } else if(c1 == ESC) {
 875                  if((c1 = GETC(f)) == EOF) {
 876                      (*oconv)(0, ESC);
 877                      LAST;
 878                  } else if(c1 == '$') {
 879                      if((c1 = GETC(f)) == EOF) {
 880                          (*oconv)(0, ESC);
 881                          (*oconv)(0, '$');
 882                          LAST;
 883                      } else if(c1 == '@'|| c1 == 'B') {
 884                          /* This is kanji introduction */
 885                          input_mode = X0208;
 886                          shift_mode = FALSE;
 887                          NEXT;
 888                      } else if(c1 == '(') {
 889                          if((c1 = GETC(f)) == EOF) {
 890                              (*oconv)(0, ESC);
 891                              (*oconv)(0, '$');
 892                              (*oconv)(0, '(');
 893                              LAST;
 894                          } else if(c1 == '@'|| c1 == 'B') {
 895                              /* This is kanji introduction */
 896                              input_mode = X0208;
 897                              shift_mode = FALSE;
 898                              NEXT;
 899                          } else {
 900                              (*oconv)(0, ESC);
 901                              (*oconv)(0, '$');
 902                              (*oconv)(0, '(');
 903                              (*oconv)(0, c1);
 904                              NEXT;
 905                          }
 906                      } else if(broken_f&0x2) {
 907                          input_mode = X0208;
 908                          shift_mode = FALSE;
 909                          NEXT;
 910                      } else {
 911                          (*oconv)(0, ESC);
 912                          (*oconv)(0, '$');
 913                          (*oconv)(0, c1);
 914                          NEXT;
 915                      }
 916                  } else if(c1 == '(') {
 917                      if((c1 = GETC(f)) == EOF) {
 918                          (*oconv)(0, ESC);
 919                          (*oconv)(0, '(');
 920                          LAST;
 921                      } else {
 922                          if(c1 == 'I') {
 923                              /* This is X0201 kana introduction */
 924                              input_mode = X0201; shift_mode = X0201;
 925                              NEXT;
 926                          } else if(c1 == 'B' || c1 == 'J' || c1 == 'H') {
 927                              /* This is X0208 kanji introduction */
 928                              input_mode = ASCII; shift_mode = FALSE;
 929                              NEXT;
 930                          } else if(broken_f&0x2) {
 931                              input_mode = ASCII; shift_mode = FALSE;
 932                              NEXT;
 933                          } else {
 934                              (*oconv)(0, ESC);
 935                              (*oconv)(0, '(');
 936                              /* maintain various input_mode here */
 937                              SEND;
 938                          }
 939                      }
 940                  } else {
 941                      /* lonely ESC  */
 942                      (*oconv)(0, ESC);
 943                      SEND;
 944                  }
 945              } else if(c1 == NL && broken_f&4) {
 946                  input_mode = ASCII; 
 947                  SEND;
 948              } else
 949                  SEND;
 950          }
 951          /* send: */
 952          if(input_mode == X0208) 
 953              (*oconv)(c2, c1);  /* this is JIS, not SJIS/EUC case */
 954          else
 955              (*iconv)(c2, c1);  /* can be EUC/SJIS */
 956          c2 = 0;
 957          continue;
 958          /* goto next_word */
 959      }
 960  
 961      /* epilogue */
 962      (*iconv)(EOF, 0);
 963  }
 964  
 965  
 966  
 967  
 968  static void
 969  h_conv(f, c2, c1)
 970      FILE  *f;
 971      int    c1, c2;
 972  {
 973      int    wc;
 974  
 975  
 976      /** it must NOT be in the kanji shifte sequence      */
 977      /** it must NOT be written in JIS7                   */
 978      /** and it must be after 2 byte 8bit code            */
 979  
 980      hold_count = 0;
 981      push_hold_buf(c2, c1);
 982      c2 = 0;
 983  
 984      while ((c1 = GETC(f)) != EOF) {
 985          if(c2) {
 986              /* second byte */
 987              if(!estab_f) {
 988                  /* not established */
 989                  if(c1 > SSP) {
 990                      /* it is still ambiguious yet */
 991                      SEND;
 992                  } else if(c1 < AT) {
 993                      /* ignore bogus first byte */
 994                      c2 = 0;
 995                      SEND;
 996                  } else {
 997                      /* now established */
 998                      /* it seems to be MS Kanji */
 999                      estab_f = TRUE;
1000                      iconv = s_iconv;
1001                      SEND;
1002                  }
1003              } else
1004                  SEND;
1005          } else {
1006              /* First byte */
1007              if(c1 > DEL) {
1008                  /* 8th bit is on */
1009                  if(c1 < SSP) {
1010                      /* it seems to be MS Kanji */
1011                      estab_f = TRUE;
1012                      iconv = s_iconv;
1013                  } else if(c1 < 0xe0) {
1014                      /* it seems to be EUC */
1015                      estab_f = TRUE;
1016                      iconv = oconv;
1017                  } else {
1018                      /* still ambiguious */
1019                  }
1020                  c2 = c1;
1021                  NEXT;
1022              } else
1023              /* 7 bit code , then send without any process */
1024                  SEND;
1025          }
1026          /* send: */
1027          if((push_hold_buf(c2, c1) == EOF) || estab_f)
1028              break;
1029          c2 = 0;
1030          continue;
1031      }
1032  
1033      /** now,
1034       ** 1) EOF is detected, or
1035       ** 2) Code is established, or
1036       ** 3) Buffer is FULL (but last word is pushed)
1037       **
1038       ** in 1) and 3) cases, we continue to use
1039       ** Kanji codes by oconv and leave estab_f unchanged.
1040       **/
1041  
1042      for (wc = 0; wc < hold_count; wc += 2) {
1043          c2 = hold_buf[wc];
1044          c1 = hold_buf[wc+1];
1045          (*iconv)(c2, c1);
1046      }
1047      return;
1048  }
1049  
1050  
1051  
1052  static int
1053  push_hold_buf(c2, c1)
1054      int c2, c1;
1055  {
1056      if(hold_count >= HOLD_SIZE*2)
1057          return (EOF);
1058      hold_buf[hold_count++] = c2;
1059      hold_buf[hold_count++] = c1;
1060      return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count);
1061  }
1062  
1063  
1064  static void
1065  s_iconv(c2, c1)
1066      int    c2,
1067                      c1;
1068  {
1069      if((c2 == EOF) || (c2 == 0)) {
1070          /* NOP */
1071      } else {
1072          c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
1073          if(c1 < 0x9f)
1074              c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);
1075          else {
1076              c1 = c1 - 0x7e;
1077              c2++;
1078          }
1079      }
1080      (*oconv)(c2, c1);
1081  }
1082  
1083  
1084  static void
1085  e_oconv(c2, c1)
1086      int    c2, c1;
1087  {
1088      c2 = pre_convert(c1,c2); c1 = c1_return;
1089      if(fold_f) {
1090          switch(line_fold(c2,c1)) {
1091              case '\n': 
1092                  if(add_cr == TRUE) {
1093                      putchar('\r');
1094                      c1 = '\n';
1095                  }
1096                  putchar('\n');
1097                  break;
1098              case 0:    return;
1099              case '\r': 
1100                  c1 = '\n'; c2 = 0;
1101                  break;
1102              case '\t': 
1103              case ' ': 
1104                  c1 = ' '; c2 = 0;
1105                  break;
1106          }
1107      }
1108      if(c2==DOUBLE_SPACE) {
1109          putchar(' '); putchar(' ');
1110          return;
1111      }
1112      if(c2 == EOF)
1113          return;
1114      else if(c2 == 0 && (c1&0x80)) {
1115          putchar(SSO); putchar(c1);
1116      } else if(c2 == 0) {
1117          if(c1 == '\n' && add_cr == TRUE) 
1118              putchar('\r');
1119          if(c1 != '\r') 
1120              putchar(c1);
1121          else if(del_cr == FALSE) 
1122              putchar(c1);
1123      } else {
1124          if((c1<0x20 || 0x7e<c1) ||
1125             (c2<0x20 || 0x7e<c2)) {
1126              estab_f = FALSE;
1127              return; /* too late to rescue this char */
1128          }
1129          putchar(c2 | 0x080);
1130          putchar(c1 | 0x080);
1131      }
1132      return;
1133  }
1134  
1135  
1136  static void
1137  s_oconv(c2, c1)
1138      int    c2, c1;
1139  {
1140      c2 = pre_convert(c1,c2); c1 = c1_return;
1141      if(fold_f) {
1142          switch(line_fold(c2,c1)) {
1143              case '\n': 
1144                  if(add_cr == TRUE) {
1145                     putchar('\r');
1146                     c1 = '\n';
1147                  }
1148                  putchar('\n');
1149                  break;
1150              case '\r': 
1151                  c1 = '\n'; c2 = 0;
1152                  break;
1153              case 0:    return;
1154              case '\t': 
1155              case ' ': 
1156                  c1 = ' '; c2 = 0;
1157                  break;
1158          }
1159      }
1160      if(c2==DOUBLE_SPACE) {
1161          putchar(' '); putchar(' ');
1162          return;
1163      }
1164      if(c2 == EOF)
1165          return;
1166      else if(c2 == 0) {
1167          if(c1 == '\n' && add_cr == TRUE) 
1168              putchar('\r');
1169          if(c1 != '\r') 
1170              putchar(c1);
1171          else if(del_cr == FALSE) 
1172              putchar(c1);
1173      } else {
1174          if((c1<0x20 || 0x7e<c1) ||
1175             (c2<0x20 || 0x7e<c2)) {
1176              estab_f = FALSE;
1177              return; /* too late to rescue this char */
1178          }
1179          putchar((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1)));
1180          putchar((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e)));
1181      }
1182      return;
1183  }
1184  
1185  
1186  static void
1187  j_oconv(c2, c1)
1188      int    c2, c1;
1189  {
1190      c2 = pre_convert(c1,c2); c1 = c1_return;
1191      if(fold_f) {
1192          switch(line_fold(c2,c1)) {
1193              case '\n': 
1194                  if(output_mode) {
1195                      putchar(ESC);
1196                      putchar('(');
1197                      putchar(ascii_intro);
1198                  }
1199                  if(add_cr == TRUE) {
1200                      putchar('\r');
1201                      c1 = '\n';
1202                  }
1203                  putchar('\n');
1204                  output_mode = ASCII;
1205                  break;
1206              case '\r': 
1207                  c1 = '\n'; c2 = 0;
1208                  break;
1209              case '\t': 
1210              case ' ': 
1211                  c1 = ' '; c2 = 0;
1212                  break;
1213              case 0:    return;
1214          }
1215       }
1216      if(c2 == EOF) {
1217          if(output_mode) {
1218              putchar(ESC);
1219              putchar('(');
1220              putchar(ascii_intro);
1221          }
1222      } else if(c2 == 0 && (c1 & 0x80)) {
1223          if(input_mode==X0201 || !iso8859_f) {
1224              if(output_mode!=X0201) {
1225                  putchar(ESC);
1226                  putchar('(');
1227                  putchar('I');
1228                  output_mode = X0201;
1229              }
1230              c1 &= 0x7f;
1231          } else {
1232              /* iso8859 introduction, or 8th bit on */
1233              /* Can we convert in 7bit form using ESC-'-'-A ? 
1234                 Is this popular? */
1235          }
1236          putchar(c1);
1237      } else if(c2 == 0) {
1238          if(output_mode) {
1239              putchar(ESC);
1240              putchar('(');
1241              putchar(ascii_intro);
1242              output_mode = ASCII;
1243          }
1244          if(c1 == '\n' && add_cr == TRUE) 
1245              putchar('\r');
1246          if(c1 != '\r') 
1247              putchar(c1);
1248          else if(del_cr == FALSE) 
1249              putchar(c1);
1250      } else if(c2 == DOUBLE_SPACE) {
1251          if(output_mode) {
1252              putchar(ESC);
1253              putchar('(');
1254              putchar(ascii_intro);
1255              output_mode = ASCII;
1256          }
1257          putchar(' ');
1258          if(c1 == '\n' && add_cr == TRUE) 
1259              putchar('\r');
1260          if(c1 != '\r') 
1261              putchar(c1);
1262          else if(del_cr == FALSE) 
1263              putchar(c1);
1264      } else {
1265          if(output_mode != X0208) {
1266              putchar(ESC);
1267              putchar('$');
1268              putchar(kanji_intro);
1269              output_mode = X0208;
1270          }
1271          if(c1<0x20 || 0x7e<c1) 
1272              return;
1273          if(c2<0x20 || 0x7e<c2) 
1274              return;
1275          putchar(c2);
1276          if(c1 == '\n' && add_cr == TRUE) 
1277              putchar('\r');
1278          if(c1 != '\r') 
1279              putchar(c1);
1280          else if(del_cr == FALSE) 
1281              putchar(c1);
1282      }
1283      return;
1284  }
1285  
1286  
1287  
1288  #define rot13(c)  ( \
1289        ( c < 'A' ) ? c: \
1290        (c <= 'M')  ? (c + 13): \
1291        (c <= 'Z')  ? (c - 13): \
1292        (c < 'a')   ? (c): \
1293        (c <= 'm')  ? (c + 13): \
1294        (c <= 'z')  ? (c - 13): \
1295        (c) \
1296  )
1297  
1298  #define  rot47(c) ( \
1299        ( c < '!' ) ? c: \
1300        ( c <= 'O' ) ? (c + 47) : \
1301        ( c <= '~' ) ?  (c - 47) : \
1302        c \
1303  )
1304  
1305  
1306  /* 
1307    Return value of line_fold()
1308  
1309         \n  add newline  and output char
1310         \r  add newline  and output nothing
1311         ' ' space
1312         0   skip  
1313         1   (or else) normal output 
1314  
1315    fold state in prev (previous character)
1316  
1317        >0x80 Japanese (X0208/X0201)
1318        <0x80 ASCII
1319        \n    new line 
1320        ' '   space
1321  
1322    This fold algorthm does not preserve heading space in a line.
1323    This is the main difference from fmt.
1324  */
1325  
1326  static int
1327  line_fold(c2,c1) 
1328  int c2,c1;
1329  { 
1330      int prev0;
1331      if(c1=='\r') 
1332          return 0;               /* ignore cr */
1333      if(c1== 8) {
1334          if(line>0) line--;
1335          return 1;
1336      }
1337      if(c2==EOF && line != 0)    /* close open last line */
1338          return '\n';
1339      /* new line */
1340      if(c1=='\n') {
1341          if(prev == c1) {        /* duplicate newline */
1342              if(line) {
1343                  line = 0;
1344                  return '\n';    /* output two newline */
1345              } else {
1346                  line = 0;
1347                  return 1;
1348              }
1349          } else  {
1350              if(prev&0x80) {     /* Japanese? */
1351                  prev = c1;
1352                  return 0;       /* ignore given single newline */
1353              } else if(prev==' ') {
1354                  return 0;
1355              } else {
1356                  prev = c1;
1357                  if(++line<=fold_len) 
1358                      return ' ';
1359                  else {
1360                      line = 0;
1361                      return '\r';        /* fold and output nothing */
1362                  }
1363              }
1364          }
1365      }
1366      if(c1=='\f') {
1367          prev = '\n';
1368          if(line==0)
1369              return 1;
1370          line = 0;
1371          return '\n';            /* output newline and clear */
1372      }
1373      /* X0208 kankaku or ascii space */
1374      if( (c2==0&&c1==' ')||
1375          (c2==0&&c1=='\t')||
1376          (c2==DOUBLE_SPACE)||
1377          (c2=='!'&& c1=='!')) {
1378          if(prev == ' ') {
1379              return 0;           /* remove duplicate spaces */
1380          } 
1381          prev = ' ';    
1382          if(++line<=fold_len) 
1383              return ' ';         /* output ASCII space only */
1384          else {
1385              prev = ' '; line = 0;
1386              return '\r';        /* fold and output nothing */
1387          }
1388      } 
1389      prev0 = prev; /* we still need this one... , but almost done */
1390      prev = c1;
1391      if(c2 || (SSP<=c1 && c1<=0xdf)) 
1392          prev |= 0x80;  /* this is Japanese */
1393      line += (c2==0)?1:2;
1394      if(line<=fold_len) {   /* normal case */
1395          return 1;
1396      }
1397      if(line>=fold_len+FOLD_MARGIN) { /* too many kinsou suspension */
1398          line = (c2==0)?1:2;
1399          return '\n';       /* We can't wait, do fold now */
1400      }
1401      /* simple kinsoku rules  return 1 means no folding  */
1402      if(c2==0) {
1403          if(c1==0xde) return 1; /* $B!+(B*/
1404          if(c1==0xdf) return 1; /* $B!,(B*/
1405          if(c1==0xa4) return 1; /* $B!#(B*/
1406          if(c1==0xa3) return 1; /* $B!$(B*/
1407          if(c1==0xa1) return 1; /* $B!W(B*/
1408          if(c1==0xb0) return 1; /* - */
1409          if(SSP<=c1 && c1<=0xdf) {               /* X0201 */
1410              line = 1;
1411              return '\n';/* add one new line before this character */
1412          }
1413          /* fold point in ASCII { [ ( */
1414          if(( c1!=')'&&
1415               c1!=']'&&
1416               c1!='}'&&
1417               c1!='.'&&
1418               c1!=','&&
1419               c1!='!'&&
1420               c1!='?'&&
1421               c1!='/'&&
1422               c1!=':'&&
1423               c1!=';')&&
1424              ((prev0=='\n')|| (prev0==' ')||     /* ignored new line */
1425              (prev0&0x80))                       /* X0208 - ASCII */
1426              ) {
1427              line = 1;
1428              return '\n';/* add one new line before this character */
1429          }
1430          return 1;  /* default no fold in ASCII */
1431      } else {
1432          if(c2=='!') {
1433              if(c1=='"')  return 1; /* $B!"(B */
1434              if(c1=='#')  return 1; /* $B!#(B */
1435              if(c1=='$')  return 1; /* $B!$(B */
1436              if(c1=='%')  return 1; /* $B!%(B */
1437              if(c1=='\'') return 1; /* $B!\(B */
1438              if(c1=='(')  return 1; /* $B!((B */
1439              if(c1==')')  return 1; /* $B!)(B */
1440              if(c1=='*')  return 1; /* $B!*(B */
1441              if(c1=='+')  return 1; /* $B!+(B */
1442              if(c1==',')  return 1; /* $B!,(B */
1443          }
1444          line = 2;
1445          return '\n'; /* add one new line before this character */
1446      }
1447  }
1448  
1449  static int
1450  pre_convert(c1,c2)
1451      int c1,c2;
1452  {
1453          if(c2) c1 &= 0x7f;
1454          c1_return = c1;
1455          if(c2==EOF) return c2;
1456          c2 &= 0x7f;
1457          if(rot_f) {
1458              if(c2) {
1459                  c1 = rot47(c1);
1460                  c2 = rot47(c2);
1461              } else {
1462                  if(!(c1 & 0x80)) 
1463                      c1 = rot13(c1);
1464              }
1465              c1_return = c1;
1466          }
1467          /* JISX0208 Alphabet */
1468          if(alpha_f && c2 == 0x23 ) return 0; 
1469          /* JISX0208 Kigou */
1470          if(alpha_f && c2 == 0x21 ) { 
1471             if(0x21==c1) {
1472                 if(alpha_f&0x2) {
1473                     c1_return = ' ';
1474                     return 0;
1475                 } else if(alpha_f&0x4) {
1476                     c1_return = ' ';
1477                     return DOUBLE_SPACE;
1478                 } else {
1479                     return c2;
1480                 }
1481             } else if(0x20<c1 && c1<0x7f && fv[c1-0x20]) {
1482                 c1_return = fv[c1-0x20];
1483                 return 0;
1484             } 
1485          }
1486          return c2;
1487  }
1488  
1489  
1490  #ifdef STRICT_MIME
1491  /* This converts  */
1492  
1493  unsigned char *mime_pattern[] = {
1494     (unsigned char *)"\075?ISO-8859-1?Q?",
1495     (unsigned char *)"\075?ISO-2022-JP?B?",
1496     (unsigned char *)"\075?ISO-2022-JP?Q?",
1497     (unsigned char *)"\075?JAPANESE_EUC?B?",
1498     (unsigned char *)"\075?SHIFT_JIS?B?",
1499     NULL
1500  };
1501  
1502  int      mime_encode[] = {
1503      'Q', 'B', 'Q',
1504      0
1505  };
1506  #endif
1507  
1508  #define MAXRECOVER 20
1509  int iso8859_f_save;
1510  
1511  #ifdef STRICT_MIME
1512  
1513  #define nkf_toupper(c)  (('a'<=c && c<='z')?(c-('a'-'A')):c)
1514  /* I don't trust portablity of toupper */
1515  
1516  static int
1517  mime_begin(f)
1518      FILE *f;
1519  {
1520      int c1;
1521      int i,j,k;
1522      unsigned char *p,*q;
1523      int r[MAXRECOVER];    /* recovery buffer, max mime pattern lenght */
1524  
1525      mime_mode = FALSE;
1526      /* =? has been checked   */
1527      j = 0;
1528      p = mime_pattern[j];
1529      r[0]='='; r[1]='?';
1530  
1531      for(i=2;p[i]>' ';i++) {                   /* start at =? */
1532          if( ((((r[i] = c1 = getc(f))==EOF) || nkf_toupper(c1) != p[i] ) {
1533              /* pattern fails, try next one */
1534              q = p;
1535              while (p = mime_pattern[++j]) {
1536                  for(k=2;k<i;k++)              /* assume length(p) > i */
1537                      if(p[k]!=q[k]) break;
1538                  if(k==i && nkf_toupper(c1)==p[k]) break;
1539              }
1540              if(p) continue;  /* found next one, continue */
1541              /* all fails, output from recovery buffer */
1542              ungetc(c1,f);
1543              for(j=0;j<i;j++) {
1544                  (*oconv)(0,r[j]);
1545              }
1546              return c1;
1547          }
1548      }
1549      mime_mode = mime_encode[j];
1550      iso8859_f_save = iso8859_f;
1551      if(j==0) {
1552          iso8859_f = TRUE;
1553      }
1554      if(mime_mode=='B') {
1555          mimebuf_f = unbuf_f;
1556          if(!unbuf_f) {
1557              /* do MIME integrity check */
1558              return mime_integrity(f,mime_pattern[j]);
1559          } 
1560      }
1561      mimebuf_f = TRUE;
1562      return c1;
1563  }
1564  
1565  #define mime_getc0(f)   (mimebuf_f?getc(f):Fifo(mime_input++))
1566  #define mime_ungetc0(c,f) (mimebuf_f?ungetc(c,f):mime_input--)
1567  
1568  #else
1569  static int
1570  mime_begin(f)
1571  FILE *f;
1572  {
1573      int c1;
1574      int i,j;
1575      int r[MAXRECOVER];    /* recovery buffer, max mime pattern lenght */
1576  
1577      mime_mode = FALSE;
1578      /* =? has been checked   */
1579      j = 0;
1580      r[0]='='; r[1]='?';
1581      for(i=2;i<MAXRECOVER;i++) {                   /* start at =? */
1582          /* We accept any charcter type even if it is breaked by new lines */
1583          if( (r[i] = c1 = getc(f))==EOF) break;
1584          if(c1=='=') break;
1585          if(c1<' '&& c1!='\r' && c1!='\n') break;
1586          if(c1=='?') {
1587              i++;
1588              if(!(i<MAXRECOVER) || (r[i] = c1 = getc(f))==EOF) break;
1589              if(c1=='b'||c1=='B') {
1590                  mime_mode = 'B';
1591              } else if(c1=='q'||c1=='Q') {
1592                  mime_mode = 'Q';
1593              } else {
1594                  break;
1595              }
1596              i++;
1597              if(!(i<MAXRECOVER) || (r[i] = c1 = getc(f))==EOF) break;
1598              if(c1=='?') {
1599                  break;
1600              } else {
1601                  mime_mode = FALSE;
1602              }
1603              break;
1604          }
1605      }
1606      if(!mime_mode || c1==EOF || i==MAXRECOVER) {
1607          ungetc(c1,f);
1608          if (i == MAXRECOVER)
1609              i--;
1610          for(j=0;j<i;j++) {
1611              (*oconv)(0,r[j]);
1612          }
1613          return c1;
1614      }
1615      iso8859_f_save = iso8859_f;
1616      /* do no MIME integrity check */
1617      return c1;   /* used only for checking EOF */
1618  }
1619  
1620  #define mime_getc0(f)   getc(f)
1621  #define mime_ungetc0(c,f) ungetc(c,f)
1622  
1623  #endif
1624  
1625  static int 
1626  mime_getc(f)
1627      FILE *f;
1628  {
1629      int c1, c2, c3, c4, cc;
1630      int t1, t2, t3, t4, mode, exit_mode;
1631  
1632      if(mime_top != mime_last) {  /* Something is in FIFO */
1633          return  Fifo(mime_top++);
1634      }
1635  
1636      if(mimebuf_f == FIXED_MIME)
1637          exit_mode = mime_mode;
1638      else
1639          exit_mode = FALSE;
1640      if(mime_mode == 'Q') {
1641          if((c1 = mime_getc0(f)) == EOF) return (EOF);
1642          if(c1=='_') return ' ';
1643          if(c1!='=' && c1!='?') 
1644              return c1;
1645          mime_mode = exit_mode; /* prepare for quit */
1646          if(c1<=' ') return c1;
1647          if((c2 = mime_getc0(f)) == EOF) return (EOF);
1648          if(c2<=' ') return c2;
1649          if(c1=='?'&&c2=='=') {
1650              /* end Q encoding */
1651              input_mode = exit_mode;
1652              iso8859_f = iso8859_f_save;
1653              return getc(f);
1654          }
1655          if(c1=='?') {
1656              mime_mode = 'Q'; /* still in MIME */
1657              mime_ungetc0(c2,f);
1658              return c1;
1659          }
1660          if((c3 = mime_getc0(f)) == EOF) return (EOF);
1661          if(c2<=' ') return c2;
1662          mime_mode = 'Q'; /* still in MIME */
1663  #define hex(c)   (('0'<=c&&c<='9')?(c-'0'):\
1664       ('A'<=c&&c<='F')?(c-'A'+10):('a'<=c&&c<='f')?(c-'a'+10):0)
1665          return ((hex(c2)<<4) + hex(c3));
1666      }
1667  
1668      if(mime_mode != 'B') {
1669          mime_mode = FALSE;
1670          return getc(f);
1671      }
1672  
1673  
1674      /* Base64 encoding */
1675      /* 
1676          MIME allows line break in the middle of 
1677          Base64, but we are very pessimistic in decoding
1678          in unbuf mode because MIME encoded code may broken by 
1679          less or editor's control sequence (such as ESC-[-K in unbuffered
1680          mode. ignore incomplete MIME.
1681      */
1682      mode = mime_mode;
1683      mime_mode = exit_mode;  /* prepare for quit */
1684  
1685      while ((c1 = mime_getc0(f))<=' ') {
1686          if(c1==EOF)
1687              return (EOF);
1688      }
1689      if((c2 = mime_getc0(f))<=' ') {
1690          if(c2==EOF)
1691              return (EOF);
1692          if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
1693          return c2;
1694      }
1695      if((c1 == '?') && (c2 == '=')) {
1696          input_mode = ASCII;
1697          while((c1 =  getc(f))==' ' /* || c1=='\n' || c1=='\r' */);
1698          return c1;
1699      }
1700      if((c3 = mime_getc0(f))<=' ') {
1701          if(c3==EOF)
1702              return (EOF);
1703          if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
1704          return c3;
1705      }
1706      if((c4 = mime_getc0(f))<=' ') {
1707          if(c4==EOF)
1708              return (EOF);
1709          if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;  
1710          return c4;
1711      }
1712  
1713      mime_mode = mode; /* still in MIME sigh... */
1714  
1715      /* BASE 64 decoding */
1716  
1717      t1 = 0x3f & base64decode(c1);
1718      t2 = 0x3f & base64decode(c2);
1719      t3 = 0x3f & base64decode(c3);
1720      t4 = 0x3f & base64decode(c4);
1721      cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03);
1722      if(c2 != '=') {
1723          Fifo(mime_last++) = cc;
1724          cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f);
1725          if(c3 != '=') {
1726              Fifo(mime_last++) = cc;
1727              cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f);
1728              if(c4 != '=') 
1729                  Fifo(mime_last++) = cc;
1730          }
1731      } else {
1732          return c1;
1733      }
1734      return  Fifo(mime_top++);
1735  }
1736  
1737  static int
1738  mime_ungetc(c) 
1739      unsigned int c;
1740  {
1741      Fifo(mime_last++) = c;
1742      return c;
1743  }
1744  
1745  #ifdef STRICT_MIME
1746  int
1747  mime_integrity(f,p)
1748      FILE *f;
1749      unsigned char *p;
1750  {
1751      int c,d;
1752      unsigned int q;
1753      /* In buffered mode, read until =? or NL or buffer fffull
1754       */
1755      mime_input = mime_top;
1756      mime_last = mime_top;
1757      while(*p) Fifo(mime_input++) = *p++;
1758      d = 0;
1759      q = mime_input;
1760      while((c=getc(f))!=EOF) {
1761          if(((mime_input-mime_top)&MIME_BUF_MASK)==0) break;
1762          if(c=='=' && d=='?') {
1763              /* checked. skip header, start decode */
1764              Fifo(mime_input++) = c;
1765              mime_input = q; 
1766              return 1;
1767          }
1768          if(!( (c=='+'||c=='/'|| c=='=' || c=='?' ||
1769              ('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9'))))
1770              break;
1771          /* Should we check length mod 4? */
1772          Fifo(mime_input++) = c;
1773          d=c;
1774      }
1775      /* In case of Incomplete MIME, no MIME decode  */
1776      Fifo(mime_input++) = c;
1777      mime_last = mime_input;     /* point undecoded buffer */
1778      mime_mode = 1;              /* no decode on Fifo last in mime_getc */
1779      return 1;
1780  }
1781  #endif
1782  
1783  static int
1784  base64decode(c)
1785      int c;
1786  {
1787      int             i;
1788      if(c > '@')
1789          if(c < '[')
1790              i = c - 'A';                        /* A..Z 0-25 */
1791          else
1792              i = c - 'G'     /* - 'a' + 26 */ ;  /* a..z 26-51 */
1793      else if(c > '/')
1794          i = c - '0' + '4'   /* - '0' + 52 */ ;  /* 0..9 52-61 */
1795      else if(c == '+')
1796          i = '>'             /* 62 */ ;          /* +  62 */
1797      else
1798          i = '?'             /* 63 */ ;          /* / 63 */
1799      return (i);
1800  }
1801  
1802  static void 
1803  reinit()
1804  {
1805      unbuf_f = FALSE;
1806      estab_f = FALSE;
1807      nop_f = FALSE;
1808      binmode_f = TRUE;       
1809      rot_f = FALSE;         
1810      input_f = FALSE;      
1811      alpha_f = FALSE;     
1812      mime_f = TRUE;      
1813      mimebuf_f = FALSE; 
1814      broken_f = FALSE;  
1815      iso8859_f = FALSE; 
1816      x0201_f = TRUE;    
1817      x0201_f = NO_X0201; 
1818      fold_f  = FALSE;
1819      kanji_intro = DEFAULT_J;
1820      ascii_intro = DEFAULT_R;
1821      oconv = DEFAULT_CONV; 
1822      output_mode = ASCII;
1823      input_mode =  ASCII;
1824      shift_mode =  FALSE;
1825      mime_mode =   FALSE;
1826      file_out = FALSE;
1827      add_cr = FALSE;
1828      del_cr = FALSE;
1829      line = 0;
1830  }
1831  
1832  #ifndef PERL_XS
1833  int 
1834  usage()   
1835  {
1836      fprintf(stderr,"USAGE:  nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n");
1837      fprintf(stderr,"Flags:\n");
1838      fprintf(stderr,"b,u      Output is bufferred (DEFAULT),Output is unbufferred\n");
1839  #ifdef DEFAULT_CODE_SJIS
1840      fprintf(stderr,"j,s,e    Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC)\n");
1841  #endif
1842  #ifdef DEFAULT_CODE_JIS
1843      fprintf(stderr,"j,s,e    Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC)\n");
1844  #endif
1845  #ifdef DEFAULT_CODE_EUC
1846      fprintf(stderr,"j,s,e    Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT)\n");
1847  #endif
1848      fprintf(stderr,"J,S,E    Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC)\n");
1849      fprintf(stderr,"t        no conversion\n");
1850      fprintf(stderr,"i_       Output sequence to designate JIS-kanji (DEFAULT B)\n");
1851      fprintf(stderr,"o_       Output sequence to designate ASCII (DEFAULT B)\n");
1852      fprintf(stderr,"r        {de/en}crypt ROT13/47\n");
1853      fprintf(stderr,"v        Show this usage\n");
1854      fprintf(stderr,"m[BQ0]   MIME decode [B:base64,Q:quoted,0:no decode]\n");
1855      fprintf(stderr,"l        ISO8859-1 (Latin-1) support\n");
1856      fprintf(stderr,"f        Folding: -f60 or -f\n");
1857      fprintf(stderr,"Z[0-2]   Convert X0208 alphabet to ASCII  1: Kankaku to space,2: 2 spaces\n");
1858      fprintf(stderr,"X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201\n");
1859      fprintf(stderr,"B[0-2]   Broken input  0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n");
1860  #ifdef MSDOS
1861      fprintf(stderr,"T        Text mode output\n");
1862  #endif
1863      fprintf(stderr,"O        Output to File (DEFAULT 'nkf.out')\n");
1864      fprintf(stderr,"d,c      Delete \\r in line feed, Add \\r in line feed\n");
1865      fprintf(stderr,"Network Kanji Filter Version %s (%s) "
1866  #if defined(MSDOS) && !defined(_Windows)
1867                    "for DOS"
1868  #endif
1869  #if !defined(__WIN32__) && defined(_Windows)
1870                    "for Win16"
1871  #endif
1872  #if defined(__WIN32__) && defined(_Windows)
1873                    "for Win32"
1874  #endif
1875  #ifdef __OS2__
1876                    "for OS/2"
1877  #endif
1878                    ,Version,Patchlevel);
1879      fprintf(stderr,"\n%s\n",CopyRight);
1880      return 0;
1881  }
1882  #endif
1883  
1884  /**
1885   ** $B%Q%C%A@):n<T(B
1886   **  void@merope.pleiades.or.jp (Kusakabe Youichi)
1887   **  NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
1888   **  ohta@src.ricoh.co.jp (Junn Ohta)
1889   **  inouet@strl.nhk.or.jp (Tomoyuki Inoue)
1890   **  kiri@pulser.win.or.jp (Tetsuaki Kiriyama)
1891   **  Kimihiko Sato <sato@sail.t.u-tokyo.ac.jp>
1892   **  a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
1893   **  kono@ie.u-ryukyu.ac.jp (Shinji Kono)
1894   **  GHG00637@nifty-serve.or.jp (COW)
1895   **
1896   ** $B:G=*99?7F|(B
1897   **  1998.11.7
1898   **/
1899  
1900  /* end */