nkf を使用した文字コード変換ライブラリCinnamonのインストール

CinnamonはHaskellからnkfを呼び出し、文字コードを変換するためのライブラリです。便利なライブラリなのですがエラーが発生するため、そのままではインストール出来ません。修正してインストールする手順をまとめました。

  • こちらよりcinnamon-0.2.tar.gz をダウンロードします。
  • ファイルを展開するとディレクトリ cinnamon-0.2 が作成されますので、 cinnamon-0.2 に移動し、cabal configure を実行します。

しかし、以下のエラーが表示されます。

PS C:\HaskellPlatform\cinnamon\cinnamon-0.2> cabal configure
Resolving dependencies...
[1 of 1] Compiling Main             ( Setup.hs, dist\setup\Main.o )
Linking .\dist\setup\setup.exe ...
Configuring cinnamon-0.2...
Warning: No 'build-type' specified. If you do not need a custom Setup.hs or
./configure script then use 'build-type: Simple'.             -- > build-type:     Simple を追加
Warning: Instead of 'ghc-options: -ffi' use 'extensions:
ForeignFunctionInterface'
Warning: The 'license-file' field refers to the file 'LICENCE' which does not
exist.
  • cinnamon.cabalを以下のように修正します。
Name:           cinnamon
Version:        0.2
License:        OtherLicense
--  LICENCE から修正
License-File:   LICENSE
Author:         TANAKA Shinya
Homepage:       http://sourceforge.jp/projects/cinnamon/
Category:       Utility
-- Build-Depends:  base (小文字へ)
build-depends:  base, array, utf8-string
Synopsis:       Tiny utilities for Haskell.
-- build-type: 追加
build-type:     Simple
Exposed-modules:
        Cinnamon,
        Cinnamon.Base64,
        Cinnamon.Bsearch,
        Cinnamon.Crc,
        Cinnamon.Misc,
        Cinnamon.Nkf,
        Cinnamon.Rot13,
        Cinnamon.RubyString,
        Cinnamon.Ucs
C-Sources:
        Cinnamon/cnkf.c
Extensions:     CPP
-- GHC-Options:    -ffi 削除

これでcabal configure は通りますが、cabal build で以下のエラーが出ます。

Preprocessing library cinnamon-0.2...
Building cinnamon-0.2...
(snip)
[3 of 9] Compiling Cinnamon.Nkf     ( Cinnamon\Nkf.hs, dist\build\Cinnamon\Nkf.o )

Cinnamon\Nkf.hs:16:9: parse error on input `import'
  • これは Nkf.hs の先頭に{-# LANGUAGE ForeignFunctionInterface #-}{-# LANGUAGE MagicHash, UnliftedFFITypes #-}の2行を追加するとコンパイルが通ります。
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE MagicHash, UnliftedFFITypes #-}
#ifndef __HADDOCK__
-- $Id: Nkf.hs,v 1.10 2007/01/14 11:31:01 ha-tan Exp $
#endif
module Cinnamon.Nkf (
  nkf, nkf',
  toJis, toEuc, toSjis, toUtf8, toUtf16
) where
  • このままインストールしても良いのですが、昨日検証した「nkf を使用した文字コード変換ライブラリCinnamonのUCS4->UTF8の変換」ではutf8-stringのencodeString、decodeString が高速でしたので Ucs.hs を入れ替えます。
  • 新たに関数に ' を追加した同じ名前の関数を定義しました。sjisToUcs4は変換のときに半角カナは全角カナに変換されますが、sjisToUcs4'は変換を行いません。
module Cinnamon.Ucs (
  jisToUcs4, jisToUcs4', eucToUcs4, eucToUcs4', sjisToUcs4, sjisToUcs4', utf16ToUcs4, utf16ToUcs4',
  ucs4ToJis, ucs4ToJis', ucs4ToEuc, ucs4ToEuc', ucs4ToSjis, ucs4ToSjis', ucs4ToUtf16,  ucs4ToUtf16'
) where

import Codec.Binary.UTF8.String  (encodeString ,decodeString )
import Cinnamon.Nkf              (nkf)

-- -x	通常行われるX0201仮名->X0208の仮名変換しない
-- -Z	X0208中の英数字と一部の記号をASCIIに変換する
{-
$ nkf --help
Usage:  nkf -[flags] [--] [in file] .. [out file for -O flag]
 j/s/e/w  Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP
          UTF options is -w[8[0],{16,32}[{B,L}[0]]]
 J/S/E/W  Specify input encoding ISO-2022-JP, Shift_JIS, EUC-JP
          UTF option is -W[8,[16,32][B,L]]
 m[BQSN0] MIME decode [B:base64,Q:quoted,S:strict,N:nonstrict,0:no decode]
 M[BQ]    MIME encode [B:base64 Q:quoted]
 f/F      Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl
 Z[0-4]   Default/0: Convert JISX0208 Alphabet to ASCII
          1: Kankaku to one space  2: to two spaces  3: HTML Entity
          4: JISX0208 Katakana to JISX0201 Katakana
 X,x      Assume X0201 kana in MS-Kanji, -x preserves X0201
 O        Output to File (DEFAULT 'nkf.out')
 L[uwm]   Line mode u:LF w:CRLF m:CR (DEFAULT noconversion)
 --ic=<encoding>        Specify the input encoding
 --oc=<encoding>        Specify the output encoding
 --hiragana --katakana  Hiragana/Katakana Conversion
 --katakana-hiragana    Converts each other
 --{cap, url}-input     Convert hex after ':' or '%'
 --numchar-input        Convert Unicode Character Reference
 --fb-{skip, html, xml, perl, java, subchar}
                        Specify unassigned character's replacement
 --in-place[=SUF]       Overwrite original files
 --overwrite[=SUF]      Preserve timestamp of original files
 -g --guess             Guess the input code
 -v --version           Print the version
 --help/-V              Print this help / configuration
Network Kanji Filter Version 2.0.9 (2009-01-20)
Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).
Copyright (C) 1996-2009, The nkf Project.
-}

-- | JISコードの文字列をUCS4の文字列に変換します。
-- MIMEの変換は行いません。
-- この関数はスレッドセーフではありません。
jisToUcs4 :: String -> String
jisToUcs4 = decodeString . nkf "-m0Jw"

jisToUcs4' :: String -> String
jisToUcs4' = decodeString . nkf "-m0xJw"

-- | EUCコードの文字列をUCS4の文字列に変換します。
-- MIMEの変換は行いません。
-- この関数はスレッドセーフではありません。
eucToUcs4 :: String -> String
eucToUcs4 = decodeString . nkf "-m0Ew"

eucToUcs4' :: String -> String
eucToUcs4' = decodeString . nkf "-m0xEw"

-- | Shift-JISコードの文字列をUCS4の文字列に変換します。
-- MIMEの変換は行いません。
-- この関数はスレッドセーフではありません。
sjisToUcs4 :: String -> String
sjisToUcs4 = decodeString . nkf "-m0Sw"

sjisToUcs4' :: String -> String
sjisToUcs4' = decodeString . nkf "-m0xSw"

-- | UTF16の文字列をUCS4の文字列に変換します。
-- MIMEの変換は行いません。
-- この関数はスレッドセーフではありません。
utf16ToUcs4 :: String -> String
utf16ToUcs4 = decodeString . nkf "-m0W16w"

utf16ToUcs4' :: String -> String
utf16ToUcs4' = decodeString . nkf "-m0xW16w"

-- | UCS4の文字列をJISコードの文字列に変換します。
-- MIMEの変換は行いません。
-- この関数はスレッドセーフではありません。
ucs4ToJis :: String -> String
ucs4ToJis = nkf "-m0Wj" . encodeString

ucs4ToJis' :: String -> String
ucs4ToJis' = nkf "-m0xWj" . encodeString

-- | UCS4の文字列をEUCコードの文字列に変換します。
-- MIMEの変換は行いません。
-- この関数はスレッドセーフではありません。
ucs4ToEuc :: String -> String
ucs4ToEuc = nkf "-m0We" . encodeString

ucs4ToEuc' :: String -> String
ucs4ToEuc' = nkf "-m0xWe" . encodeString

-- | UCS4の文字列をShift-JISコードの文字列に変換します。
-- MIMEの変換は行いません。
-- この関数はスレッドセーフではありません。
ucs4ToSjis :: String -> String
ucs4ToSjis = nkf "-m0Ws" . encodeString

ucs4ToSjis' :: String -> String
ucs4ToSjis' = nkf "-m0xWs" . encodeString

-- | UCS4の文字列をUTF16の文字列に変換します。
-- MIMEの変換は行いません。
-- この関数はスレッドセーフではありません。
ucs4ToUtf16 :: String -> String
ucs4ToUtf16 = nkf "-m0Ww16" . encodeString

ucs4ToUtf16' :: String -> String
ucs4ToUtf16' = nkf "-m0xWw16" . encodeString

cabal install でインストールされます。

  • ucs4ToSjis' $ sjisToUcs4' で SJISからUCS4に変換し、その逆にUCS4からSJISに変換しても半角のままです。ucs4ToSjis $ sjisToUcs4 は全角に変換されます。
Prelude> :m + Data.Char Cinnamon.Ucs
Prelude Data.Char Cinnamon.Ucs> let sjisHanKana = map chr [0xa1..0xdf]
Prelude Data.Char Cinnamon.Ucs> putStrLn $ ucs4ToSjis' $ sjisToUcs4' sjisHanKana
-- > 。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚
Prelude Data.Char Cinnamon.Ucs> putStrLn $ ucs4ToSjis $ sjisToUcs4 sjisHanKana
-- > 。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜
  • SJISの「あ」を変換した例
> putStrLn [chr 0x82,chr 0xa0]                                                 -- > あ
-- SJIS
> map (\x ->showHex (ord x) "")$ [chr 0x82,chr 0xa0]                           -- > ["82","a0"]
-- UCS4
> map (\x ->showHex (ord x) "")$ sjisToUcs4 [chr 0x82,chr 0xa0]                -- > ["3042"]
-- UTF16
> map (\x ->showHex (ord x) "")$ ucs4ToUtf16 $ sjisToUcs4 [chr 0x82,chr 0xa0]  -- > ["30","42"]
-- UTF8
> map (\x ->showHex (ord x) "")$ encodeString $ sjisToUcs4 [chr 0x82,chr 0xa0] -- > ["e3","81","82"]
-- JIS
> map (\x ->showHex (ord x) "")$ ucs4ToJis $ sjisToUcs4 [chr 0x82,chr 0xa0]    -- > ["1b","24","42","24","22"]
-- EUC
> map (\x ->showHex (ord x) "")$ ucs4ToEuc $ sjisToUcs4 [chr 0x82,chr 0xa0]    -- > ["a4","a2"]
  • nkf を直接呼び出せばnkf の全機能が使用できます。
> map (\x ->showHex (ord x) "")$ nkf "-m0Sw" [chr 0x82,chr 0xa0]     -- > ["e3","81","82"]
> map (\x ->showHex (ord x) "")$ nkf "-m0Sw32" [chr 0x82,chr 0xa0]   -- > ["e3","81","82"]
> map (\x ->showHex (ord x) "")$ nkf "-m0Sw16" [chr 0x82,chr 0xa0]   -- > ["30","42"]
> map (\x ->showHex (ord x) "")$ nkf "-m0Sw16L" [chr 0x82,chr 0xa0]  -- > ["ff","fe","42","30"]
> map (\x ->showHex (ord x) "")$ nkf "-m0Sw16L0" [chr 0x82,chr 0xa0] -- > ["42","30"]
> map (\x ->showHex (ord x) "")$ nkf "-m0Sw16B0" [chr 0x82,chr 0xa0] -- > ["30","42"]
> map (\x ->showHex (ord x) "")$ nkf "-m0Sw16B" [chr 0x82,chr 0xa0]  -- > ["fe","ff","30","42"]

自己責任でお願いします。