home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / j_tools.zip / jcode.c < prev    next >
C/C++ Source or Header  |  1998-01-14  |  32KB  |  1,038 lines

  1. /*
  2. Program: jcode.c
  3. Version: 3.0
  4. Date:    July 1, 1993
  5. Author:  Ken R. Lunde, Adobe Systems Incorporated
  6.   EMAIL: lunde@mv.us.adobe.com
  7.   MAIL : 1585 Charleston Road, P.O. Box 7900, Mountain View, CA 94039-7900
  8. Type:    A tool for displaying the electronic values of Japanese characters.
  9. Code:    ANSI C (portable)
  10.  
  11. PORTABILITY:
  12. This source code was written so that it would be portable on C compilers which
  13. conform to the ANSI C standard. It has been tested on a variety of compilers.
  14.  
  15. I used THINK C and GNU C as my development platforms. I left in the Macintosh-
  16. specific lines of code so that it would be easier to enhance/debug this tool
  17. later. For those of you who wish to use this tool on the Macintosh, simply
  18. add the ANSI library to the THINK C project, and then build the application.
  19. Be sure that THINK_C has been defined, though, as the conditional compilation
  20. depends on it. You then have a double-clickable application, which when
  21. launched, will greet you with a Macintosh-style interface.
  22.  
  23. DISTRIBUTION AND RESTRICTIONS ON USAGE:
  24.  1) Please give this source code away to your friends at no charge.
  25.  2) Please try to compile this source code on various platforms to check for
  26.     portablity, and please report back to me with any results be they good or
  27.     bad. Suggestions are always welcome.
  28.  3) Only use this tool on a copy of a file -- do not use an original. This
  29.     is just common sense.
  30.  4) This source code or a compiled version may be bundled with commercial
  31.     software as long as the author is notified beforehand. The author's name
  32.     should also be mentioned in the credits.
  33.  5) Feel free to use any of the algorithms for your own work. Many of them are
  34.     being used in other tools I have written.
  35.  6) The most current version can be obtained by requesting a copy directly
  36.     from me.
  37.  
  38. DESCRIPTION:
  39.  1) Supports Shift-JIS, EUC, New-JIS, Old-JIS, and NEC-JIS codes.
  40.  2) Automatically detects infile's Japanese code.
  41.  3) The tool reads the infile, and will create an outfile which
  42.     contains all of the characters within the infile along with their
  43.     electronic codes. The user may choose octal, decimal, or hexadecimal
  44.     notation (the default, if none specified, is hexadecimal).
  45.  4) Supports half-width katakana in both Shift-JIS and EUC codes as input.
  46.  5) The outfile specifies the Shift-JIS, EUC, JIS, ASCII, and KUTEN values
  47.     for each character in the file. The default file extension is ".val" if
  48.     no outfile is specified.
  49.  
  50. FILE HANDLING:
  51.  1) Specifying the infile is optional as one can redirect stdin and stdout.
  52.  2) Specifying the outfile is also optional. If none is specified, the
  53.     tool will semi-intelligently change the file's name. The tool
  54.     simply scans the outfile name, finds the last period in it, terminates
  55.     the string at that point, and tacks on an extension. Here are some example
  56.     command lines, and the resulting outfile names:
  57.  
  58.     a) jcode sig.jpn                      = sig.val
  59.     b) jcode sig.jpn sig.out              = sig.out
  60.     c) jcode sig.jpn.txt                  = sig.jpn.val
  61.     d) jcode sig                          = sig.val
  62.  
  63.     This is very useful for MS-DOS users since a filename such as sig.jpn.val
  64.     will not result in converting a file called sig.jpn.
  65.  
  66.     Also note that if the outfile and infile have the same name, the tool
  67.     will not work, and data will be lost. I tried to build safe-guards against
  68.     this. For example, note how this tool will change the outfile name so
  69.     that it does not overwrite the infile:
  70.     
  71.     a) jcode sig.val                      = sig-.val
  72.     b) jcode sig.val sig.val              = sig-.val
  73.     c) jcode sig-.val                     = sig--.val
  74.     
  75.     If only the infile is given, a hyphen is inserted after the last period,
  76.     and the extension is then reattached. If the outfile is specified by the
  77.     user, then it will search for the last period (if any), attach a hyphen,
  78.     and finally attach the proper extension). This sort of protection is NOT
  79.     available from this tool if stdin/stdout are used.
  80.  3) If you want to specify an infile, but to have the output to go to stdout,
  81.     you have two options:
  82.  
  83.     a) jcode < sig.jpn                    <= redirect stdin for infile
  84.     b) jcode sig.jpn -                    <= specify infile, then use "-" to
  85.                                              indictate stdout for output
  86.  
  87.  4) When using pipes under UNIX, it is very important to use the "-iCODE"
  88.     option so that the automatic code detection routines are skipped. This
  89.     is because the tool attempts to use the rewind() function, and this
  90.     has no effect on some machines if input is coming from a pipe. Here
  91.     are some examples (they assume that the infile code is EUC):
  92.  
  93.     a) cat japan.txt | jcode -oj          <= does not work
  94.     a) cat japan.txt | jcode -ie -oj      <= works
  95. */
  96.  
  97. #ifdef THINK_C
  98. #include <console.h>
  99. #include <stdlib.h>
  100. #endif
  101. #include <stdio.h>
  102. #include <string.h>
  103. #include <ctype.h>
  104. #ifndef THINK_C
  105. #include <errno.h>
  106. #endif
  107.  
  108. #define INPUT        1
  109. #define OUTPUT       2
  110. #define NOTSET       0
  111. #define NEW          1
  112. #define OLD          2
  113. #define NEC          3
  114. #define EUC          4
  115. #define SJIS         5
  116. #define EUCORSJIS    6
  117. #define ASCII        7
  118. #define KUTEN        8
  119. #define JISORSJIS    9
  120. #define TRUE         1
  121. #define FALSE        0
  122. #define ESC          27
  123. #define SJS1         0
  124. #define SJS2         1
  125. #define EUC1         2
  126. #define EUC2         3
  127. #define JIS1         4
  128. #define JIS2         5
  129. #define KT1          6
  130. #define KT2          7
  131. #define OCT          8
  132. #define DEC          10
  133. #define HEX          16
  134. #define ASCII_ZERO   48
  135. #define KUTEN_OFFSET 32
  136. #define EUC_OFFSET   128
  137. #define PERIOD       '.'
  138. #define SJIS1(A)     ((A >= 129 && A <= 159) || (A >= 224 && A <= 239))
  139. #define SJIS2(A)     (A >= 64 && A <= 252)
  140. #define ISJIS(A)     (A >= 33 && A <= 126)
  141. #define ISKUTEN(A)   (A >= 1 && A <= 94)
  142. #define HANKATA(A)   (A >= 161 && A <= 223)
  143. #define ISEUC(A)     (A >= 161 && A <= 254)
  144. #define NOTEUC(A,B)  ((A >= 129 && A <= 159) && (B >= 64 && B <= 160))
  145. #define ISASCII(A)   (A >= 0 && A <= 127)
  146. #define VALID(X)     ((X >= '0' && X <= '9') || (X >= 'A' && X <= 'F'))
  147. #ifndef SEEK_CUR
  148. #define SEEK_CUR     1
  149. #endif
  150. /* The following 4 lines of code are used to establish the default output code
  151.  * when using the "-o[CODE]" option, and for the default notation when using
  152.  * the "-n[NOTATION]" option. They are self-explanatory, and easy to change.
  153.  */
  154. #define DEFAULT_O    SJIS     /* default output code for "-o[CODE]" option */
  155. #define DEFAULT_OKI  ""       /* default kanji-in code for "-o[CODE]" option */
  156. #define DEFAULT_OKO  ""       /* default kanji-out code for "-o[CODE]" option */
  157. #define DEFAULT_N    HEX      /* default notation for "-n[NOTATION]" option */
  158.  
  159. void printheader(FILE *out,int pad);
  160. void print1byte(FILE *out,int notation,int p1,int control,int pad);
  161. void print2byte(FILE *out,int outcode,int notation,int data[],char ki[],char ko[],int pad);
  162. void printhwkana(FILE *out,int outcode,int notation,int p1,int p2,int pad);
  163. void jis2sjis(int *p1,int *p2);
  164. void sjis2jis(int *p1,int *p2);
  165. void TreatCodes(FILE *in,FILE *out,int outcode,int notation,int pad,char ki[],char ko[]);
  166. void TreatEUC(FILE *in,FILE *out,int outcode,int notation,char ki[],char ko[],int control,int pad);
  167. void TreatJIS(FILE *in,FILE *out,int outcode,int notation,char ki[],char ko[],int control,int pad);
  168. void TreatSJIS(FILE *in,FILE *out,int outcode,int notation,char ki[],char ko[],int control,int pad);
  169. void TreatASCII(FILE *in,FILE *out,int notation,int control,int pad);
  170. void printcode(int code);
  171. void dohelp(char toolname[]);
  172. void TreatOneCode(char mydata[]);
  173. int toup(int data);
  174. int SkipESCSeq(FILE *in,int temp,int *intwobyte);
  175. int DetectCodeType(FILE *in);
  176. int getline(FILE *in,char *myarray);
  177. int getcode(int data,char ki[],char ko[],int doing);
  178. int getnotation(int data);
  179. int hex2dec(int data);
  180. int convert2code(int p1,int p2,int incode);
  181. int dopadding(int data);
  182. #ifdef THINK_C
  183. int ccommand(char ***p);
  184. #endif
  185.  
  186. void main(int argc,char **argv)
  187. {
  188.   FILE *in,*out;
  189. #ifndef THINK_C
  190.   int rc;
  191. #endif
  192.   int tempincode,incode,verbose = FALSE,makeoutfile = TRUE,doing = FALSE,control = FALSE;
  193.   int outcode = NOTSET,notation = DEFAULT_N,pad = TRUE,setincode = FALSE,readcodes = FALSE;
  194.   char infilename[100],outfilename[100],extension[10],ki[10],ko[10],toolname[100];
  195.  
  196. #ifdef THINK_C
  197.   argc = ccommand(&argv);
  198. #endif
  199.  
  200.   strcpy(toolname,*argv);
  201.   while (--argc > 0 && (*++argv)[0] == '-')
  202.     switch (toup(*++argv[0])) {
  203.       case 'C' :
  204.         readcodes = TRUE;
  205.         if (*++argv[0] != '\0') {
  206.           TreatOneCode(argv[0]);
  207.           exit(1);
  208.         }
  209.         break;
  210.       case 'H' :
  211.         dohelp(toolname);
  212.         break;
  213.       case 'I' :
  214.         setincode = TRUE;
  215.         doing = INPUT;
  216.         incode = getcode(toup(*++argv[0]),ki,ko,doing);
  217.         break;
  218.       case 'N' :
  219.         notation = getnotation(toup(*++argv[0]));
  220.         break;
  221.       case 'O' :
  222.         doing = OUTPUT;
  223.         outcode = getcode(toup(*++argv[0]),ki,ko,doing);
  224.         break;
  225.       case 'P' :
  226.         pad = dopadding(toup(*++argv[0]));
  227.         break;
  228.       case 'S' :
  229.         control = TRUE;
  230.         break;
  231.       case 'V' :
  232.         verbose = TRUE;
  233.         break;
  234.       default :
  235.         fprintf(stderr,"Illegal option \"-%c\"! Try using the \"-h\" option for help.\n",*argv[0]);
  236.         fprintf(stderr,"Usage: %s [-options] [infile] [outfile]\nExiting...\n",toolname);
  237.         exit(1);
  238.         break;
  239.     }
  240.   if (argc == 0) {
  241. #ifndef THINK_C
  242.     rc = lseek(0,0,SEEK_CUR);
  243.     if (rc == -1 && errno == ESPIPE && !setincode) {
  244.       fprintf(stderr,"Cannot automatically detect input code from a pipe!\n");
  245.       fprintf(stderr,"Try using the \"iCODE\" option.\nExiting...\n");
  246.       exit(1);
  247.     }
  248. #endif
  249.     in = stdin;
  250.     out = stdout;
  251.   }
  252.   else if (argc > 0) {
  253.     if (argc == 1) {
  254.       strcpy(extension,".val");
  255.       strcpy(infilename,*argv);
  256.       if (strchr(*argv,PERIOD) != NULL)
  257.         *strrchr(*argv,PERIOD) = '\0';
  258.       strcpy(outfilename,*argv);
  259.       strcat(outfilename,extension);
  260.       if (!strcmp(infilename,outfilename)) {
  261.         if (strchr(outfilename,PERIOD) != NULL)
  262.           *strrchr(outfilename,PERIOD) = '\0';
  263.         strcat(outfilename,"-");
  264.         strcat(outfilename,extension);
  265.       }
  266.       if (verbose)
  267.         fprintf(stderr,"Output file will be named %s\n",outfilename);
  268.     }
  269.     else if (argc > 1) {
  270.       strcpy(infilename,*argv++);
  271.       if (*argv[0] == '-') {
  272.         out = stdout;
  273.         makeoutfile = FALSE;
  274.       }
  275.       else {
  276.         strcpy(outfilename,*argv);
  277.         if (!strcmp(infilename,outfilename)) {
  278.           if (strchr(outfilename,PERIOD) != NULL)
  279.             *strrchr(outfilename,PERIOD) = '\0';
  280.           strcat(outfilename,"-");
  281.           strcat(outfilename,extension);
  282.         }
  283.       }
  284.     }
  285.     if ((in = fopen(infilename,"r")) == NULL) {
  286.       fprintf(stderr,"Cannot open %s! Exiting...\n",infilename);
  287.       exit(1);
  288.     }
  289.     if (makeoutfile)
  290.       if ((out = fopen(outfilename,"w")) == NULL) {
  291.         fprintf(stderr,"Cannot open %s! Exiting...\n",outfilename);
  292.         exit(1);
  293.       }
  294.   }
  295.   if (readcodes && control)
  296.     control = FALSE;
  297.   if (outcode == NOTSET) {
  298.     strcpy(ki,DEFAULT_OKI);
  299.     strcpy(ko,DEFAULT_OKO);
  300.     outcode = DEFAULT_O;
  301.   }
  302.   tempincode = incode;
  303.   if (setincode && verbose) {
  304.     fprintf(stderr,"User-selected input code: ");
  305.     printcode(incode);
  306.   }
  307.   if (verbose) {
  308.     fprintf(stderr,"User-selected output code: ");
  309.     printcode(outcode);
  310.     fprintf(stderr,"User-selected notation: ");
  311.     switch (notation) {
  312.       case OCT :
  313.         fprintf(stderr,"octal\n");
  314.         break;
  315.       case DEC :
  316.         fprintf(stderr,"decimal\n");
  317.         break;
  318.       case HEX :
  319.         fprintf(stderr,"hexadecimal\n");
  320.         break;
  321.     }
  322.   }
  323.   if ((setincode && verbose) || readcodes)
  324.     ;
  325.   else if (!setincode || verbose) {
  326.     incode = DetectCodeType(in);
  327.     if (verbose) {
  328.       fprintf(stderr,"Detected input code: ");
  329.       printcode(incode);
  330.     }
  331.     rewind(in);
  332.   }
  333.   if (setincode)
  334.     incode = tempincode;
  335.   if ((incode != NOTSET && incode != EUCORSJIS) || readcodes)
  336.     printheader(out,pad);
  337.   if (readcodes)
  338.     TreatCodes(in,out,outcode,notation,pad,ki,ko);
  339.   switch (incode) {
  340.     case NOTSET :
  341.       fprintf(stderr,"Unknown input code! Exiting...\n");
  342.       exit(1);
  343.       break;
  344.     case EUCORSJIS :
  345.       fprintf(stderr,"Ambiguous (Shift-JIS or EUC) input code!\n");
  346.       fprintf(stderr,"Try using the \"-iCODE\" option to specify either Shift-JIS or EUC.\n");
  347.       fprintf(stderr,"Exiting...\n");
  348.       exit(1);
  349.       break;
  350.     case NEW :
  351.     case OLD :
  352.     case NEC :
  353.       TreatJIS(in,out,outcode,notation,ki,ko,control,pad);
  354.       break;
  355.     case EUC :
  356.       TreatEUC(in,out,outcode,notation,ki,ko,control,pad);
  357.       break;
  358.     case SJIS :
  359.       TreatSJIS(in,out,outcode,notation,ki,ko,control,pad);
  360.       break;
  361.     case ASCII :
  362.       TreatASCII(in,out,notation,control,pad);
  363.       break;
  364.   }
  365.   exit(0);
  366. }
  367.  
  368. int toup(int data)
  369. {
  370.   if (islower(data))
  371.     return (toupper(data));
  372.   else
  373.     return data;
  374. }
  375.  
  376. int dopadding(int data)
  377. {
  378.   if (data == 'T')
  379.     return FALSE;
  380.   else
  381.     return TRUE;
  382. }
  383.  
  384. void printcode(int code)
  385. {
  386.   switch (code) {
  387.     case OLD :
  388.       fprintf(stderr,"Old-JIS\n");
  389.       break;
  390.     case NEW :
  391.       fprintf(stderr,"New-JIS\n");
  392.       break;
  393.     case NEC :
  394.       fprintf(stderr,"NEC-JIS\n");
  395.       break;
  396.     case EUC :
  397.       fprintf(stderr,"EUC\n");
  398.       break;
  399.     case SJIS :
  400.       fprintf(stderr,"Shift-JIS\n");
  401.       break;
  402.     case EUCORSJIS :
  403.       fprintf(stderr,"ambiguous (Shift-JIS or EUC)\n");
  404.       break;
  405.     case ASCII :
  406.       fprintf(stderr,"ASCII (no Japanese)\n");
  407.       break;
  408.     case NOTSET :
  409.       fprintf(stderr,"unknown\n");
  410.       break;
  411.     default :
  412.       break;
  413.   }
  414. }
  415.  
  416. void dohelp(char toolname[])
  417. {
  418.   printf("** %s v3.0 (July 1, 1993) **\n\n",toolname);
  419.   printf("Written by Ken R. Lunde, Adobe Systems Incorporated\nlunde@mv.us.adobe.com\n\n");
  420.   printf("Usage: %s [-options] [infile] [outfile]\n\n",toolname);
  421.   printf("Tool description: This tool is a utility for displaying the electronic values\n");
  422.   printf("of Japanese characters within textfiles, and supports Shift-JIS, EUC, New-JIS,\n");
  423.   printf("Old-JIS, and NEC-JIS for both input and output.\n\n");
  424.   printf("Options include:\n\n");
  425.   printf("  -c[DATA]      Reads codes, one per line, rather than characters as input --\n");
  426.   printf("                if DATA is specified, only that code is treated, then exits\n");
  427.   printf("                (KUTEN codes must be prefixed with \"k,\" and EUC codes with\n");
  428.   printf("                \"x\" -- EUC, JIS, and Shift-JIS codes must be hexadecimal)\n");
  429.   printf("  -h            Displays this help page, then exits\n");
  430.   printf("  -iCODE        Forces input code to be recognized as CODE\n");
  431.   printf("  -n[NOTATION]  Output notation set to NOTATION (default is hexadecimal if this\n");
  432.   printf("                option is not specified, if NOTATION is not specified, or if\n");
  433.   printf("                the specified NOTATION is invalid)\n");
  434.   printf("  -o[CODE]      Output code set to CODE (default is Shift-JIS if this option\n");
  435.   printf("                is not specified, if CODE is not specified, or if the\n");
  436.   printf("                specified CODE is invalid)\n");
  437.   printf("  -p[CHOICE]    Pads the columns with CHOICE whereby CHOICE can be either \"t\"\n");
  438.   printf("                for tabs or \"s\" for spaces (default is spaces if this option\n");
  439.   printf("                is not specified, if CHOICE is not specified, or if the\n");
  440.   printf("                specified CHOICE is invalid)\n");
  441.   printf("  -s            Shows control characters (except escape sequences)\n");
  442.   printf("  -v            Verbose mode -- displays information such as automatically\n");
  443.   printf("                generated file names, detected input code, etc.\n\n");
  444.   printf("NOTE: CODE has five possible values:\n");
  445.   printf("      \"e\" = EUC; \"s\" = Shift-JIS; \"j\" = New-JIS; \"o\" = Old-JIS;\n");
  446.   printf("      and \"n\" = NEC-JIS\n\n");
  447.   printf("NOTE: NOTATION has three possible values:\n");
  448.   printf("      \"o\" = octal; \"d\" = decimal; and \"h\" = hexadecimal\n\n");
  449.   exit(0);
  450. }
  451.  
  452. int getnotation(int data)
  453. {
  454.   if (data == 'D')
  455.     return DEC;
  456.   else if (data == 'O')
  457.     return OCT;
  458.   else if (data == 'H')
  459.     return HEX;
  460.   else
  461.     return DEFAULT_N;
  462. }
  463.  
  464. int getcode(int data,char ki[],char ko[],int doing)
  465. {
  466.   if (data == 'E')
  467.     return EUC;
  468.   else if (data == 'S')
  469.     return SJIS;
  470.   else if (data == 'J') {
  471.     if (doing == OUTPUT) {
  472.       strcpy(ki,"\033$B");
  473.       strcpy(ko,"\033(J");
  474.     }
  475.     return NEW;
  476.   }
  477.   else if (data == 'O') {
  478.     if (doing == OUTPUT) {
  479.       strcpy(ki,"\033$@");
  480.       strcpy(ko,"\033(J");
  481.     }
  482.     return OLD;
  483.   }
  484.   else if (data == 'N') {
  485.     if (doing == OUTPUT) {
  486.       strcpy(ki,"\033K");
  487.       strcpy(ko,"\033H");
  488.     }
  489.     return NEC;
  490.   }
  491.   else {
  492.     if (doing == INPUT) {
  493.       fprintf(stderr,"Missing or invalid user-selected input code! Exiting...\n");
  494.       exit(1);
  495.     }
  496.     else if (doing == OUTPUT) {
  497.       strcpy(ki,DEFAULT_OKI);
  498.       strcpy(ko,DEFAULT_OKO);
  499.       return DEFAULT_O;
  500.     }
  501.   }
  502. }
  503.  
  504. int DetectCodeType(FILE *in)
  505. {
  506.   int c = 0,whatcode = ASCII;
  507.  
  508.   while ((whatcode == EUCORSJIS || whatcode == ASCII) && c != EOF) {
  509.     if ((c = fgetc(in)) != EOF) {
  510.       if (c == ESC) {
  511.         c = fgetc(in);
  512.         if (c == '$') {
  513.           c = fgetc(in);
  514.           if (c == 'B')
  515.             whatcode = NEW;
  516.           else if (c == '@')
  517.             whatcode = OLD;
  518.         }
  519.         else if (c == 'K')
  520.           whatcode = NEC;
  521.       }
  522.       else if ((c >= 129 && c <= 141) || (c >= 143 && c <= 159))
  523.         whatcode = SJIS;
  524.       else if (c == 142) {
  525.         c = fgetc(in);
  526.         if ((c >= 64 && c <= 126) || (c >= 128 && c <= 160) || (c >= 224 && c <= 252))
  527.           whatcode = SJIS;
  528.         else if (c >= 161 && c <= 223)
  529.           whatcode = EUCORSJIS;
  530.       }
  531.       else if (c >= 161 && c <= 223) {
  532.         c = fgetc(in);
  533.         if (c >= 240 && c <= 254)
  534.           whatcode = EUC;
  535.         else if (c >= 161 && c <= 223)
  536.           whatcode = EUCORSJIS;
  537.         else if (c >= 224 && c <= 239) {
  538.           whatcode = EUCORSJIS;
  539.           while (c >= 64 && c != EOF && whatcode == EUCORSJIS) {
  540.             if (c >= 129) {
  541.               if (c <= 141 || (c >= 143 && c <= 159))
  542.                 whatcode = SJIS;
  543.               else if (c >= 253 && c <= 254)
  544.                 whatcode = EUC;
  545.             }
  546.             c = fgetc(in);
  547.           }
  548.         }
  549.         else if (c <= 159)
  550.           whatcode = SJIS;
  551.       }
  552.       else if (c >= 240 && c <= 254)
  553.         whatcode = EUC;
  554.       else if (c >= 224 && c <= 239) {
  555.         c = fgetc(in);
  556.         if ((c >= 64 && c <= 126) || (c >= 128 && c <= 160))
  557.           whatcode = SJIS;
  558.         else if (c >= 253 && c <= 254)
  559.           whatcode = EUC;
  560.         else if (c >= 161 && c <= 252)
  561.           whatcode = EUCORSJIS;
  562.       }
  563.     }
  564.   }
  565.   return whatcode;
  566. }
  567.  
  568. void printheader(FILE *out,int pad)
  569. {
  570.   if (pad)
  571.     fprintf(out,"Character  Shift-JIS  EUC      JIS      ASCII  KUTEN\n");
  572.   else
  573.     fprintf(out,"Character\tShift-JIS\tEUC\tJIS\tASCII\tKUTEN\n");
  574. }
  575.  
  576. void printhwkana(FILE *out,int outcode,int notation,int p1,int p2,int pad)
  577. {
  578.   if (!pad) {
  579.     if (outcode == EUC)
  580.       fprintf(out,"%c%c\t",p1,p2);
  581.     else
  582.       fprintf(out,"%c\t",p2);
  583.     switch (notation) {
  584.       case OCT :
  585.         fprintf(out,"%03o\t%03o-%03o\t%03o\n",p2,p1,p2,p2 - 128);
  586.         break;
  587.       case DEC :
  588.         fprintf(out,"%03d\t%03d-%03d\t%03d\n",p2,p1,p2,p2 - 128);
  589.         break;
  590.       case HEX :
  591.         fprintf(out,"%02X\t%02X-%02X\t%02X\n",p2,p1,p2,p2 - 128);
  592.         break;
  593.     }
  594.   }
  595.   else {
  596.     if (outcode == EUC)
  597.       fprintf(out,"%c%c          ",p1,p2);
  598.     else
  599.       fprintf(out,"%c          ",p2);
  600.     switch (notation) {
  601.       case OCT :
  602.         fprintf(out,"%03o        %03o-%03o  %03o\n",p2,p1,p2,p2 - 128);
  603.         break;
  604.       case DEC :
  605.         fprintf(out,"%03d        %03d-%03d  %03d\n",p2,p1,p2,p2 - 128);
  606.         break;
  607.       case HEX :
  608.         fprintf(out,"%02X         %02X-%02X    %02X\n",p2,p1,p2,p2 - 128);
  609.         break;
  610.     }
  611.   }
  612. }
  613.  
  614. void print1byte(FILE *out,int notation,int p1,int control,int pad)
  615. {
  616.   static char *controlchar[] = {
  617.   "<NUL>","<SOH>","<STX>","<ETX>","<EOT>","<ENQ>","<ACK>","<BEL>","<BS> ","<HT> ",
  618.   "<LF> ","<VT> ","<FF> ","<CR> ","<SO> ","<SI> ","<DLE>","<DC1>","<DC2>","<DC3>",
  619.   "<DC4>","<NAK>","<SYN>","<ETB>","<CAN>","<EM> ","<SUB>","<ESC>","<FS> ","<GS> ",
  620.   "<RS> ","<US> ","<SP> " };
  621.  
  622.   if (control) {
  623.     if (p1 >= 0 && p1 <= 32) {
  624.       fprintf(out,"%s",controlchar[p1]);
  625.       if (pad)
  626.         fprintf(out,"      ");
  627.       else
  628.         fprintf(out,"\t");
  629.     }
  630.     else if (p1 == 127) {
  631.       fprintf(out,"<DEL>");
  632.       if (pad)
  633.         fprintf(out,"      ");
  634.       else
  635.         fprintf(out,"\t");
  636.     }
  637.     else {
  638.       fprintf(out,"%c",p1);
  639.       if (pad)
  640.         fprintf(out,"          ");
  641.       else
  642.         fprintf(out,"\t");
  643.     }
  644.  
  645.  
  646.     switch (notation) {
  647.       case OCT :
  648.         fprintf(out,"%03o\n",p1);
  649.         break;
  650.       case DEC :
  651.         fprintf(out,"%03d\n",p1);
  652.         break;
  653.       case HEX :
  654.         fprintf(out,"%02X\n",p1);
  655.         break;
  656.     }
  657.   }
  658.   else if (!control && p1 >= 33 && p1 <= 126) {
  659.     fprintf(out,"%c",p1);
  660.     if (pad)
  661.       fprintf(out,"          ");
  662.     else
  663.       fprintf(out,"\t");
  664.     switch (notation) {
  665.       case OCT :
  666.         fprintf(out,"%03o\n",p1);
  667.         break;
  668.       case DEC :
  669.         fprintf(out,"%03d\n",p1);
  670.         break;
  671.       case HEX :
  672.         fprintf(out,"%02X\n",p1);
  673.         break;
  674.     }
  675.   }
  676. }
  677.  
  678. void print2byte(FILE *out,int outcode,int notation,int data[],char ki[],char ko[],int pad)
  679. {
  680.   switch (outcode) {
  681.     case NEW :
  682.     case OLD :
  683.     case NEC :
  684.       fprintf(out,"%s%c%c%s",ki,data[JIS1],data[JIS2],ko);
  685.       break;
  686.     case EUC :
  687.       fprintf(out,"%c%c",data[EUC1],data[EUC2]);
  688.       break;
  689.     case SJIS :
  690.       fprintf(out,"%c%c",data[SJS1],data[SJS2]);
  691.       break;
  692.     default :
  693.       break;
  694.   }
  695.   if (!pad) {
  696.     fprintf(out,"\t");
  697.     switch (notation) {
  698.       case OCT :
  699.         fprintf(out,"%03o-%03o\t",data[SJS1],data[SJS2]);
  700.         fprintf(out,"%03o-%03o\t",data[EUC1],data[EUC2]);
  701.         fprintf(out,"%03o-%03o\t",data[JIS1],data[JIS2]);
  702.         break;
  703.       case DEC :
  704.         fprintf(out,"%03d-%03d\t",data[SJS1],data[SJS2]);
  705.         fprintf(out,"%03d-%03d\t",data[EUC1],data[EUC2]);
  706.         fprintf(out,"%03d-%03d\t",data[JIS1],data[JIS2]);
  707.         break;
  708.       case HEX :
  709.         fprintf(out,"%02X-%02X\t",data[SJS1],data[SJS2]);
  710.         fprintf(out,"%02X-%02X\t",data[EUC1],data[EUC2]);
  711.         fprintf(out,"%02X-%02X\t",data[JIS1],data[JIS2]);
  712.         break;
  713.     }
  714.     fprintf(out,"%c%c\t",data[JIS1],data[JIS2]);
  715.     fprintf(out,"%02d-%02d\n",data[KT1],data[KT2]);
  716.   }
  717.   else {
  718.     fprintf(out,"         ");
  719.     switch (notation) {
  720.       case OCT :
  721.         fprintf(out,"%03o-%03o    ",data[SJS1],data[SJS2]);
  722.         fprintf(out,"%03o-%03o  ",data[EUC1],data[EUC2]);
  723.         fprintf(out,"%03o-%03o  ",data[JIS1],data[JIS2]);
  724.         break;
  725.       case DEC :
  726.         fprintf(out,"%03d-%03d    ",data[SJS1],data[SJS2]);
  727.         fprintf(out,"%03d-%03d  ",data[EUC1],data[EUC2]);
  728.         fprintf(out,"%03d-%03d  ",data[JIS1],data[JIS2]);
  729.         break;
  730.       case HEX :
  731.         fprintf(out,"%02X-%02X      ",data[SJS1],data[SJS2]);
  732.         fprintf(out,"%02X-%02X    ",data[EUC1],data[EUC2]);
  733.         fprintf(out,"%02X-%02X    ",data[JIS1],data[JIS2]);
  734.         break;
  735.     }
  736.     fprintf(out,"%c%c     ",data[JIS1],data[JIS2]);
  737.     fprintf(out,"%02d-%02d\n",data[KT1],data[KT2]);
  738.   }
  739. }
  740.  
  741. void sjis2jis(int *p1, int *p2)
  742. {
  743.   unsigned char c1 = *p1;
  744.   unsigned char c2 = *p2;
  745.   int adjust = c2 < 159;
  746.   int rowOffset = c1 < 160 ? 112 : 176;
  747.   int cellOffset = adjust ? (c2 > 127 ? 32 : 31) : 126;
  748.  
  749.   *p1 = ((c1 - rowOffset) << 1) - adjust;
  750.   *p2 -= cellOffset;
  751. }
  752.  
  753. void jis2sjis(int *p1, int *p2)
  754. {
  755.   unsigned char c1 = *p1;
  756.   unsigned char c2 = *p2;
  757.   int rowOffset = c1 < 95 ? 112 : 176;
  758.   int cellOffset = c1 % 2 ? (c2 > 95 ? 32 : 31) : 126;
  759.  
  760.   *p1 = ((c1 + 1) >> 1) + rowOffset;
  761.   *p2 += cellOffset;
  762. }
  763.  
  764. int SkipESCSeq(FILE *in,int temp,int *intwobyte)
  765. {
  766.   int tempdata = *intwobyte;
  767.  
  768.   if (temp == '$' || temp == '(')
  769.     fgetc(in);
  770.   if (temp == 'K' || temp == '$')
  771.     *intwobyte = TRUE;
  772.   else
  773.     *intwobyte = FALSE;
  774.   if (tempdata == *intwobyte)
  775.     return FALSE;
  776.   else
  777.     return TRUE;
  778. }
  779.  
  780. void TreatEUC(FILE *in,FILE *out,int outcode,int notation,char ki[],char ko[],int control,int pad)
  781. {
  782.   int p1,p2;
  783.   int data[8];
  784.  
  785.   while ((p1 = fgetc(in)) != EOF) {
  786.     if ISEUC(p1) {
  787.       p2 = fgetc(in);
  788.       if ISEUC(p2) {
  789.         data[SJS1] = data[EUC1] = data[JIS1] = data[KT1] = p1;
  790.         data[SJS2] = data[EUC2] = data[JIS2] = data[KT2] = p2;
  791.         data[SJS1] -= EUC_OFFSET;
  792.         data[SJS2] -= EUC_OFFSET;
  793.         jis2sjis(&data[SJS1],&data[SJS2]);
  794.         data[JIS1] -= EUC_OFFSET;
  795.         data[JIS2] -= EUC_OFFSET;
  796.         data[KT1] -= 160;
  797.         data[KT2] -= 160;
  798.         print2byte(out,outcode,notation,data,ki,ko,pad);
  799.       }
  800.       else {
  801.         print1byte(out,notation,p1,control,pad);
  802.         print1byte(out,notation,p2,control,pad);
  803.       }
  804.     }
  805.     else if ISASCII(p1)
  806.       print1byte(out,notation,p1,control,pad);
  807.     else if (p1 == 142) {
  808.       p2 = fgetc(in);
  809.       printhwkana(out,outcode,notation,p1,p2,pad);
  810.     }
  811.   }
  812. }
  813.  
  814. void TreatJIS(FILE *in,FILE *out,int outcode,int notation,char ki[],char ko[],int control,int pad)
  815. {
  816.   int intwobyte = FALSE,temp,p1,p2;
  817.   int data[8];
  818.  
  819.   while ((p1 = fgetc(in)) != EOF) {
  820.     if (p1 == ESC) {
  821.       temp = fgetc(in);
  822.       SkipESCSeq(in,temp,&intwobyte);
  823.       if ((p1 = fgetc(in)) == EOF)
  824.         exit(1);
  825.     }
  826.     if (intwobyte) {
  827.       p2 = fgetc(in);
  828.       data[SJS1] = data[EUC1] = data[JIS1] = data[KT1] = p1;
  829.       data[SJS2] = data[EUC2] = data[JIS2] = data[KT2] = p2;
  830.       jis2sjis(&data[SJS1],&data[SJS2]);
  831.       data[EUC1] += EUC_OFFSET;
  832.       data[EUC2] += EUC_OFFSET;
  833.       data[KT1] -= KUTEN_OFFSET;
  834.       data[KT2] -= KUTEN_OFFSET;
  835.       print2byte(out,outcode,notation,data,ki,ko,pad);
  836.     }
  837.     else if (!intwobyte && ISASCII(p1))
  838.       print1byte(out,notation,p1,control,pad);
  839.   }
  840. }
  841.  
  842. void TreatSJIS(FILE *in,FILE *out,int outcode,int notation,char ki[],char ko[],int control,int pad)
  843. {
  844.   int p1,p2;
  845.   int data[8];
  846.  
  847.   while ((p1 = fgetc(in)) != EOF) {
  848.     if SJIS1(p1) {
  849.       p2 = fgetc(in);
  850.       if SJIS2(p2) {
  851.         data[SJS1] = data[EUC1] = data[JIS1] = data[KT1] = p1;
  852.         data[SJS2] = data[EUC2] = data[JIS2] = data[KT2] = p2;
  853.         sjis2jis(&data[EUC1],&data[EUC2]);
  854.         data[EUC1] += EUC_OFFSET;
  855.         data[EUC2] += EUC_OFFSET;
  856.         sjis2jis(&data[JIS1],&data[JIS2]);
  857.         sjis2jis(&data[KT1],&data[KT2]);
  858.         data[KT1] -= KUTEN_OFFSET;
  859.         data[KT2] -= KUTEN_OFFSET;
  860.         print2byte(out,outcode,notation,data,ki,ko,pad);
  861.       }
  862.       else {
  863.         print1byte(out,notation,p1,control,pad);
  864.         print1byte(out,notation,p2,control,pad);
  865.       }
  866.     }
  867.     else if ISASCII(p1)
  868.       print1byte(out,notation,p1,control,pad);
  869.     else if HANKATA(p1)
  870.       printhwkana(out,outcode,notation,142,p1,pad);
  871.   }
  872. }
  873.  
  874. void TreatASCII(FILE *in,FILE *out,int notation,int control,int pad)
  875. {
  876.   int p1;
  877.  
  878.   while ((p1 = fgetc(in)) != EOF)
  879.     if ISASCII(p1)
  880.       print1byte(out,notation,p1,control,pad);
  881. }
  882.  
  883. int getline(FILE *in,char *myarray)
  884. {
  885.   if (fgets(myarray,100,in) == NULL)
  886.     return 0;
  887.   else
  888.     return 1;
  889. }
  890.  
  891. int hex2dec(int data)
  892. {
  893.   if (data >= '0' && data <= '9')
  894.     return (data - ASCII_ZERO);
  895.   else if (data >= 'A' && data <= 'F')
  896.     return (data - 55);
  897. }
  898.  
  899. int convert2code(int p1,int p2,int incode)
  900. {
  901.   if (incode == KUTEN)
  902.     return (((p1 - ASCII_ZERO) * 10) + (p2 - ASCII_ZERO));
  903.   else
  904.     return ((hex2dec(p1) * 16) + hex2dec(p2));
  905. }
  906.  
  907. void TreatCodes(FILE *in,FILE *out,int outcode,int notation,int pad,char ki[],char ko[])
  908. {
  909.   int y,p1,p2,incode,offset,okay;
  910.   int data[8];
  911.   char myarray[100],temparray[10];
  912.  
  913.   while (getline(in,myarray)) {
  914.     okay = TRUE;
  915.     offset = 0;
  916.     switch (toup(myarray[0])) {
  917.       case 'K' :
  918.         incode = KUTEN;
  919.         offset = 1;
  920.         break;
  921.       case 'X' :
  922.         incode = EUC;
  923.         offset = 1;
  924.         break;
  925.       default :
  926.         incode = JISORSJIS;
  927.         break;
  928.     }
  929.     for (y = 0;y < 4;y++) {
  930.       if VALID(toup(myarray[y + offset]))
  931.         temparray[y] = toup(myarray[y + offset]);
  932.       else {
  933.         fprintf(stderr,"Invalid character code! Skipping...\n");
  934.         okay = FALSE;
  935.         incode = NOTSET;
  936.         break;
  937.       }
  938.     }
  939.     if (okay) {
  940.       p1 = convert2code(temparray[0],temparray[1],incode);
  941.       p2 = convert2code(temparray[2],temparray[3],incode);
  942.       if (incode == JISORSJIS && ISJIS(p1) && ISJIS(p2))
  943.         ;
  944.       else if (incode == JISORSJIS && SJIS1(p1) && SJIS2(p2))
  945.         sjis2jis(&p1,&p2);
  946.       else if (incode == EUC && ISEUC(p1) && ISEUC(p2)) {
  947.         p1 -= EUC_OFFSET;
  948.         p2 -= EUC_OFFSET;
  949.       }
  950.       else if (incode == KUTEN && ISKUTEN(p1) && ISKUTEN(p2)) {
  951.         p1 += KUTEN_OFFSET;
  952.         p2 += KUTEN_OFFSET;
  953.       }
  954.       else {
  955.         fprintf(stderr,"Invalid character code! Skipping...\n");
  956.         okay = FALSE;
  957.       }
  958.     }
  959.     if (okay) {
  960.       data[SJS1] = data[EUC1] = data[JIS1] = data[KT1] = p1;
  961.       data[SJS2] = data[EUC2] = data[JIS2] = data[KT2] = p2;
  962.       jis2sjis(&data[SJS1],&data[SJS2]);
  963.       data[EUC1] += EUC_OFFSET;
  964.       data[EUC2] += EUC_OFFSET;
  965.       data[KT1] -= KUTEN_OFFSET;
  966.       data[KT2] -= KUTEN_OFFSET;
  967.       print2byte(out,outcode,notation,data,ki,ko,pad);
  968.     }
  969.   }
  970. }
  971.  
  972. void TreatOneCode(char mydata[])
  973. {
  974.   int y,p1,p2,incode,offset = 0,okay = TRUE;
  975.   int data[8];
  976.   char temparray[10];
  977.  
  978.   switch (toup(mydata[0])) {
  979.     case 'K' :
  980.       incode = KUTEN;
  981.       offset = 1;
  982.       break;
  983.     case 'X' :
  984.       incode = EUC;
  985.       offset = 1;
  986.       break;
  987.     default :
  988.       incode = JISORSJIS;
  989.       break;
  990.   }
  991.   for (y = 0;y < 4;y++) {
  992.     if VALID(toup(mydata[y + offset]))
  993.       temparray[y] = toup(mydata[y + offset]);
  994.     else {
  995.       fprintf(stderr,"Invalid character code! Exiting...\n");
  996.       exit(1);
  997.     }
  998.   }
  999.   if (okay) {
  1000.     p1 = convert2code(temparray[0],temparray[1],incode);
  1001.     p2 = convert2code(temparray[2],temparray[3],incode);
  1002.     if (incode == JISORSJIS && ISJIS(p1) && ISJIS(p2))
  1003.       fprintf(stderr,"NOTE: Input code was detected as JIS\n\n");
  1004.     else if (incode == JISORSJIS && SJIS1(p1) && SJIS2(p2)) {
  1005.       fprintf(stderr,"NOTE: Input code was detected as Shift-JIS\n\n");
  1006.       sjis2jis(&p1,&p2);
  1007.     }
  1008.     else if (incode == EUC && ISEUC(p1) && ISEUC(p2)) {
  1009.       fprintf(stderr,"NOTE: Input code was detected as EUC\n\n");
  1010.       p1 -= EUC_OFFSET;
  1011.       p2 -= EUC_OFFSET;
  1012.     }
  1013.     else if (incode == KUTEN && ISKUTEN(p1) && ISKUTEN(p2)) {
  1014.       fprintf(stderr,"NOTE: Input code was detected as KUTEN\n\n");
  1015.       p1 += KUTEN_OFFSET;
  1016.       p2 += KUTEN_OFFSET;
  1017.     }
  1018.     else {
  1019.       fprintf(stderr,"Invalid character code! Exiting...\n");
  1020.       exit(1);
  1021.     }
  1022.   }
  1023.   if (okay) {
  1024.     data[SJS1] = data[EUC1] = data[JIS1] = data[KT1] = p1;
  1025.     data[SJS2] = data[EUC2] = data[JIS2] = data[KT2] = p2;
  1026.     jis2sjis(&data[SJS1],&data[SJS2]);
  1027.     data[EUC1] += EUC_OFFSET;
  1028.     data[EUC2] += EUC_OFFSET;
  1029.     data[KT1] -= KUTEN_OFFSET;
  1030.     data[KT2] -= KUTEN_OFFSET;
  1031.     fprintf(stderr,"Shift-JIS:  %02X-%02X\n",data[SJS1],data[SJS2]);
  1032.     fprintf(stderr,"EUC:        %02X-%02X\n",data[EUC1],data[EUC2]);
  1033.     fprintf(stderr,"JIS:        %02X-%02X\n",data[JIS1],data[JIS2]);
  1034.     fprintf(stderr,"ASCII       %c%c\n",data[JIS1],data[JIS2]);
  1035.     fprintf(stderr,"KUTEN:      %02d-%02d\n",data[KT1],data[KT2]);
  1036.   }
  1037. }
  1038.