[Message Prev][Message Next][Thread Prev][Thread Next][Message Index][Thread Index]
Re: [MD:7103] Bug? of unix-to-dos-filename and dos-to-unix-filename
- X-ml-count: 7113
- Subject: Re: [MD:7103] Bug? of unix-to-dos-filename and dos-to-unix-filename
- From: "M.Fujii" <boochang@xxxxxxxxxxxx>
- Date: Fri, 23 Dec 2005 11:06:30 +0900 (JST)
- X-mailer: Mew version 4.2 on Emacs 22.0.50 / Mule 5.0 (SAKAKI)
藤井です。
From: Hideyuki SHIRAI (白井秀行) <shirai@xxxxxxxxxxx>
Subject: [MD:7103] Bug? of unix-to-dos-filename and dos-to-unix-filename
Date: Wed, 21 Dec 2005 18:59:45 +0900 (JST)
Message-ID: <20051221.185945.143328023.shirai.hideyuki@xxxxxxxxxxxxxxxxxxx>
> dispicon で icon がでないので気付いたのですが、これってバグでしょ
> うか?それともなにか使いかたを間違っていますか?
>
> (unix-to-dos-filename "c:/書/tmp.txt")
> => "c:\\書/tmp.txt"
>
> (dos-to-unix-filename "c:\\書\\tmp.txt")
> => "c:/書\\tmp.txt"
>
> となります。Meadow1.15 でも同じでした。
>
> w32.c: normalize_filename() をじーーと見てもぼくには全然わかりま
> せん (_ _)
normalize_filename は文字列として Emacs の内部コードが渡されます。
しかし、w32.c:normalize_filename() は文字列として Windows の文字コード
を想定して実装してあるようです。
したがって、正しく動作しないケースがあります。(また、それとは別の問題も
抱えています。後述します)
まず、白井さんのケースを単純化して以下のような場合を考えます。
(dos-to-unix-filename "書\\")
以下を評価すれば分かると思いますが、emacs の内部コードは 0x92 0xbd
0xf1 0x5c となります。(最初の 3 バイトが「書」、最後の 1 バイトが「\」)
(mapconcat (lambda (x) (format "0x%02x" x))
(encode-coding-string "書\\" 'no-conversion) " ")
関数の冒頭では文字列のポインタ fp は文字列の冒頭 0x92 を指しています。
これはパス区切文字ではないので、CharNext で次の文字を探します。
CharNext は日本語環境では文字列を Shift_JIS (というか cp932) として扱い
ます。最初の 2 バイトは SJIS では「朕」になるので、CharNext の呼び出し
で 2 バイト進みます。
すると、0xf1 はパス区切文字ではないので、CharNext で次の文字を探します。
3 バイト目、4 バイト目 に漢字は割りあてられていないようですが、これも
SJIS の 2 バイト文字と判断されるので、CharNext は文字列終端を返します。
これによって「\」は無視されることになります。
正常に動作する例として、(dos-to-unix-filename "山\\") の場合を考えます
と、これの内部コードは 0x92 0xbb 0xb3 0x5c です。
先程と同様に文字列を処理をなぞってみると、最初の 2 バイトは「捗」になり
ますので、CharNext で 3 バイト目に移動します、3 バイト目は半角「ウ」に
なるので、CharNext は 1 バイト文字と判断し、4 バイト目に移動します。
4 バイト目の「\」を変換して、終了することになります。
あと、dos-to-unix-filename には、変数 w32-downcase-file-names が非 nil
であれば、ファイル名を英小文字に正規化するという機能もあります。しかし、
この機能は正常に動作していません。
# 失敗ケース 1
(let ((w32-downcase-file-names t))
(dos-to-unix-filename "c:\\TEST")) ==> "c:/TEST"
# 失敗ケース 2
(let ((w32-downcase-file-names t))
(dos-to-unix-filename "c:\\TEST\\TEST")) ==> "c:/tEsT/TEST"
# 失敗ケース 3
(let ((w32-downcase-file-names t))
(dos-to-unix-filename "c:\\TEST\\")) ==> "c:/tEsT/"
# 失敗ケース 4
(let ((w32-downcase-file-names t))
(dos-to-unix-filename "c:\\TEST\\TEST\\")) ==> "c:/tEsT/tEsT/"
つまり、以下の不具合があります。
1. ファイル名がパス区切文字で終わっていない場合、最後のパス区切文字以
降変換されない。
2. 小文字変換が 2 文字目以降で処理されている。
--
藤井 正行 / Masayuki FUJII