texjporg / tex-jp-build

Minimum source repository to build Japanese TeX processing tools
23 stars 6 forks source link

[(u)pbibtex] TeX Live 2023 の pbibtex + sieicej.bst で文字化け #157

Closed h20y6m closed 1 year ago

h20y6m commented 1 year ago

Twiter より

確かに TeX Live 2023 の pbibtex (upbibtex --kanji-internal=euc) で試すと以下のような test.tex と test.bib で「日本音響学会誌」が「日鵬恭音」に化けます。 (sieicej.bst は #133 のリンク先からダウンロード)

TeX Live 2022 の pbibtex では発生しませんが、upbibtex --kanji-internal=euc では同様の文字化けが発生します。

\documentclass{jarticle}
\bibliographystyle{sieicej}
\begin{document}
てすと。\cite{haniu2020asj,kaneda2013asj}
\bibliography{test}
\end{document}
@article{haniu2020asj,
  title={室内音響におけるインパルス応答測定と評価},
  author={羽入 敏樹},
  journal={日本音響学会誌},
  volume={76},
  number={3},
  pages={156-163},
  year={2020},
  doi={10.20697/jasj.76.3_156}
}

@article{kaneda2013asj,
  title={インパルス応答測定信号と測定誤差},
  author={金田 豊},
  journal={日本音響学会誌},
  volume={69},
  number={10},
  pages={549-554},
  year={2013},
  doi={10.20697/jasj.69.10_549}
}

調べてみたところ sieicej.bst の format.string で文字列が壊れているみたいです。

FUNCTION {format.string}
{
  't :=
  ""
  { t empty$ not}
  {
    t #1 #1 substring$ "." =
      {
        t #1 #2 substring$ ". " = not
          {
            t #1 #1 substring$ *
            t #2 global.max$ substring$ 't :=
          }
          {
            ".\ " *
            t #3 global.max$ substring$ 't :=
          }
        if$
      }
      {
        t #1 #1 substring$ is.kanji.str$
          {
            t #1 #2 substring$ *
            t #3 global.max$ substring$ 't :=
          }
          {
            t #1 #1 substring$ *
            t #2 global.max$ substring$ 't :=
          }
        if$
      }
    if$
  }
  while$
}

いろいろ試してみると substring$ の結果に対してさらに #1 #1 substring$ をすると先頭が和文文字にもかかわらず 1 バイトだけ切り出されているようです。

TeX Live 2022 の pbibtex では文字化けは発生しませんが #3 global.max$ substring$ #1 #1 substring$ text.length$ で 1 が返ってくるので潜在的バグではないかと思われます。


bibtex.web の x_substring に以下の部分で先頭からの切り出し(pop_lit2 = 1)かつ文字列が特定の条件(pop_lit3 >= cmd_str_ptr)を満たすときにショートカットをするようです。

https://github.com/texjporg/tex-jp-build/blob/9cc7b92d4caa422c658f26c5312a75b78ca0337c/source/texk/web2c/bibtex.web#L10821-L10829

cmd_str_ptr が何かよくわからないのですが、コードの雰囲気的に対象文字列が pool の最後尾にあって先頭文字からの切り出しの場合は新たに文字列を確保してコピーするのではなく pool 終端ポインタを手前にずらすことで高速化しているのではないかと思います。

このショートカット部分に和文文字の途中で切らないようにする対策がされていないので和文文字なのに先頭 1 バイトだけ切り出されているのではないかと思います。

t-tk commented 1 year ago

とりあえず、TeX Live 2023 の bibtexu では文字化けは発生しないようです。 pbibtex (TeX Live 2019) では、羽入敏樹 の姓と名の間に \hskip1zw が入らない、bibtexu (TeX Live 2023) では入る、という違いがありました。 pbibtex (TeX Live 2023) の文字化けはこちらでも再現しました。 upbibtex (TeX Live 2019)では、無限ループに入ったのか、終了しません。 upbibtex --kanji-internal=euc (TeX Live 2019) は、pbibtex (TeX Live 2019) と同じ結果(文字化け無し、羽入敏樹 の姓と名の間に \hskip1zw が入らない)でした。

This is BibTeXu: a UTF-8 Big BibTeX version 0.99d-x4.00 (TeX Live 2023/dev)

\begin{thebibliography}{1}

\bibitem{haniu2020asj}
羽入\hskip1zw敏樹,
``室内音響におけるインパルス応答測定と評価,\<''
日本音響学会誌,
vol.76,no.3,pp.156--163,2020.

\bibitem{kaneda2013asj}
金田\hskip1zw豊,
``インパルス応答測定信号と測定誤差,\<''
日本音響学会誌,
vol.69,no.10,pp.549--554,2013.

\end{thebibliography}
h20y6m commented 1 year ago

https://github.com/h20y6m/tex-jp-build/commit/2d43ba2d9e45adafe8643c6a00c5204daaee6830 で修正してみました。

pBibTeX で化けなかったのは和文の 1 バイト目の次に必ず 2 バイト目が続いている前提で終端チェックをしておらずオーバーランして後ろにゴミとして残っていた 2 バイト目を拾っていたため偶然うまくうごいていたように見てていただのだと思います。 (多分 20 年以上前からずっとバグっていた) upBibTeX で終端チェックをするようになった部分でバグが表面化したのだと思います。

BibTeXu はバイト単位ではなくコードポイント単位のように見えます。コードポイント単位なので和文文字の途中で切られることがないので大丈夫なのだと思います。 一方で sieicej.bst は和文文字が 2 バイト前提の処理になっているため、BibTeXu だと和文 2 文字を 1 文字とみなして処理してしまい想定外の結果になっているように見えます。

t-tk commented 1 year ago

pbibtex-manual の方にある substring$ の単体テストに今回の件を追加しました。 https://github.com/texjporg/pbibtex-manual/tree/test_substr の tests/unit/ の中の test-bib.sh testsubstr.bst substrp.bbl.base substru.bbl.base あたりです。 @h20y6m さんのパッチがちゃんと動いているようです。ありがとうございます。 以前の pbibtex, upbibtex, upbibtex -kanji-internal=euc では、今回追加したところが壊れます。

TeX Live にコミットしましょうか。 素の pbibtex の方(upbibtex -kanji-internal=euc でない方)は放置でいいですよね? もう既にTeX Live のソースから消してしまっていますし。

t-tk commented 1 year ago

TeX Live svn r66818 コミットしました。 何かあったら再オープンをお願いします。