home *** CD-ROM | disk | FTP | other *** search
/ Internet 1996 World Exposition / park.org.s3.amazonaws.com.7z / park.org.s3.amazonaws.com / cgi-bin / Japan / Theme / jcode.pl < prev    next >
Perl Script  |  2017-09-21  |  6KB  |  263 lines

  1. package jcode;
  2. ;######################################################################
  3. ;#
  4. ;# jcode.pl: Japanese character code conversion library
  5. ;#
  6. ;# Copyright (c) 1991,1992 Software Research Associates, Inc.
  7. ;#    Original by srekcah@sra.co.jp, Feb 1992
  8. ;#
  9. ;#    Maintained by Kazumasa Utashiro <utashiro@sra.co.jp>
  10. ;#    Software Research Associates, Inc., Japan
  11. ;#
  12. ;; $rcsid = q$Id: jcode.pl,v 1.8 1993/06/23 02:17:41 utashiro Exp $;
  13. ;#
  14. ;######################################################################
  15. ;#
  16. ;# INTERFACE:
  17. ;#
  18. ;#    &jcode'getcode(*line)
  19. ;#        Return 'jis', 'sjis', 'euc' or undef according to
  20. ;#        Japanese character code in $line.
  21. ;#
  22. ;#    &jcode'convert(*line, $ocode [, $icode])
  23. ;#        Convert the line in any Japanese code to specified
  24. ;#        code in second argument $ocode.  $ocode is one of
  25. ;#        'jis', 'sjis' or 'euc'.  Input code is recognized
  26. ;#        automatically from the line itself when $icode is not
  27. ;#        supplied.  $icode also can be specified, but xxx2yyy
  28. ;#        routine is more efficient when both codes are known.
  29. ;#
  30. ;#        It returns a list of pointer of convert subroutine and
  31. ;#        input code.  It means that this routine returns the
  32. ;#        input code of the line in scalar context.
  33. ;#
  34. ;#    &jcode'xxx2yyy(*line)
  35. ;#        Convert Japanese code from xxx to yyy.  xxx and yyy
  36. ;#        are one of "jis", "sjis" or "euc".  These subroutines
  37. ;#        return number of converted substrings.  So return
  38. ;#        value 0 means the line was not converted at all.
  39. ;#
  40. ;#    &jcode'jis_inout($in, $out)
  41. ;#        Set or inquire JIS start and end sequences.  Default
  42. ;#        is "ESC-$-B" and "ESC-(-B".  If you supplied only one
  43. ;#        character, "ESC-$" or "ESC-(" is added as a prefix
  44. ;#        for each character respectively.  Acutually "ESC-(-B"
  45. ;#        is not a sequence to end JIS code but a sequence to
  46. ;#        start ASCII code set.  So `in' and `out' are somewhat
  47. ;#        misleading.
  48. ;#
  49. ;#    &jcode'get_inout($string)
  50. ;#        Get JIS start and end sequences from $string.
  51. ;#
  52. ;#    $jcode'convf{'xxx', 'yyy'}
  53. ;#        The value of this associative array is pointer to the
  54. ;#        subroutine jcode'xxx2yyy().
  55. ;#
  56. ;######################################################################
  57. ;#
  58. ;# SAMPLES
  59. ;#
  60. ;# Convert any Kanji code to JIS and print each line with code name.
  61. ;#
  62. ;#    while (<>) {
  63. ;#        $code = &jcode'convert(*_, 'jis');
  64. ;#        print $code, "\t", $_;
  65. ;#    }
  66. ;#    
  67. ;# Convert all lines to JIS according to the first recognized line.
  68. ;#
  69. ;#    while (<>) {
  70. ;#        print, next unless /[\033\200-\377]/;
  71. ;#        (*f, $icode) = &jcode'convert(*_, 'jis');
  72. ;#        print;
  73. ;#        defined(&f) || next;
  74. ;#        while (<>) { &f(*_); print; }
  75. ;#        last;
  76. ;#    }
  77. ;#
  78. ;# The safest way for converting to JIS
  79. ;#
  80. ;#    while (<>) {
  81. ;#        ($matched, $code) = &jcode'getcode(*_);
  82. ;#        print, next unless (@buf || $matched);
  83. ;#        push(@readahead, $_);
  84. ;#        next unless $code;
  85. ;#        eval "&jcode'${code}2jis(*_), print while (\$_ = shift(\@buf));";
  86. ;#        eval "&jcode'${code}2jis(*_), print while (\$_ = <>);";
  87. ;#        last;
  88. ;#    }
  89. ;#        
  90. ;######################################################################
  91.  
  92. ($version) = ($rcsid =~ /,v ([\d.]+)/);
  93. $re_sjis_c = '[\201-\237\340-\374][\100-\176\200-\374]';
  94. $re_sjis_s = "($re_sjis_c)+";
  95. $re_euc_c  = '[\241-\376][\241-\376]';
  96. $re_euc_s  = "($re_euc_c)+";
  97. $re_jin    = '\033\$[\@B]';
  98. $re_jout   = '\033\([BJ]';
  99. &jis_inout("\033\$B", "\033(B");
  100.  
  101. for $from ('jis', 'sjis', 'euc') {
  102.     for $to ('jis', 'sjis', 'euc') {
  103.     eval "\$convf{$from, $to} = *${from}2${to};";
  104.     }
  105. }
  106.  
  107. ;#
  108. ;# Set JIS in and out final characters.
  109. ;#
  110. sub jis_inout {
  111.     $jin = shift || $jin;
  112.     $jout = shift || $jout;
  113.     $jin = "\033\$".$jin if length($jin) == 1;
  114.     $jout = "\033\(".$jout if length($jout) == 1;
  115.     ($jin, $jout);
  116. }
  117.  
  118. ;#
  119. ;# Get JIS in and out sequences from the string.
  120. ;#
  121. sub get_inout {
  122.     local($jin, $jout);
  123.     $_[$[] =~ /$re_jin/o && ($jin = $&);
  124.     $_[$[] =~ /$re_jout/o && ($jout = $&);
  125.     ($jin, $jout);
  126. }
  127.  
  128. ;#
  129. ;# Character code recognition
  130. ;#
  131. sub getcode {
  132.     local(*_) = @_;
  133.     return undef unless /[\033\200-\377]/;
  134.     return 'jis' if /$re_jin|$re_jout/o;
  135.  
  136.     local($sjis, $euc);
  137.     $sjis += length($&) while /$re_sjis_s/go;
  138.     $euc  += length($&) while /$re_euc_s/go;
  139.     (&max($sjis, $euc), ('euc', undef, 'sjis')[($sjis<=>$euc) + $[ + 1]);
  140. }
  141. sub max { $_[ $[ + ($_[$[] < $_[$[+1]) ]; }
  142.  
  143. ;#
  144. ;# Convert any code to specified code
  145. ;#
  146. sub convert {
  147.     local(*_, $ocode, $icode) = @_;
  148.     return (undef, undef) unless $icode = $icode || &getcode(*_);
  149.     $ocode = 'jis' unless $ocode;
  150.     local(*convf) = $convf{$icode, $ocode};
  151.     do convf(*_);
  152.     (*convf, $icode);
  153. }
  154.  
  155. ;#
  156. ;# JIS to JIS
  157. ;#
  158. sub jis2jis {
  159.     local(*_) = @_;
  160.     s/$re_jin/$jin/go;
  161.     s/$re_jout/$jout/go;
  162. }
  163.  
  164. ;#
  165. ;# SJIS to JIS
  166. ;#
  167. sub sjis2jis {
  168.     local(*_) = @_;
  169.     s/$re_sjis_s/&_sjis2jis($&)/geo;
  170. }
  171. sub _sjis2jis {
  172.     local($_) = @_;
  173.     s/../$s2e{$&}||&s2e($&)/geo;
  174.     tr/\241-\376/\041-\176/;
  175.     $jin . $_ . $jout;
  176. }
  177.  
  178. ;#
  179. ;# EUC to JIS
  180. ;#
  181. sub euc2jis {
  182.     local(*_) = @_;
  183.     s/$re_euc_s/&_euc2jis($&)/geo;
  184. }
  185. sub _euc2jis {
  186.     local($_) = @_;
  187.     tr/\241-\376/\041-\176/;
  188.     $jin . $_ . $jout;
  189. }
  190.  
  191. ;#
  192. ;# JIS to EUC
  193. ;#
  194. sub jis2euc {
  195.     local(*_) = @_;
  196.     s/$re_jin([!-~]*)$re_jout/&_jis2euc($1)/geo;
  197. }
  198. sub _jis2euc {
  199.     local($_) = @_;
  200.     tr/\041-\176/\241-\376/;
  201.     $_;
  202. }
  203.  
  204. ;#
  205. ;# JIS to SJIS
  206. ;#
  207. sub jis2sjis {
  208.     local(*_) = @_;
  209.     s/$re_jin([!-~]*)$re_jout/&_jis2sjis($1)/geo;
  210. }
  211. sub _jis2sjis {
  212.     local($_) = @_;
  213.     tr/\041-\176/\241-\376/;
  214.     s/../$e2s{$&}||&e2s($&)/ge;
  215.     $_;
  216. }
  217.  
  218. ;#
  219. ;# SJIS to EUC
  220. ;#
  221. sub sjis2euc {
  222.     local(*_) = @_;
  223.     s/$re_sjis_c/$s2e{$&}||&s2e($&)/geo;
  224. }
  225. sub s2e {
  226.     ($c1, $c2) = unpack('CC', $code = shift);
  227.     if ($c2 >= 0x9f) {
  228.     $c1 = $c1 * 2 - ($c1 >= 0xe0 ? 0xe0 : 0x60);
  229.     $c2 += 2;
  230.     } else {
  231.     $c1 = $c1 * 2 - ($c1 >= 0xe0 ? 0xe1 : 0x61);
  232.     $c2 += 0x60 + ($c2 < 0x7f);
  233.     }
  234.     $s2e{$code} = pack('CC', $c1, $c2);
  235. }
  236.  
  237. ;#
  238. ;# EUC to SJIS
  239. ;#
  240. sub euc2sjis {
  241.     local(*_) = @_;
  242.     s/$re_euc_c/$e2s{$&}||&e2s($&)/geo;
  243. }
  244. sub e2s {
  245.     ($c1, $c2) = unpack('CC', $code = shift);
  246.     if ($c1 % 2) {
  247.     $c1 = ($c1>>1) + ($c1 < 0xdf ? 0x31 : 0x71);
  248.     $c2 -= 0x60 + ($c2 < 0xe0);
  249.     } else {
  250.     $c1 = ($c1>>1) + ($c1 < 0xdf ? 0x30 : 0x70);
  251.     $c2 -= 2;
  252.     }
  253.     $e2s{$code} = pack('CC', $c1, $c2);
  254. }
  255.  
  256. ;#
  257. ;# SJIS to SJIS, EUC to EUC
  258. ;#
  259. sub sjis2sjis { 0; }
  260. sub euc2euc { 0; }
  261.  
  262. 1;
  263.