[不具合]文字数カウントNo.10435
fzok4234 さん 21/05/26 16:31
 
いつもお世話になっております。

さて、文字数カウント機能において誤った文字数が返される問題が見つかりました。

テストに使ったファイルは、
1行の書式  : U+002Aが2499個連続 + 改行コードLF
行数       : 1000000行
文字コード : Shift-JIS
の2500000000文字、2500000000Byteです。

なお、ファイル読み込みに際しては
https://www.maruo.co.jp/turukame/3/x10410_.html#10410
で挙げた不正終了の不具合を回避するため、「ファイルの一部を開く」機能で「読み
込む範囲を指定する」を
ONにして「位置」を最小に、「サイズ」を最大にして開きました。

 1. 「表示」メニューやステータスバーの「文字数計算」機能。
    「文字列」ダイアログの全ての項目を「1文字分」にしたとき、結果が
    -1794967296
    と誤った値になってしまいます。まるで符号付32bit整数がオーバーフローした
ような
    結果となっています。
   
    本来、文字数のようなファイルの巨大化に伴って極めて大きくなりうる数値には、
    「符号無し64bit整数」や「倍精度浮動小数点数」などの桁数に余裕のある数値型を
    用いるべきなのですが、文字数処理が内部では本当に符号付32bit整数で行われ
てしまって
    いるような気がします。

 2. マクロのcharcount()関数。
    以下のように整数モードと浮動小数点数モードでそれぞれ1文字分と2文字分で計
算しました。
   
    debuginfo 2 ;
    setfloatmode 0 ;
    debuginfo @"[IntegerMode]" + "\U0000000A" ;
    debuginfo @"X1=" + str( charcount( 0x00000000 ) ) + "\U0000000A" ;
    debuginfo @"X2=" + str( charcount( 0x00111111 ) ) + "\U0000000A" ;
    setfloatmode 1 ;
    debuginfo @"[FloatMode]" + "\U0000000A" ;
    debuginfo @"X1=" + str( charcount( 0x00000000 ) ) + "\U0000000A" ;
    debuginfo @"X2=" + str( charcount( 0x00111111 ) ) + "\U0000000A" ;
    endmacro ;
   
    実行結果は以下の通りです
   
    [IntegerMode]
    X1=-1794967296
    X2=705032704
    [FloatMode]
    X1=2500000000
    X2=705032704
   
    整数モードでは、1文字分と2文字分との両方でオーバーフローが見られますが、
元々整数モードでの
    数値変数は符号付32bit整数であるので、これは正しい動作であるようです。一
方、浮動小数点数モードでは
    1文字分の方は正しい値となっていますが、2文字分の方は本来
    5000000000
    となるべきところが、なぜか整数モードの2文字分と同じ値になってしまってい
ます。条件次第で
    浮動小数点数モードが勝手に解除されてしまうみたいです。

バージョンはv8.98β9 Float x64です。


[ ]
RE:10435 [不具合]文字数カウントNo.10436
でるもんたいいじま さん 21/05/26 17:34
 
でるもんた・いいじまです。

> さて、文字数カウント機能において誤った文字数が返される問題が見つかりました。
>
> テストに使ったファイルは、
> 1行の書式  : U+002Aが2499個連続 + 改行コードLF
> 行数       : 1000000行
> 文字コード : Shift-JIS
> の2500000000文字、2500000000Byteです。

1行が改行コミで2500バイト、行数が100万、EOF文字はないとして合計2.5億バイトで
すね。

ちなみにこちらは訳あって32bit版の秀丸ですが、こちらでもユーザー空間3GBをフル
に使えるようですね。設定で128MBになっていたので、一時的に3000MBに上げてみま
した。

…読むだけで相当に重いです^^

#あと、最大1000万行(64bit版は1億行)の制限って、
#物理行数(画面上の行数)でカウントするんですね。
#これも歴史を感じます。

> 文字数処理が内部では本当に符号付32bit整数で行われて
> しまっているような気がします。

ですね。
…まあ、こういうものは一つずつ地道に潰していくしかないでしょう。

#そういう作業に興味がある人たちだけのML作りますか?
#ちょうど、turukame.8とturukame.9が未使用のまま空いていますし、
#あるいは、turukame.1の今の内容をHTMLにアーカイブしてから
#まっさらにして使い回してもいいですし。

☆ ☆ ☆

以下は釈迦に説法。

☆ ☆ ☆

旧版のVCにいつから uint64_t があるかは確認していませんが、昔からVC独自の組み
込み型として__int64、__uint64がありますので(Win32初対応となるVC4.0の時点か
ら既にあったと思う)、VCのバージョンが古くても64bit化は難しくないと思います。

#つまり、イマドキの通例なら #include<stdint.h> の1行で済む内容のうち、
#秀丸に必要な部分だけをうまく再発明すればいいだけのことです。

#逆に、あえて再発明することで「このパラメータは32bit縛りが仕様」
#「このパラメータは完全64bit化済」という情報が、ごく少数のヘッダ
#ファイルに集約されます。うまくやれば、型名の不一致を検出して
#ビットあふれの可能性を予測、なんてこともできるかもしれませんし。

> 本来、文字数のようなファイルの巨大化に伴って極めて大きくなりうる数値には、
> 「符号無し64bit整数」や「倍精度浮動小数点数」などの桁数に余裕のある数値型を
> 用いるべきなのですが、

今回は64bitですかね。64bit型がない時代の環境ならdoubleやむなしですが、double
は53bitしか有効数字がないので、長期的には不安です。
(たとえば今のご時世で、一般の個人や零細企業などが自前で持てるストレージはせ
いぜい100TBくらいでしょうけど、YouTubeあたりのデータ総量はもしかしたら既に64
bitの範囲を超えているかもしれません。)

それに、文字数まわりの計算はすべて整数演算(一部に1/2を含みますが)なので、d
oubleだと無駄な型変換が起きてデメリットしかないです。

[ ]
RE:10436 [不具合]文字数カウントNo.10437
秀丸担当 さん 21/05/26 18:13
 

文字数計算のダイアログ等については確かにその通りでした。
できるように対応していこうと思います。

マクロについては、setfloatmode 0;のときは通常版と同じであったほうがよくて、3
2bitの正の数の上限までの制限にしたほうがいいかもしれません。
setfloatmode 1;のときで動作を変えるべきかというのは微妙で、全部合わせたほう
がいい気もしますが、とりあえずそもそも可能かどうか試してみて検討します。

[ ]
RE:10437 [不具合]文字数カウントNo.10438
こみやんま さん 21/05/26 18:31
 
この辺 int しか想定してないのたくさんあると思いますねぇ。
linenoやcolumnなども int までになってるだろうし...

C関数としてexternしてしまってるものにもそういったものも含まれてるので、なか
なかですねこの辺は。

[ ]
RE:10437 [不具合]文字数カウントNo.10439
fzok4234 さん 21/05/26 23:15
 
マクロ仕様において破壊的変更を伴わずに正式に64bit整数をサポートする方法とし
て、通常の32bit数値変数を
2個使って64bit整数の代わりとする方法を用いてもよいのでは、と思いました。つま
り、64bitのうち0〜31bitの
下位32bitと32〜64bitの上位32bitの2個の独立した数値変数で1つのペアとすること
です。この場合、新たに以下の
例のような文/関数を新設して演算処理などを行うことになるでしょう。

四則演算。
単項+ (文) : unaryplusint64 #lower, #upper, #lowerReturn, #upperReturn ;
単項- (文) : negateint64    #lower, #upper, #lowerReturn, #upperReturn ;
+     (文) : addint64       #lowerleft, #upperleft, #lowerright, #upperright,
 #lowerReturn, #upperReturn ;
-     (文) : subtractint64  #lowerleft, #upperleft, #lowerright, #upperright,
 #lowerReturn, #upperReturn ;
*     (文) : multiplyint64  #lowerleft, #upperleft, #lowerright, #upperright,
 #lowerReturn, #upperReturn ;
/     (文) : divideint64    #lowerleft, #upperleft, #lowerright, #upperright,
 #lowerReturn, #upperReturn ;
%     (文) : moduloint64    #lowerleft, #upperleft, #lowerright, #upperright,
 #lowerReturn, #upperReturn ;

bit操作。
^ (文) : notint64 #lower, #upper, #lowerReturn, #upperReturn ;
| (文) : orint64  #lowerleft, #upperleft, #lowerright, #upperright, #lowerRe
turn, #upperReturn ;
& (文) : andint64 #lowerleft, #upperleft, #lowerright, #upperright, #lowerRe
turn, #upperReturn ;

比較。戻り値は1か0。
<= (関数) : #result = lessthanorequalint64(    #lowerleft, #upperleft, #lowe
rright, #upperright ) ;
>= (関数) : #result = greaterthanorequalint64( #lowerleft, #upperleft, #lowe
>rright, #upperright ) ;
<  (関数) : #result = lessthanint64(           #lowerleft, #upperleft, #lowe
rright, #upperright ) ;
>  (関数) : #result = greaterthanint64(        #lowerleft, #upperleft, #lowe
>rright, #upperright ) ;
!= (関数) : #result = notequalint64(           #lowerleft, #upperleft, #lowe
rright, #upperright ) ;
=  (関数) : #result = equalint64(              #lowerleft, #upperleft, #lowe
rright, #upperright ) ;

変換。
Int32=>Int64        (文)   : int32toint64 #int32, #lowerReturn, #upperReturn ;
Int64=>Int32        (関数) : #int32 = int64toint32( #lower, #upper ) ;
文字列=>Int64       (文)   : valint64 $str, #lowerReturn, #upperReturn ;
Int64=>10進数文字列 (関数) : $dec = strint64( #lower, #upper ) ;
Int64=>16進数文字列 (関数) : $hex = hexint64( #lower, #upper ) ;

文字数。
文字数計算      (文) : charcountint64       #mode, #lowerReturn, #upperRetur
n ; // #modeはcharcount( n1 ) 関数のn1と同じ。
文字位置=>行/桁 (文) : positiontolinecolumn #lowerposition, #upperposition,
#lowerlineReturn, #upperlineReturn, #lowercolumnReturn, #uppercolumnReturn ;
行/桁=>文字位置 (文) : linecolumntoposition #lowerline, #upperline, #lowerco
lumn, #uppercolumn, #lowerpositionReturn, #upperpositionReturn ;

カーソル。
x             (文) : xint64            #lowerReturn, #upperReturn ;
y             (文) : yint64            #lowerReturn, #upperReturn ;
column        (文) : columnint64       #lowerReturn, #upperReturn ;
lineno        (文) : linenoint64       #lowerReturn, #upperReturn ;
tabcolumn     (文) : tabcolumnint64    #lowerReturn, #upperReturn ;
xview         (文) : xviewint64        #lowerReturn, #upperReturn ;
prevposx      (文) : prevposxint64     #lowerReturn, #upperReturn ;
prevposy      (文) : prevposyint64     #lowerReturn, #upperReturn ;
mousecolumn   (文) : mousecolumnint64  #lowerReturn, #upperReturn ;
mouselineno   (文) : mouselinenoint64  #lowerReturn, #upperReturn ;
columntox     (文) : columntoxint64    #lowerc, #upperc, #lowerl, #upperl, #
lowerReturn, #upperReturn ;
linenotoy     (文) : linenotoyint64    #lowerc, #upperc, #lowerl, #upperl, #
lowerReturn, #upperReturn ;
xtocolumn     (文) : xtocolumnint64    #lowerx, #upperx, #lowery, #uppery, #
lowerReturn, #upperReturn ;
ytolineno     (文) : ytolinenoint64    #lowerx, #upperx, #lowery, #uppery, #
lowerReturn, #upperReturn ;
up            (文) : upint64           #lower, #upper ;
down          (文) : downint64         #lower, #upper ;
right         (文) : rightint64        #lower, #upper ;
left          (文) : leftint64         #lower, #upper ;
shiftup       (文) : shiftupint64      #lower, #upper ;
shiftdown     (文) : shiftdownint64    #lower, #upper ;
shiftright    (文) : shiftrightint64   #lower, #upper ;
shiftleft     (文) : shiftleftint64    #lower, #upper ;
moveto        (文) : movetoint64       #lowerx, #upperx, #lowery, #uppery ;
movetoview    (文) : movetoviewint64   #lowerx, #upperx, #lowery, #uppery ;
movetolineno  (文) : movetolinenoint64 #lower桁番号, #upper桁番号, #lower行
番号, #upper行番号 ;
moveto2       (文) : moveto2int64      #lowercolumn, #uppercolumn, #lowerlin
eno, #upperlineno ;

テキスト。
linecount  (文)   : linecountint64  #lowerReturn, #upperReturn ;
linecount2 (文)   : linecount2int64 #lowerReturn, #upperReturn ;
linelen    (文)   : linelenint64    #lowerReturn, #upperReturn ;
linelen2   (文)   : linelen2int64   #lowerReturn, #upperReturn ;
gettext    (関数) : $str = gettextint64(  #lowerx1, #upperx1, #lowery1,#uppe
ry1, #lowerx2, #upperx2, #lowery2, #uppery2, #n1 [ , #n2 ] ) ;
gettext2   (関数) : $str = gettext2int64( #lowerc1, #upperc1, #lowerl1,#uppe
rl1, #lowerc2, #upperc2, #lowerl2, #upperl2, #n1 [ , #n2 ] ) ;

範囲選択。
seltopx      (文) : seltopxint64       #lowerReturn, #upperReturn ;
seltopy      (文) : seltopyint64       #lowerReturn, #upperReturn ;
selendx      (文) : selendxint64       #lowerReturn, #upperReturn ;
selendy      (文) : selendyint64       #lowerReturn, #upperReturn ;
seltopcolumn (文) : seltopcolumnint64  #lowerReturn, #upperReturn ;
seltoplineno (文) : seltoplinenoint64  #lowerReturn, #upperReturn ;
selendcolumn (文) : selendcolumnint64  #lowerReturn, #upperReturn ;
selendlineno (文) : selendlinenoint64  #lowerReturn, #upperReturn ;
selopenx     (文) : selopenxint64      #lowerReturn, #upperReturn ;
selopeny     (文) : selopenyint64      #lowerReturn, #upperReturn ;

クリップボード。
selectcolumn (文) : selectcolumnint64 #lower区切り1, #upper区切り1, #lower区
切り2, #upper区切り2 [ , #lower行1, #upper行1, #lower行2, #upper行2 ] ;

ウィンドウ。
screentopy  (文) : screentopyint64  #lowerReturn, #upperReturn ;
screenleftx (文) : screenleftxint64 #lowerReturn, #upperReturn ;

検索。
foundtopx           (文) : foundtopxint64           #lowerReturn, #upperRetu
rn ;
foundtopy           (文) : foundtopyint64           #lowerReturn, #upperRetu
rn ;
foundendx           (文) : foundendxint64           #lowerReturn, #upperRetu
rn ;
foundendy           (文) : foundendyint64           #lowerReturn, #upperRetu
rn ;
colormarker         (文) : colormarkerint64         #文字色, #背景色, #スタ
イル, #種類, #ユーザーデータ, $レイヤー名, #lower開始行, #upper開始行, #lowe
r開始桁, #upper開始桁, #lower終了行, #upper終了行, #lower終了桁, #upper終了桁 ;
deletecolormarker   (文) : deletecolormarkerint64   $レイヤー名, #ユーザー
データ, #lower開始行, #upper開始行, #lower開始桁, #upper開始桁, #lower終了行,
 #upper終了行, #lower終了桁, #upper終了桁 ;
colormarkerallfound (文) : colormarkerallfoundint64 #文字色, #背景色, #スタ
イル, #種類, #ユーザーデータ, $レイヤー名, #lower開始行, #upper開始行, #lowe
r開始桁, #upper開始桁, #lower終了行, #upper終了行, #lower終了桁, #upper終了桁 ;
colormarkersnapshot (文) : colormarkersnapshotint64 #lower開始行, #upper開始
行, #lower開始桁, #upper開始桁, #lower終了行, #upper終了行, #lower終了桁, #u
pper終了桁, $レイヤー名 ;

設定。
width     (文) : widthint64     #lowerReturn, #upperReturn ;
formwidth (文) : formwidthint64 #lowerReturn, #upperReturn ;

レジストリ。
writeininum  (文) : writeininumint64  $INIファイル名, $セクション名, $キー名,
 #lower, #upper ;
writeininumw (文) : writeininumwint64 $INIファイル名, $セクション名, $キー名,
 #lower, #upper ;
getininum    (文) : getininumint64    $INIファイル名, $セクション名, $キー名,
 #lowerReturn, #upperReturn ;
getininumw   (文) : getininumwint64   $INIファイル名, $セクション名, $キー名,
 #lowerReturn, #upperReturn ;
writeregnum  (文) : writeregnumint64  $値の名前, #lower, #upper ;          
  // REG_QWORD値用。
getregnum    (文) : getregnumint64    $値の名前, #lowerReturn, #upperReturn
 ; // REG_QWORD値用。

アウトライン。
rangeedittop     (文) : rangeedittopint64     #lowerReturn, #upperReturn ;
rangeeditend     (文) : rangeeditendint64     #lowerReturn, #upperReturn ;
outlineitemcount (文) : outlineitemcountint64 #lowerReturn, #upperReturn ;

マクロ制御。
enabledraw  (文) : enabledrawint64 #lowery, #uppery, #lowerx, #upperx ;

※パラメーターの#lower〜は下位32bit、#upper〜は上位32bit、〜Returnは出力値を
受け取る変数。

この例は主に文字数や文字の座標(lineno/columnなど)を64bit化した場合に、既存の
文/関数/キーワードと
同等のものを用意したものです。命名は既存のものに末尾にint64を付けています。
また、元々1個の数値を
返していた関数/キーワードは一度に#lower〜と#upper〜との2値を返さないといけな
いため、getlinecount()の
nReturnと同様な参照渡しパラメーターで値を受け取る文として再定義しました。

これはあくまで当方で思いついた一例ですので、もっとスマートな方法があるかもし
れません。


[ ]
RE:10437 [不具合]文字数カウントNo.10440
fzok4234 さん 21/05/26 23:28
 
> setfloatmode 1;のときで動作を変えるべきかというのは微妙で、全部合わせたほ
>うがいい気も
> しますが、とりあえずそもそも可能かどうか試してみて検討します

とりあえず、当面は浮動小数点数モードを「32bitの壁」を突破する手段として利用
できるように
整備を進めることが賢明な解決法かもしれません。


[ ]
RE:10440 [不具合]文字数カウントNo.10441
こみやんま さん 21/05/26 23:59
 
自分はめったに反対意見は言わないんですが、
さすがに、32bitのマクロ空間に64bit整数用命令や仕組みを大量投入というのは反対
です。

多くのスクリプト言語も32bit版はnumberは32bitですし、
ほぼ全てのメソッドもその「32bit版なら32bitの範囲でやりとりされる」よう実装さ
れています。
64bit版秀丸もあるので、64bit変数が必要な人は64bit使え
という感じの切り分けでいいかと思います。

(まぁトップクラスの流行のpythonがデフォルトの整数型が「無限桁数」で32bitも64
bitも数値範囲かわらんし無限というすごい状態ですがw)

ただ、**64bit版秀丸なのに**、「この変数64bitまで行く可能性がそこそこあるのに
32bitでのやりとり」になってるよね? とかいう箇所があるのであれば、
そこはピンポイントで「64bit版では、64bit整数」を返した方がいいんじゃないです
か、ぐらいですね。

[ ]
RE:10441 [不具合]文字数カウントNo.10442
fzok4234 さん 21/05/27 03:48
 
> 自分はめったに反対意見は言わないんですが、
> さすがに、「32bitのマクロ空間」に64bit整数用命令や仕組みを大量投入というの
>は反対です。
>
> 多くのスクリプト言語も「32bit版」はnumberは32bitですし、
> ほぼ全てのメソッドもその「32bit版なら32bitの範囲でやりとりされる」よう実装
>されています。
> 「64bit版秀丸」もあるので、64bit変数が必要な人は64bit使え
> という感じの切り分けでいいかと思います。
>
> ただ、**64bit版秀丸なのに**、「この変数64bitまで行く可能性がそこそこあるの
>に32bitでのやりとり」に
> なってるよね? とかいう箇所があるのであれば、
> そこはピンポイントで「64bit版では、64bit整数」を返した方がいいんじゃないで
>すか、ぐらいですね。

問題の本質はまさにこの「64bit版秀丸エディタなのに32bitの壁に阻まれている。」
ということであります。

初めから「32bit版秀丸エディタ」を使っていて文字数などのオーバーフローに直面
するのは「当然のこと」であり、
この狭いマクロ空間で「64bit整数用命令や仕組み」を求めるのは「水の中に火を、
火の中に水を」求めるが如く
ナンセンスなことであります。まさに、
・さすがに、「32bitのマクロ空間」に64bit整数用命令や仕組みを大量投入というの
は反対です。
・ほぼ全てのメソッドもその「32bit版なら32bitの範囲でやりとりされる」よう実装
されています。
という感じです。

しかし、今度の舞台はまさしく「64bit版秀丸エディタ」であり、この「広いはずの
マクロ空間」で64bit整数用命令や
仕組みの大量投入を求めていくことは間違っているとは言えません。だが残念なこと
に、この「一見広く見えるマクロ空間」の
実態は昔の32bit全盛期に作られた「狭い32bitのマクロ空間」をそのまま移植したも
のであったわけです。その理由は、
・ソースレベルで32bitの変数やメソッドの実装を全て64bit化するには多大なコスト
がかかること。
・下位互換性を維持して既存のマクロやDLLの正常動作を保証するため。
であり、決して悪いことではありません。

でもやはり、OSやファイルシステムの64bit版が主流となり、これに合わせて扱うコ
ンテンツも大容量化してきた
今日においては、この「狭い32bitのマクロ空間」は時代遅れの過去の遺物となって
いて、真の意味で広いマクロ空間へと
「リフォーム」すべき時が来ているのではないかと思います。では、この「リフォー
ム」はどのように行われるべきかと
いえば、それは
・1つのマクロ空間上に32bit用命令/仕組みと64bit用命令/仕組みとが同居可能にする。
ことに尽きるはずです。つまり、
・従来の32bit用命令/仕組みを温存したまま新たに64bit用命令/仕組みを追加する。
ということになります。もちろんこれは、素質として64bitの広さを持った「64bit版
秀丸エディタ」限定であり、
これ以上広くできない「32bit版秀丸エディタ」は対象外です。

ここで1つ問題があります。それは、マクロの変数の型は「数値」と「文字列」の2種
類しかないことです。この2種類だけで
従来の「32bit整数」、「倍精度浮動小数点数(Float版秀丸エディタのみ)」、「Unic
ode文字列」に加えて新たに
「64bit整数」を表現しないといけません。そのための方法として思いつくいくつか
の案には次のようなものがあります。
1.「数値」は単独で32bit整数のままだが、これを2個で1組として64bit整数を表現す
る。この2個1組の数値をやり取り
  する文/関数を追加して実装する。先ほど具体例を挙げたやり方。
2.setfloatmode文を使って「数値」の内部形式自体を切り替える。従来は
  setfloatmode 0; で32bit整数となり、
  setfloatmode 1; で倍精度浮動小数点数となっていたが、これに加えて
  setfloatmode 2; で64bit整数する「64bitモード」を新設する。まさに
  ・そこはピンポイントで「64bit版では、64bit整数」を返した方がいいんじゃない
ですか。
  という感じである。
3.「文字列」に@"0x0F1E2D3C4B5A6978"といった桁数固定の16進数文字列を格納して6
4bit整数を表現する。この16進数値を
  やり取りする文/関数を追加して実装する。
4.メモリ上に置かれた64bit整数オブジェクトの実体を識別する「ハンドル値」を32b
it整数の「数値」で取り扱う。
  loaddll()でロードしたDLLやcreateobject()で作成したCOMオブジェクト、hidemar
uhandle()で取得するウィンドウなどと
  同じノリで専らハンドルを介して64bit整数オブジェクトを操作する。このハンド
ルをやり取りする文/関数を追加して実装する。
いずれも、現行の64bit版秀丸エディタとの下位互換性を考慮してのことです。


[ ]
RE:10442 [不具合]文字数カウントNo.10443
でるもんたいいじま さん 21/05/27 06:08
 
でるもんた・いいじまです。

> 問題の本質はまさにこの「64bit版秀丸エディタなのに32bitの壁に
> 阻まれている。」ということであります。

まあ、それはわかります。

ただ、fzok4234さん以外の他にだれも「秀丸を大々的に現代化すべきだ」という意見
が出ないのは、ハッキリ言ってしまえばfzok4234さんが「秀丸にそれを求めるという
ことがもともと無茶な案件を次から次へと、しかも大上段の態度で要求し続けている
から」だと考えます。

それだけの膨大な開発資金なんて、はっきり言ってしまえばサイトー企画さんが調達
するつもりはないでしょう。それに、仮にその資金で人員を確保して作業したとして
も、品質の劣化と既存客離れを招くだけ、と私は見込んでいます。

(秀まるおさん・担当さんレベルの優秀なエンジニアって、日本中どこを探してもな
かなか見つからないですよ。私ならそのクラスの人材をフルタイムで雇えるなら年俸
1億でも激安だと考えます。)

そもそも秀丸はたった15MBの小型アプリ、開発元も資本金300万円の零細企業(スタ
ッフ数もひと桁のはずです)です。そこに対して「資本金200億円・スタッフ数4桁
(もしかしたら5桁以上?)の巨大企業とタイマン張ってガチンコ勝負しろ」と吹っ
掛けている、この無謀な要求こそがfzok4234さんの今までの一貫した無茶振りの正体
です。

> でもやはり、OSやファイルシステムの64bit版が主流となり、
> これに合わせて扱うコンテンツも大容量化してきた今日においては、

うーむ。今は64bit環境といえどもまだ、GB単位のデータをユーザが可変長データス
トリーム用のテキストエディタで簡単に編集できる時代だとは思いませんけどね。
たとえば、長大なJSONデータに細かいパッチを当てたい、みたいなケースでテキスト
エディタを迂闊に使うと文法エラーを起こしかねませんから、そういうものは専用の
編集ツールが筋です。

まあ私でも、自作のスクリプト上でなら100MBくらいのテキストデータは平気で扱う
ことがありますけど。

> ・従来の32bit用命令/仕組みを温存したまま新たに64bit用命令/仕組みを追加する。
> ということになります。もちろんこれは、素質として64bitの広さを持った
> 「64bit版秀丸エディタ」限定であり、
> これ以上広くできない「32bit版秀丸エディタ」は対象外です。

32bit版の秀丸エディタでメモリ空間をこれ以上広げられない件と、現状で64bit整数
演算ができない件とは全く無関係ですが?64bit整数演算を実装するだけなら32bitの
秀丸にも十分に導入可能です。

> 1.「数値」は単独で32bit整数のままだが、これを2個で1組として
> 64bit整数を表現する。この2個1組の数値をやり取りする文/関数を
> 追加して実装する。先ほど具体例を挙げたやり方。

これは絶対に反対です。可読性が著しく落ちます。
無限倍長整数四則演算のコードを、C++ではなくフルアセンブラで再発明しようと挑
戦してみればそのしんどさが分かるはずです。

そもそも、たとえばZ80の時代には、環境によっては単純な「8bit×8bit→16bit」の
掛け算すらアセンブラで書かなきゃいけなかったんですよ?その時代の苦労が想像で
きますか?
(時代が下るとZ80でもC言語が普及してきて、そういう基本的な計算はランタイムラ
イブラリを呼ぶだけで済むようになりましたけどね。)

> 2.setfloatmode文を使って「数値」の内部形式自体を切り替える。従来は
>   setfloatmode 0; で32bit整数となり、
>   setfloatmode 1; で倍精度浮動小数点数となっていたが、これに加えて
>   setfloatmode 2; で64bit整数する「64bitモード」を新設する。

これは確かに検討に値すると思います。
でもそうすると、いま整数版と浮動小数点版に分かれているパッケージを後者のみに
統一する、ということになりますね。実現性をしっかり検討してみたいとこです。

> 3.「文字列」に@"0x0F1E2D3C4B5A6978"といった桁数固定の16進数文字列を
> 格納して64bit整数を表現する。この16進数値をやり取りする文/関数を
> 追加して実装する。

これは反対。「+」演算子が期待通りに働きません。

☆ ☆ ☆

もうひとつ、私からも別の提案です。

「64bit整数型の変数には、既存の #、$ とは別のprefixをつけて区別する。」
ASCII文字の中て、1文字で新規のプレフィックスとして使えそうな記号は @ ` _ く
らいしかありませんが、C言語の L'あ' や L"abc" あたりからの類推で L#abc、Q#ab
c あたりを検討してみてもいいと思います。あと、#_abc は現状、有効な変数名なん
でしたっけ?

いかがでしょう。

[ ]
RE:10442 [不具合]文字数カウントNo.10444
こみやんま さん 21/05/27 09:13
 
現在の秀丸エディタ64bit版のマクロ変数や関数の整数精度はすでに64bit幅ですよね?

何を解決しようとしているのかよくわからない...


現在の秀丸エディタ64bit版の整数精度が32bitであるかのような提案がなされている
ように思えます。

[ ]
RE:10443 [不具合]文字数カウントNo.10445
秀丸担当 さん 21/05/27 09:17
 

64bitでも扱えるようにできたらいいということで、各種の文や関数を大量に作ると
いうのは大変そうです。
setfloatmode 2;
でできたら、いろいろ合理的でいいかもしれないです。
どんな困難があるかやってみないとわかないこともあると思いますが、うまくいけば
32bit版floatでも64bit整数を扱えるように統一できるようになるかもしれません。
V9のネタにするか、作ったとしてもそんなに使う人はいない気もするので、最近はよ
くあるパターンで正式版でも特定機能はベータとかExperimentとかいう扱いで置いて
おくのでもいいかもしれないです。

[ ]
RE:10444 [不具合]文字数カウントNo.10446
秀丸担当 さん 21/05/27 09:51
 

これはヘルプにちゃんと書いていないのがいけないのですが、64bit版の浮動小数点
数版では、setfloatmode 0;の状態で32bitの整数の扱いになってしまうということが
あります。
そのあたりもヘルプに書いておきます。
いろいろ歴史的経緯と内部事情があるのですが、もともと32bit通常版と浮動小数点
数版は、int(32bit)とdouble(仮数部52bit)になっていて、setfloatmode 0;ではdoub
leをintに変換していました。
一方で64bit版ができて、64bit通常版は64bit格納できても、64bit浮動小数点数版は
やっぱりdouble(仮数部52bit)なので、64bit整数は扱えないです。
そのため、setfloatmode 0;の状態で通常版と同じになる、というのは、浮動小数点
数版においては32bitになってしまいます。
それで、setfloatmode 2;でとにかく64bit整数にできたら全部統一できて合理的にな
る可能性があります。

[ ]
RE:10446 [不具合]文字数カウントNo.10447
こみやんま さん 21/05/27 10:00
 
ああ、
64bit整数版は問題なく64bitで動作するものの、
64bit版の浮動小数版の精度がdoubleのまま、intが32bitで精度が足りてないんですね。

それはおっしゃるように、モードを追加し、
64bit整数モード(浮動小数あきらめる)で、64bit(ノーマル版)相当の動きにすれば
よいかと思います。

[ ]
RE:10443 [不具合]文字数カウントNo.10450
fzok4234 さん 21/05/27 13:35
 
> ただ、fzok4234さん以外の他にだれも「秀丸を大々的に現代化すべきだ」という意
>見が出ないのは、
> ハッキリ言ってしまえばfzok4234さんが「秀丸にそれを求めるということがもとも
>と無茶な案件を
> 次から次へと、しかも大上段の態度で要求し続けているから」だと考えます。
>
> それだけの膨大な開発資金なんて、はっきり言ってしまえばサイトー企画さんが調
>達するつもりは
> ないでしょう。それに、仮にその資金で人員を確保して作業したとしても、品質の
>劣化と既存客離れを
> 招くだけ、と私は見込んでいます。
>
> (秀まるおさん・担当さんレベルの優秀なエンジニアって、日本中どこを探しても
>なかなか見つからないですよ。
> 私ならそのクラスの人材をフルタイムで雇えるなら年俸1億でも激安だと考えます。)
>
> そもそも秀丸はたった15MBの小型アプリ、開発元も資本金300万円の零細企業(ス
>タッフ数もひと桁の
> はずです)です。そこに対して「資本金200億円・スタッフ数4桁(もしかしたら5
>桁以上?)の巨大企業と
> タイマン張ってガチンコ勝負しろ」と吹っ掛けている、この無謀な要求こそがfzok
>4234さんの今までの
> 一貫した無茶振りの正体です。

確かに、
・VS Code
を開発する天下のMicrosoftと対峙することは「戦車に竹槍で応戦」するが如く「無
謀」なことだと思います。
しかし、これが
・サクラエディタ
・Notepad++
・Mery
などの個人や零細コミュニティが開発するものとなれば、比較的「同じ土俵」で対峙
しているといえます。
これらの零細エディタ陣営側の機能紹介を見ていると、
・オープンソースかつ無料。
・Unicode化や64bit化のために1から書き直す。
・古いOSのサポートをバッサリ切る。
などのなかなか強かな戦法を取ってきたりしています。油断していると、先にLangua
ge Server Protocolなど
を実装されるなどの遅れをとる恐れもあります。

> 32bit版の秀丸エディタでメモリ空間をこれ以上広げられない件と、現状で64bit整
>数演算ができない件とは
> 全く無関係ですが?64bit整数演算を実装するだけなら32bitの秀丸にも十分に導入
>可能です。

基本的に秀丸エディタはWindows APIを直に叩くアンマネージドC/C++で書かれている
以上、32bit版秀丸エディタで
64bitの整数演算やAPIに対応することは複雑なトリックを使用するためにかなりの大
改修となり、それこそ
「開発元も資本金300万円の零細企業(スタッフ数もひと桁のはずです)に対する無
謀な要求」になってしまいそうです。
逆に、64bit版秀丸エディタで64bitの整数演算やAPIに対応することはそれほど大き
なコストはかからないと
思われます。

> もうひとつ、私からも別の提案です。
>
> 「64bit整数型の変数には、既存の #、$ とは別のprefixをつけて区別する。」
> ASCII文字の中て、1文字で新規のプレフィックスとして使えそうな記号は @ ` _
>くらいしかありませんが、C言語の L'あ' や L"abc" あたりからの類推で L#abc、Q
>#abc あたりを検討してみてもいいと思います。あと、#_abc は現状、有効な変数名
>なんでしたっけ?
>
> いかがでしょう。

やはり、最終的にはこのような「マクロの文法自体の改修」が理想的かと思われます。


[ ]
RE:10450 [不具合]文字数カウントNo.10451
こみやんま さん 21/05/27 13:51
 
Language Server Protocol というのは、ローカルで利用できる言語サーバーとして
共有されているものを、比較的簡素なプログラムで利用できるものになっています。

例えば、いつ頃だったか軽くつくってみたものでは、
https://xn--pckzexbx21r8q9b.net/?page=nobu_tool_hm_ts_intellisense

が秀丸でLanguage Server Protocol を利用しているもので、
JavaScriptがリアルタイムにTypeScript級の型分析がなされています。


利用する側(サイトー企画も利用する側になりますね)実装自体は比較的簡単ですが、
いままで外部API
(Web APIもそうだし、この場合ローカルのnodeに依存することにもなる)に依存はで
きるだけ回避する方針で開発されている様子がありますので、
この辺をサイトー企画さん側で実装するのは難しいかなぁと思っています。

マンパワー的にも、Language Protocol Serverを使ったモジュールを秀丸上で実装す
るのに欠けているAPIを秀丸から提供し、
それを利用してエディタ取り巻きがモジュールを作り上げるのが良いのですが、
v8.66だったかv8.73あたりでその辺を結構強く希望したのですが、
入力補完候補への(マクロを経由しない)割り込みを認められませんでした。
(これらが認められないと安心して配布できるモジュールとしては作りがたいです)

(強引に「そのレベルで割り込む?」というプログラムをかけば
 https://xn--pckzexbx21r8q9b.net/?page=nobu_tool_hm_autocompleteex
 みたいに入力補完にいきなり割り込むことはできますが、
 まぁ正道ではないよねっていう...)

[ ]
RE:10445 [不具合]文字数カウントNo.10452
fzok4234 さん 21/05/27 14:54
 
整数のオーバーフローについて調べてみると、
JPCERT : https://www.jpcert.or.jp/sc-rules/c-int32-c.html
IPA    : https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c907.html
といった公的機関により「セキュリティ上の脆弱性」とみなされているようで、これ
を放置することは
あまり良くないことという印象を受けました。

今回は「文字数ダイアログ」という比較的深刻度の小さいことで問題が顕在化しまし
たが、これ以外にも
ユーザーの目に見えない部分で存在しているかもしれません。特に文字数や文字イン
デックス番号、
行/桁に依存する部分で今後問題が生ずる可能性も考えられます。最悪、
・巨大ファイルを悪用して任意の悪意あるコードを実行する。
ような輩が出没するかもしれません。

それからマクロ上でのことですが、試しに

debuginfo 2 ;
debuginfo @"[0x7FFFFFFE + 1]" + "\U0000000A" ;
#number = 0x7FFFFFFE + 1 ;
#result = result ;
debuginfo @"Number=" + str( #number ) + "\U0000000A" ;
debuginfo @"Result=" + str( #result ) + "\U0000000A" ;
debuginfo @"[0x7FFFFFFF + 1]" + "\U0000000A" ;
#number = 0x7FFFFFFF + 1 ;
#result = result ;
debuginfo @"Number=" + str( #number ) + "\U0000000A" ;
debuginfo @"Result=" + str( #result ) + "\U0000000A" ;
endmacro ;

を実行すると、結果は

[0x7FFFFFFE + 1]
Number=2147483647
Result=0
[0x7FFFFFFF + 1]
Number=-2147483648
Result=0

となってresultキーワードでは整数オーバーフローを捕捉できないことがわかりまし
た。

このことから提案があるのですが、マクロ開発者が各自で整数オーバーフロー対策を
行いやすいように
自動でチェックを行う動作モードを新設する、というのはどうでしょうか。すなわち、
setoverflowcheckmode文
なるものを用意して、整数オーバーフローが起きたらエラーとして捕捉できるように
するモードを
有効にできるようにすることです。例えば、
setoverflowcheckmode 0 ; // 従来の動作と同じで何もチェックしない。
setoverflowcheckmode 1 ; // getresultex()関数で捕捉する。
setoverflowcheckmode 2 ; // 実行時エラーとして直ちに処理を停止する。
という感じです。


[ ]
RE:10452 [不具合]文字数カウントNo.10453
でるもんたいいじま さん 21/05/27 15:40
 
でるもんた・いいじまです。

> 整数のオーバーフローについて調べてみると、
> JPCERT : https://www.jpcert.or.jp/sc-rules/c-int32-c.html
> IPA    : https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c907.html
> といった公的機関により「セキュリティ上の脆弱性」とみなされているようで、
> これを放置することは
> あまり良くないことという印象を受けました。

リンク先を読んでいない(し、まず間違いなくfzok4234さんの曲解なのでわざわざ読
む必要も感じない)のですが、「どんな場合でも」32bit(あるいは64bit)の境界を
溢れる整数演算は悪である、という主張には強く異議を申し述べておきます。

そもそも、Pythonならともかくアセンブラあたりだと、桁溢れを意図的に起こさない
ことには整数演算のロジック自体が成立しません。

> resultキーワードでは整数オーバーフローを捕捉できないことがわかりました。

当然です。

> このことから提案があるのですが、マクロ開発者が各自で整数オーバーフロー
> 対策を行いやすいように自動でチェックを行う動作モードを新設する、
> というのはどうでしょうか。すなわち、
> setoverflowcheckmode文
> なるものを用意して、

そうすると「 & 0x80000000」みたいなビット演算を文法レベルで禁止しないと意味
がないですね。x86/x64アーキテクチャ的にも面倒ですし、効率的に実装しようとす
ればC言語の中に大量のインラインアセンブラが混入することにもなりかねないので、
反対します。

☆ ☆ ☆

繰り返します。
「ご自身も含めて誰も使わないもの」を大量でタダで作れという要求はそろそろやめ
てください。
それにあなたは秀丸のセールス&マーケティング責任者でも何でもありません。勝手
に「俺が現代人の総意だ」という口ぶりで出しゃばらないでください。

[ ]
RE:10453 [不具合]文字数カウントNo.10454
fzok4234 さん 21/05/27 16:12
 
> 「ご自身も含めて誰も使わないもの」を大量でタダで作れという**要求**は
> そろそろやめてください。
> それにあなたは秀丸のセールス&マーケティング責任者でも何でもありません。
> 勝手に「俺が現代人の総意だ」という口ぶりで出しゃばらないでください。

実装を強く求める「要求」ではなく、こういうアイデアがあることを示しただけの
「提案」です。実装に多大なコストがかかるようであれば無理に実装する必要の
ないもので、「もしゆとりがあれば将来こういうものを検討してみてはいかが?」と
いう程度のものです。

くれぐれも誤解なきようお願いします。


[ ]
RE:10453 [不具合]文字数カウントNo.10456
fzok4234 さん 21/05/27 16:43
 
それから、文字数や行/桁のように大きくなりがちな整数値の計算には、知らず知らずの
うちにオーバーフローさせてしまうリスクを伴います。これを回避するためには、
先ほど紹介したJPCERTのサイトで紹介されているような2項演算子に対応する
サブルーチンを前もって用意しておく必要があります。

しかしながら、秀丸マクロのサブルーチンの仕様は、戻り値を一旦変数##returnに
保存する方式のため、例えば
#val = ( #a + #b ) / #c + ( #d - #e ) * / #f ;
という風に1つの式中に2項演算が複雑に入り組んでいる場合では、安全な
サブルーチンに置き換えると記述量が大幅に増えて可読性や保守性も著しく
損なわれてしまいます。

もしでるもんた・いいじまさんが現在の秀丸マクロの仕様だけで実現可能な
もっとスマートな記述方法を御存知であるならば、それを紹介すればよいだけの
話ではないでしょうか。


[ ]
RE:10456 [不具合]文字数カウントNo.10460
秀丸担当 さん 21/05/28 13:00
 

C++等のネイティブコードは脆弱性になりうると思いますが、マクロの実行空間のこ
ととはまた別という気がします。
何らかの問題の要因にはなるかもしれないので、可能性はゼロとは言い切れないです
が。
オーバーフローしたかどうかを簡単にチェックできたらいいと思います。いつでもge
tresultex(n)とかで知れれば、簡便かもしれません。
四則演算などだけでなく、あらゆるケースにおいて漏れなくチェックするようにでき
るかというとわからないです。
ゆとりがあれば将来そういうものを検討できたらいいと思います。

[ ]
RE:10460 [不具合]文字数カウントNo.10462
fzok4234 さん 21/05/28 13:12
 
ご検討の方ありがとうございます。

とりあえず、当方においては代替の四則演算用のサブルーチン(あるいは外部DLLのメ
ソッド)を
作って、ファイル全体の文字数や行/桁の番号の演算に使用して当座はしのごうかと
思ってます。


[ ]
RE:10460 [不具合]文字数カウントNo.10467
fzok4234 さん 21/05/31 13:57
 
v8.98β10 Float x64にて、2500000000文字のファイルに対して「文字数」ダイアログが
正しく機能することと、charcount()関数が0を返すことを確認しました。
また、
( -2147483648 ) / ( -1 )
( -2147483648 ) % ( -1 )
- ( -2147483648 )
の演算でオーバーフローエラーとなることも確認できました。

修正ありがとうございます。


[ ]