mtgto/macSKK

SKK_JISYO.JIS3_4の読み込みに失敗する

rkarsnk opened this issue · 6 comments

現象

https://github.com/skk-dev/dict で配布されているSKK-JISYO.JIS3_4を読みこもうとすると
エラーmacSKK.EucJis2004Error.convert が発生し読みこみに失敗する.

ログ

2024-05-13 12:50:48.797] [notice] SKK辞書 SKK-JISYO.JIS3_4 を読み込みます
[2024-05-13 12:50:48.801] [error] 入力に不正なバイト列が存在します
[2024-05-13 12:50:48.801] [error] 辞書 SKK-JISYO.JIS3_4 の読み込みでエラーが発生しました: Error Domain=macSKK.EucJis2004Error Code=1
[2024-05-13 12:50:48.801] [notice] 辞書 SKK-JISYO.JIS3_4 がプロセスから削除されます
[2024-05-13 12:50:48.801] [notice] SKK辞書 SKK-JISYO.JIS3_4 の読み込みに失敗しました!: Error Domain=macSKK.EucJis2004Error Code=1

関連しそうなissue

報告ありがとうございます。ちょっと対処が難しそうなのでどうするか考えます。

簡単な調査

macSKKではlibiconvを使ってEUC-JIS-2004からUTF-8に変換を試みますが、SKK-JISYO.JIS3_4には結合文字(合字)が含まれており、libiconvは結合文字をUnicodeに変換するときに失敗しているようです。

iconv -f EUC-JISX0213 -t UTF-8 ~/Downloads/SKK-JISYO.JIS3_4 >/dev/null
iconv: iconv(): Illegal byte sequence

たとえば iconv -f EUC-JISX0213 -t UTF-8 /path/to/SKK-JISYO.JIS3_4 で見ると、2502行目の a' /á/ά;発音記号/ で途切れています。このあとにも続いているのですがiconvコマンドで変換できなくなったようです。

このあとにくる 0xABCB は EUC-JISX0213で U+028c U+0301 の2文字の結合文字 (合字とも) である ʌ́ (アキュートアクセント付きターンドV小文字) に割り当てられています。

libiconvのeuc_jisx0213.hでは結合文字について書いてありますが、これに対応するのはけっこうめんどうくさそう。

if (wc) {
  if (wc < 0x80) {
    /* It's a combining character. */
    ucs4_t wc1 = jisx0213_to_ucs_combining[wc - 1][0];
    ucs4_t wc2 = jisx0213_to_ucs_combining[wc - 1][1];
    /* We cannot output two Unicode characters at once. So,
       output the first character and buffer the second one. */
    *pwc = wc1;
    conv->istate = wc2;
  } else
    *pwc = wc;
    return (c == 0x8f ? 3 : 2);
  }
}

https://opensource.apple.com/source/libiconv/libiconv-24.0.1/libiconv/lib/euc_jisx0213.h.auto.html

こちらで対処療法的にやったのは,辞書ファイルの文字コードをnkfでUTF-8に変換し,
先頭行を以下のように変更して,読み込ませました.

;; -*- mode: fundamental; coding: utf-8 -*-

読み込ませた結果は以下のようになりますが,①②などの丸囲み数字の変換はできるようになっています.

4,824エントリ(3,255行の読み込みエラー)

ひとまず原因の一つはmacOSに入っているlibiconvが古いことでした。
ためしにHomebrewで brew install libiconv したあとでHomebrew版のiconv (GNU iconv 1.17) を使ったら変換はできました。
https://formulae.brew.sh/formula/libiconv

/opt/homebrew/opt/libiconv/bin/iconv -f EUC-JISX0213 -t UTF-8 /path/to/SKK-JISYO.JIS3_4 > SKK-JISYO.JIS3_4.utf8/opt/homebrew/opt/libiconv/bin/iconv --version
iconv (GNU libiconv 1.17)
Copyright (C) 2000-2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Bruno Haible.

ただUTF-8版でもmacSKKで41行読み込みエラーとなったので確認してみます。
(合字だけではなさそう…?)

お手数おかけしますが、ひとまずはUTF-8に変換して使ってみてください。
nkfはさすがに古すぎるので正常に変換できなくてもおかしくないためlibiconvをおすすめします。

libiconvでUTF-8に変換したあとの41行の読み込みエラーのうち、例えばSKK-JISYO.JIS3_4の2493行目にある ^ /̂;(diacritic)/ 、これをmacSKKでは ” /” で分割して、前を読みとして、後ろを変換候補として扱うんですが、Swiftだとこの文字列に ” /” なんてないよ、といわれてしまいますね。

swift repl
Welcome to Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4).
Type :help for assistance.
  1> "^ /̂;(diacritic)/".split(separator:  " /")
$R0: [String.SubSequence] = 1 value {
  [0] = "^ /̂;(diacritic)/" {
    _slice = {
      _startIndex = 0[any]
      _endIndex = 18[utf8]
      _base = "^ /̂;(diacritic)/"
    }
  }
}
  2> "^ /̂;(diacritic)/".split(separator: " /") .count
$R1: Int = 1

Rubyはちゃんと分割できるので、Swiftでの文字列処理で工夫する必要がありそう。

irb
irb(main):001:0> "^ /̂;(diacritic)/".split(" /", 2)
=> ["^", "̂;(diacritic)/"]

自分のブラウザでもスラッシュと^が合体したような文字に見えているので、そのあたりで判定がうまくいってなさそう。

この ^ に見えるのはUnicodeではU+0302。
合成可能なダイアクリティカルマークの1つなので、SwiftのStringでは先行のスラッシュと結合した文字として扱われるようです。
https://ja.wikipedia.org/wiki/%E5%90%88%E6%88%90%E5%8F%AF%E8%83%BD%E3%81%AA%E3%83%80%E3%82%A4%E3%82%A2%E3%82%AF%E3%83%AA%E3%83%86%E3%82%A3%E3%82%AB%E3%83%AB%E3%83%9E%E3%83%BC%E3%82%AF

y-yu commented

関連するかもしれない話題として、macOS 14.1.2のlibiconvですとそもそもSKK-JISYO.LをEUCで読めないようです。

[2024-06-18 10:57:20.861] [notice] SKK辞書 SKK-JISYO.L を読み込みます
[2024-06-18 10:57:20.868] [error] 入力に不正なバイト列が存在します
[2024-06-18 10:57:20.869] [error] 辞書 SKK-JISYO.L の読み込みでエラーが発生しました: Error Domain=macSKK.EucJis2004Error Code=1
[2024-06-18 10:57:20.869] [notice] 辞書 SKK-JISYO.L がプロセスから削除されます
[2024-06-18 10:57:20.869] [notice] SKK辞書 SKK-JISYO.L の読み込みに失敗しました!: Error Domain=macSKK.EucJis2004Error Code=1

macOS 14.5にしたところ読めるようになりましたので、macOS標準のlibiconvに依存するかどうかも今後考えてもいいかもです 🤔