Skip to content

Instantly share code, notes, and snippets.

@aminophen
Created September 1, 2023 22:53
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save aminophen/43b5f7f8592fc66210935f67d4d88391 to your computer and use it in GitHub Desktop.
upTeX: 文字コードの範囲を調べてみる
%#!euptex
% "8000000 = 2147483648 (TeX Integer Limit + 1)
% "1000000 = 16777216 (24bit + 1)
% "110000 = 1114112 (Unicode + 1)
% 文字コード "110000 以上は otf パッケージで
% Unicode (.."10FFFF) までに設定された \kcatcode や
% 禁則ペナルティの影響を受けない目的で利用される.
% ノード化の際もそのままの文字コードである.
% DVI 出力時には文字コード mod "110000 とみなす.
\kchar"2603
\kchar"112603 % = "2603 + "110000
\kchar"222603 % = "2603 + "110000 x 2
% => いずれも DVI では "2603 になる.
% 現在は文字コードとして TeX の最大の整数値 "7FFFFFFF まで
% 許容されているらしい(\chardef/\kchardef にも許容).
% 和文トークンは kcatcode 5bit + charcode 24bit で表すので
% 文字コードは下位 24bit すなわち mod "1000000 に切られる.
% ノード化の際は冒頭と同様.
% しかし,一部 \lastnodechar がおかしい?
\kchar "7FFFFF % "7FFFFF = "110000 x "7 + "8FFFF (mod "110000)
% => DVI では "8FFFF
\showthe\lastnodechar % => 8388607 = "8FFFF
\kchar "FFFFFF % "FFFFFF = "110000 x "F + "FFFF (mod "110000)
% => DVI では "FFFF
\showthe\lastnodechar % => 16777215 = "FFFFFF
\kchar"7F000001 % "7FFFFFFF = "1000000 x "7F + "1 (mod "1000000)
% 下位24bit: "1 = "1 (mod "110000)
% => DVI では "1
\showthe\lastnodechar % => -16777215 !?
\kchar"7FFFFFFF % "7FFFFFFF = "1000000 x "7F + "FFFFFF (mod "1000000)
% 下位24bit: "FFFFFF = "110000 x "F + "FFFF (mod "110000)
% => DVI では "FFFF
\showthe\lastnodechar % => -1 !?
% 一部 \lastnodechar がおかしい?
\def\TEST#1{%
\kchardef\X=#1 \message{\the\X}%
\X \showthe\lastnodechar}
\TEST{"1F000001}% => 520093697, 1
\TEST{"2F000001}% => 788529153, 1
\TEST{"3F000001}% => 1056964609, 1
\TEST{"4F000001}% => 1325400065, 1
\TEST{"5F000001}% => 1593835521, 1
\TEST{"6F000001}% => 1862270977, -16777215 !?
\TEST{"7F000001}% => 2130706433, -16777215 !?
% トークン生成 \Uchar は大丈夫そう
\newcount\C
\def\TEST#1{%
\edef\X{\Uchar#1}\expandafter\C=\expandafter`\X
\message{\expandafter\meaning\X,%
\expandafter\the\expandafter\kcatcode\expandafter`\X,%
\the\C}}
\TEST{"7F000001}% => the character ^^A,15,1
\TEST{"7F000020}% => blank space ,15,32
\TEST{"7FFF4E00}% => kanji character 一,16,19968
\TEST{"7FFFFF66}% => kanji character ヲ,17,65382
\bye
@h-kitagawa
Copy link

\kchar, \kchardef の引数の範囲を制限(というか,scan_char_num で 2^24 以上を弾く)するほうが自然な気がしていますが…….

@aminophen
Copy link
Author

kanji.c の is_char_kanji が単に c>0 の判定になっているのを 0 以上 2^24 未満 にすれば自然と言えばそれまでですが,何か意味があるのかなと。

@aminophen
Copy link
Author

ちなみに ptex-guide-en にはこんな使い方ができる,と書いてしまっていました。

ptex-guide-en

@h-kitagawa
Copy link

kanji.c の is_char_kanji が単に c>0 の判定になっているのを 0 以上 2^24 未満 にすれば自然と言えばそれまでですが,何か意味があるのかなと。

check_kanji のところで,和文文字トークンの判定を is_char_kanji に投げてしまっていることぐらいな気がします.

 boolean check_kanji (integer c)
 {
     if (c >= CS_TOKEN_FLAG) return false;
     else if (!(XXHi(c)>=KCAT_KANJI && XXHi(c)<=KCAT_HANGUL)) return false;
-    else return is_char_kanji(c);
+    else return is_char_kanji(c & CJK_TOKEN_FLAG);
 }
...
 boolean is_char_kanji(integer c)
 {
     if (is_internalUPTEX()) 
-        return (c >= 0);
+        return ((c >= 0)&&(c<CJK_CHAR_LIMIT));

@aminophen
Copy link
Author

なるほど。直し方としては

  • kanji.c の is_char_kanji を 24bit に制限(→文字コードの有効範囲が減る=大きな整数値を定義する技は封じられる)して,付随する check_kanji も調整
  • kanji.c はそのまま,uptex-m.ch で \char, \kchar, \chardef, \kchardef からのノード生成前に mod max_cjk_val する (texjporg/tex-jp-build@550980f: texjporg/tex-jp-build#159 の修正への追加という形になっています)

どちらでも実現は可能そうです。もちろん前者の方がきれいですが,相談してみます。

@aminophen
Copy link
Author

texjporg/tex-jp-build#160 を立てました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment