Skip to content
sceawung edited this page Aug 27, 2021 · 74 revisions

Table of Contents

TIPs for SpoilerAL ver 6.4

リポジトリ管理者(≠修正パッチ原作者)が記すSSG作成の手引きです
リポジトリ管理者による添削の意図や、既存機能の振る舞いを中心に
執筆時点の実装を説くものであり、仕様を保証するものではありません
HowToSSGに則り、[subject]項目[attribute]属性と称します

Troubleshooting

※一部のセキュリティソフトでマルウェアとして検出されるのは仕様です
特にBitDefender系は酷く、Razy・Graftor・Jaikの各亜種と判定されますが
概ねアプリケーション動作と関係ない部分に反応しており対処が困難です
修正パッチを除外するか、誤検出報告を行う、乗り換え等をお奨めします
SpoilerAL自体がリスクウェアですから悪意あるSSGにこそ警戒して下さい

指定されたインスタンスが見つかりませんでした。
パラメーターが間違っています。
アクセスが拒否されました。
  • 対象のプロセスが起動していないか権限不足、あるいはプロセス指定に不備があります
  • SpoilerALを管理者として実行してください
    ユーザーアカウント制御(UAC)は無効にせず、暗転しないも選ばないでください
    パフォーマンス上の問題がある場合はやむを得ませんが、デスクトップが保護されません
無効なアドレスにアクセスしようとしています。
メモリ ロケーションへのアクセスが無効です。
  • 製品バージョンが異なるか、環境依存となるアドレスが指定されています
この操作を完了するのに十分な記憶域がありません。
  • [repeat]終了値が省略されており、お使いのパッチが旧式版と思われます
メモリの割り当てに失敗しました。
  • 2021.01.19以降、上記エラーがこのメッセージへ変わります
    コーディングパーサ外でmallocnewの失敗により表示され
    パース中ならばメモリの確保に失敗しました。とガイドされます
    無効なパラメータが記述されていない限り目にしないでしょう
このプロセスまたはスレッドのアプリケーション分離メタデータが壊れています。
  • SSGデバッグモードでこのメッセージが表示される場合、[allocate]等によって
    ローカル確保されたメモリ上へオーバーランが発生し、ヒープが破損しています
    おそらく本体の不具合ではありません。サイズや宛先などSSGの修正が必要です

What's new in SpoilerAL version 6.4.2021.0225?

来歴はREADMEをご覧頂くとして、version : 6.3から動的スコープ変数が導入されました
これによりSSG6.2以上でグローバル変数、6.4以上でローカル変数もサポートされます
SSGヘッダ6.3以上は動的スコープ変数に備え、後述の破壊的な挙動修正も適用します
修正version : 6.4以降は多段適用式(replace, enabled, scope)を定義順に参照します

6.2以前は属性アドレス順≒アロケータ依存、6.3はソートが不完全…6.4で保証されます

またマイナー要素としてmenu.ini[File]を省略した行はSSGを開くコマンドになる他
表示メニューから現在値の描写を設定でき、SSG6.2以上ではアドレス演算子も追加され
その上アドレスネーミングは文字列もエラー時の代替え文字列に続き書式を指定できます
[repeat]終了値も省略可能になり、それは開始値終了値に、開始値0にします

ANSIコードページ以外の書式化は、ナロー文字列に替わりワイド文字列が渡されます
その為%sではなく%ls(C言語標準)又は%S(ベンダー拡張)を使用してください

[script]

2021.0225以降、SSGヘッダを更新用に回帰させる[script]オプションが導入されました
推奨ヘッダはSSG for SpoilerAL ver 6.4.2021.0225の様にヘルプversionを記述しつつ
[script]fix=3,dir=1,mul=0等も併用しver相当の機能を制御する形式へと移行されます

機能 挙動の概要(詳細については後述のセクションを参照)
fix 2 従来の6.2:パッチ専用パーサ、コード外{define}解決
3 従来の6.3[funnel][group]$Rel*の正規化
switch有効化、アドレスネーミングを解決する名称検索
dir 0 dir拡張しない6.4未満での既定値、常用メモリが微減
1 dirのイベントハンドラ有効化、fix=3併用で6.4相当
遅延展開時メモリリーク対策用に属性セットを常に保持
[child_rw]splitを含めるかの既定値がtrueに変化
mul 0 既存属性の多段化を行わない0が全verにおける既定値
1 ビットフラグ:多段[funnel][error_skip]にも対応
2 ビットフラグ:多段[io_fep]、実数は$Type >> 32
3 上記の組み合わせ:[funnel]及び[io_fep]を多段適用
修正パッチの式解析はMSVCを参考にリベースされ一部にPython文法も取り入れています
三項演算子は右結合であり、x86由来の命令や、CRTを模倣した関数も多数追加されます
C言語と異なり引数の,は順次評価演算子の破棄しない実装で、左から右へ評価されます

以降に挙げる記述例の対象は[process]<TApplication> *SpoilerAL :SpoilerAL.exeです

SSG for SpoilerAL ver 6.4

SSGバージョン6.4を宣言するとdirのパラメータが試験的に拡張されます
属性管理方式も変え、常用メモリを費やし遅延展開毎の肥大化を低減します

動的スコープ変数は6.2から使えますが、修正パッチversion : 6.4未満では
スコープ選択が不完全なのでネストスコープ定義の際も6.4を推奨します

dir,を続け記述したコードはイベントハンドラとして拡張時に限り評価され
[repeat]引数を記述すると、ツリー拡張直前に属性を引き継ぎ遅延展開します
この引数もアドレスコーディングとして評価され、子孫項目が動的生成されます
静的配置の子孫項目は据え置かれる一方、遅延展開分は拡張毎に再生成します

[repeat]引数パース中に所謂ヌルポ等が発生すると展開は中止されます
実装上、遅延展開dir直下へ記述できる静的な子項目は65535個未満です
[involve]EX
[group]Char
	[subject][!F @data + $Val, 0x%p= !]:string,_@data + $Idx,1
[/group]
[group]Copyright
	[subject]Copyright :string,_@data,[!L $Val !],null
	 [repeat]Ex->Char,[!L $Val !]
[/group]
[/involve]

[subject]Borland C++:dir,EX->Copyright,@i++;\
	strlen::(@data = MName::nul:=.data),0x40000000,0x40000000
	[subject]<# @i, 展開%u回目 #>:split,label
[back]

dir[repeat]となるこの機能の肝は、ツリー拡張時に解釈される点です
プロセス設定後であるため、開始値・終了値・増加値を動的に指定できる上
SSRファイル中の変換式[! !]においてもポインタ演算子が使用可能になり
変換後にSSGとして再解析される仕様から、項目の種類さえ自在になります
遅延生成によって展開速度が分散され、循環参照など対応の幅も広がります

遅延展開内では通常の[repeat]も変換式にポインタ演算子を使用可能
変換式は展開時間とメモリを消費し、対の$Idxは計算時間が微増します
頻度次第では[repeat][enabled]も併用し開閉作業を減らしましょう
この機能が試験的とされるのは貴重なdirコード部を専有している事に加え
元々SpoilerALの項目は動的に増減しない為、展開前は名称検索が使えません
対応させると全ての遅延展開をせねばならず、循環参照は無限ループします
一度展開すれば探せますが、閉じていると再展開し、別項目になりずれます
また遅延展開された状態が異なると項目設定の保存&復元も機能しませんし
再拡張時に項目再生成が行われるため遅延展開内は値の固定も解除されます

[scope]

ローカルスコープ属性です。動的スコープ変数名を,で区切って定義します
変数名に=を続け、初期整数および小数も設定できますが定数に限ります
SSGロード時における静的展開ゆえ、例外は[repeat]中の変換式だけです
{define}も解決はされるものの置換後が定数リテラルでなければ不正です

項目よろしくタグ以降に:があると、それ以前をスコープIDとして解釈します
整数または文字列を指定でき、0と空文字列はグローバルスコープになります
文字列IDは一意の正数になる為、混在時は-65535迄の負数を使用してください

IDが未定義なら同一性検証は属性インスタンスアドレスの補数を用います
即ち-2147483647-65536の何れかになり、もし遅延展開内である場合は
拡張毎に新しいスコープが生成され、SSGを閉じるまでメモリリークします
2019.02.18旧仕様の順序からID文法を変更2021.01.15文字列IDに対応

[scope][enabled]と同様に入れ子も可能ですが、[enabled]とは逆に
内側から外側へ辿られ、未定義の変数はグローバル変数として扱われます
外側の同名変数は隠蔽され、スコープ毎に異なる値を保持する事も可能です

アドレスコーディングからは@変数名として参照しますが、特筆すべき点として
ダイナミックスコープ、通常変数へのインポート、変数名の衝突が挙げられます

[offset]_MName::nul + @diff,これも「version : 6.3」以降の新構文
	[scope]diff=0x00
		[subject]_,_L&@diff,4,num,?,Sig(%u):string,0,1
		[scope]diff=0x01
			[subject]_,_L&@diff,4,num,?,Sig(%u):string,0,1
		[/scope]
	[/scope]
[/offset]

上記例だとローカルスコープ外で@diffを参照しますが、グローバル固定にはならず
[offset]を評価する項目次第であり、属するスコープの値がそれぞれ参照されます
[define]を除く属性は項目を対象に適用され、属性参照は項目を元に行われます
[replace]オフセット値[. .]を使用すると無限再帰に陥る理由も同様です
[adjustment]は基準がroot:dir固定なので、グローバル変数しか参照できません
またトップレベルスコープで[/scope]を記述すると、以降のスコープが消滅します

動的スコープ変数の参照方法は前述した通りですが、これは$@変数名と同じ意味で
6.2以降のアドレスコーディングパーサは$を無視します。6.3でこれが拡張されると
未代入の通常変数が参照され変数名が@で始まる場合、項目のスコープ構造を辿り
同名の動的スコープ変数の値が、同名の通常変数の初期値としてインポートされ
評価を抜ける際、その成否に関わらず通常変数の現在値が参照元へ書き戻されます
これにより同コード中の参照が簡略化され、評価完了を示す番兵にも活用できます

スコープ変数のアドレス取得は、コード末尾かreturn時のみ参照元を返します

変数名の衝突は[scope][adjustment]heapの流用で実装される事に起因します
[adjustment]heapheap番号をキーに開始アドレス終端アドレスを持つ辞書です
即ち32bitキーと32bit×2=64bitデータを蓄積できますが、変数名を32bitキーとするに
FNV-1aハッシュを直接採用し、本来は衝突時に行う完全比較を省略してしまいました
動的スコープ変数名はアルゴリズムに因って混同される組み合わせが稀に存在します

この制約は2020.07.30バージョンからアルゴリズム変更により解消されました

SSG for SpoilerAL ver 6.3

SSGバージョン6.3を宣言すると、参照透過性悪化の低減を目的として
主に[funnel]属性の処理が修正され、ファンネルファイル適用時の
[enabled]再評価を抑制し、HowToSSGとの整合性を担保します

項目が数値の書き込みを行うとき、付随して書き込み処理を行わせる

順序も修正され、条件式書き込むアドレスと記述通りの評価になります

従来は書き込むアドレス==0条件式ごと丸々スルーされていました
6.2以下で書き込まず抜ける節は書き込むアドレス-1等とします

この修正は項目で有効条件が無効になる書き込みを行おうとした場合に
書き込みが成功したとしても[funnel]が付随しない問題を解消しつつ
意図した条件に合致させ、アドレス計算の失敗時に通知させる為です

最初に記述され$Valを唯一参照できる条件式から評価を行う事で
スコープ変数などへの代入・参照順序を明確化する狙いもあります
また$ValはSSGヘッダ6.2以下と6.3以上で些か値が変化します

$Type 項目 $Addr 6.2以下の$Val 6.3以上の$Val
2 calc 絶対 [io_fep]適用後の値 [io_fep]適用前の値
3 toggle 絶対 チェック状態
4 list 絶対 [io_fep]適用後の値 [io_fep]適用前の値
5 string 絶対 最下位4バイト 文字バイト数
6 bitlist 絶対 [io_fep]適用後の値 [io_fep]適用前の値
7 b_toggle 相対※ チェック状態
8 b_calc 相対※ [io_fep]適用後の値 [io_fep]適用前の値
9 b_list 相対※ [io_fep]適用後の値 [io_fep]適用前の値
10 d_list 相対※ 選択された行番号 (0 based)
11 trace 未定義 常に1
12 d_toggle 相対※ ビットベクタの先頭アドレス
13 copy 絶対 4byte以下⇒[io_fep]適用後 4byte以下⇒[io_fep]適用前
14 f_calc 絶対 [io_fep]適用後のdouble* [io_fep]適用前のdouble*
15 bf_calc 相対※ [io_fep]適用後のdouble* [io_fep]適用前のdouble*
※一括系とダブル系は項目アドレスの計算が特殊でコーディングによって
明示的にオフセットが加算されると絶対になる他、realならば未定義です
表の$Val[io_fep]適用時の物で、アドレスとなる場合はローカルです

更に名称検索がアドレスネーミングを解決して行われます(ガイド出力なし)
ヒープリストのソートは廃止され、HNumber::もOSの列挙順序を尊重します
加えてリスト抽出オプションをnocacheにせずとも引数パースが有効化され
キャッシュリストも可変長にしつつ、2回目以降の冗長な抽出を省略できます

起動中に変化し再抽出が必要なリストのみをnocacheにすると効率的です
アドレスかステップサイズが0なら何れにしてもキャッシュは働きません
※キャッシュの一意性担保はエラー時の代替え文字列による差別化が有効

[group]

既存タグですが、SSGヘッダ6.3以上だと重複定義時の扱いを若干変更します
同名[involve]の多重定義は従来から可能なものの、既存[group]の扱いは
同SSL内で再定義されたら上書き、多重定義時は破棄されるという実装でした

[involve]はファイル名と同様case-insensitive、[group]はcase-sensitive
※多重定義時の挙動は仕様ではなくAL作者の誤解によるものと推察される
ソースのコメントには「グループ名も同じ場合は上書きとなる」とあるが
std::map::insertが使用されており、これは既存のキーを上書きしない
それに因ってリスト抽出も「毎回読み直す」は行うが、破棄されていた
修正パッチはキャッシュ機構も是正し、nocacheリストのみを読み直す

それを多重定義時も上書きにし、6.3で再定義された際は末尾へ追加します
この修正で[group]の分割定義が可能となり、更なる柔軟性も期待できます

[involve]Ex
[group]ample
	[subject]Directory:dir
[/group]
#include "Ex.insert.ssl"
[group]ample,Alias_can_be_assigned_by_commas
		[subject]Label:string,0,48,null
[/group]
#include "Ex.append.ssl"
[group]ample
	[back]
[/group]
[/involve]

[involve]Ex
#include "Ex.replace.ssl"
[/involve]

[replace]_MName::nul:=.data,Ex->ample
[replace]_MName::nul:=.data,Ex->Alias_can_be_assigned_by_commas

上記のように#includeを併用すると、分割定義された[group]の統合に留まらず
#includeしたSSLに同名[group]が含まれていれば前後に項目が配置されるという
#includeされた側から[group]指定の加筆が、リストやチェイン等も含め可能です

[offset]

これは単にSSCファイル指定が不要な[replace]の糖衣構文です(6.2でも使用可能

[offset]0x01
	[subject]<# [.0.], Sig(%d) #>:string,_[.MName::nul.],1
[/offset]

と項目の内包表記が可能な以外、実装は同一、多段も制約も同じなので
[replace]先の[group]にて[/offset]だけ使用しても、1段外れます

同一の[offset]は排除されます、SSCファイル部をコメント代わりに差別化しましょう

$Rel

2019.02.12より、6.3以上で反復オフセットたる$Rel変数が正規化されます
バイト列オフセットになり、*[ 4 :: FF $1 $Rel $$ *]等の複合バイト列では
6.2なら02と変化しますが、6.3以上は13となります(FFを加味)
これにより反復命令外でも、バイト列の累積オフセットを取得可能となります

$Relは絶対ジャンプでリセットされ、条件付き命令やネストを考慮しません
また終了アドレス-ONのバイト列も反復と共通処理になり$Relを参照できます

この修正に伴い、特定の反復命令を特殊化し高速処理する機構も実装されます

[allocate]0,0x10000,ERW
# 単純バイト列の反復は、ベクトル化アンロールされ反復サイズの一括処理になる
# 倍々コピーを行うため、例え2byteを64KB反復する等としても速度に遜色はない
[subject]反復例1:toggle,_Memory::0,*[ 0x10000 :: 0100 *]
# バイト列+ニブルマスクバイト列は、マスクバイト列に一元化され上記同様になる
# マスク処理はバイト単位だが、体感できる程には成らず、相対ジャンプよりも高速
[subject]反復例2:toggle,_Memory::0,*[ 0x10000 :: 0100???? *]
# 単一の置き換え型アドレスコーディングは、バイト列パーサを再帰的に呼び出さず
# コードパーサの直接呼び出しで無駄を省き、反復単位($4)が大きいほど速くなる
# 但しポインタ変換や間接演算子などの対象メモリアクセスは大幅な速度低下を招く
[subject]反復例3:toggle,_Memory::0,*[ 0x1000 :: $4 $Rel >> 2 $$ *]

[funnel] [io_fep]

これら既存タグは2020.08.10以降6.3以上で多段にすると重ね掛けします
[io_fep]出力時のみ外側から計算され、それ以外は内側から適用されます

この仕様は2021.0225以降、[script]オプションによる機能となりました

switch

2020.12.13以降、予約語と変数名の衝突を考慮し6.3以上で有効化されます
例によってcaseラベルで適正なのは32bit定数値か文字列リテラルのみです
文字列はダブルクォートで括り、最初のcaseがそうなら文字列比較モードに
文字列リテラルはプリフィックスがuならワイド文字、u8ならUTF-8と判定
breakされなければフォールスルーしますが、goto case*32bitも使えます

switch中でもcontinueはループに作用し、PHPと違ってbreak扱いしません
ネストしたswitch内を除き、ブロック内へも飛び込めるC言語に近い実装です

*間接演算子

6.2以上で使える[::]と同等の演算子ですが、間接代入が実装されて以来
実数モードでの読み書きがfloat/double下位という不整合状態だったので
2021.01.10から整合性のため6.3以上はオペランドサイズに修正されました
2021.01.12以降は実数モード[::]の不整合も全verfloatへ統一します
実数モード間接演算は[::I][::R][::F]など型指定が推奨されます
互換性問題は6.3以降でも64bitオペランド時なので整数モードだと限定的です

実装当時からですが、*()[::];を含むと評価順序が異なります
実行演算子が前後する為で2021.01.18以降はほぼ同等に修正されましたが
順次評価演算子,や事前計算、または関数化しましょう(制御構造は不正)

項目スコープ変数

2021.08.22より.で始まる変数は、項目単位で保持されるメンバ変数になります
同項目でしか参照しないならば、[scope]よりも的確な選択肢に取って代わります
SSRファイルの変換式や後述の[if]ディレクティブ条件式では対象項目がないため
dirで参照・代入を行い、通常式に於いても..で始めると同様の処理をします

可変変数

2021.08.22より$$で始まる変数参照は中身がLocal文字列アドレスと見なされます
指し示す文字列が本当の参照変数名になり、コードの一本化を図ることが出来ます
記号の都合上PHPと同じ文法にしたので、置き換え型バイト列には使用できません

SSG for SpoilerAL ver 6.2

動的スコープ変数が登場しようとも、従来の構文が遺物となる訳ではありません
実装により役割は異なりますし、導入に伴い新たな光明を得るタグもあるでしょう
この節では修正パッチの実装を踏まえ、既存タグとの連携性などを鑑みましょう
CRTライクな関数群については膨大な数になるのでソースを参照してください

[expr]

従来は[variable]属性への追記命令でしたが、2021.08.22より属性外であれば
記述された以降、その[group]限定で[subject]の初期化コードとして扱われます
項目スコープ変数の設定を想定しており、[/expr]か空の[expr]で無効にします

可変関数

2021.08.22より$funcname()としても後述のユーザー定義関数を呼び出せます
接頭辞の$は必須で、変数にLocal文字列アドレスを代入しておく必要もあります
文字列リテラルを渡して関数ポインタの様にコールバックとする使い方ができます

※文字列リテラルアドレスはそのコードを抜けると共に寿命が尽きるため注意

[if] [elif] [endif]

2021.03.02で正式実装された[subject]の追加を制御できるディレクティブです
主に[repeat]、特に6.4dir[repeat]遅延展開下での使用を想定しており
囲んだ複数行を纏めて制御でき、条件に合わない項目はツリー自体に現れません
[repeat]はテキスト変換であり、変換式置換後をSSGファイルとして解釈します
その解釈時に評価されるため$Idxを使用しますが、$Addr等は参照できません
SSCやSSRのファイル指定を変換式とするより、再帰しないため概ね効率的です

{ }

大抵の言語で複合ステートメント、所謂ブロックを記述する文法になりますが
修正パッチは制御構造より先に[define]が実装された為、その参照専用でした
しかし定義名のトリムが定義時のみで、参照時は無しという実装の抜け道から
2021.01.21以降は{}を複合ステートメントと認識するように変更しました
元々パーサが波括弧を読み取るのは置換漏れ、即ち未定義参照という事ですが
便宜上、直後が空白文字である{のみ認識し、それ以外はエラー扱いとします

※改行はSSGロード時に除去され、関数外なら直後が改行でも要インデント
従来、未定義参照を0と解析していた物も同じくパースエラーになります
定義参照の波括弧がローカルを示すLと隣接している場合は本来なら不正です
コードパースの前処理でLと置換後が合体して一つの単語になってしまいます
L{が隣接時にスペースを挿入する対策が発動すると非効率なので要注意
2021.02.02以降ブロックは同処理が適用されないので空けなくとも構いません

[process] ?

2021.01.17より正式実装され、対象のプロセスをコマンドラインで限定します
:*よろしく、後ろに続けてコマンドラインに含まれる文字列を指定します
イメージ名のみでは絞り込めなかったり、ウィンドウは別プロセスにあるなど
マルチプロセス用です。デバッグモードで対象のコマンドラインも出力します

※大文字小文字を無視し部分一致、または正規表現およびアンカーを使用
(正規表現モードでは.\.\\\など文字によりエスケープが必要)
通常コマンドラインにはフルパスが含まれるため、イメージ名が同じでも
更にはウィンドウが同じでも、ディレクトリから絞り込む方法が使えます

<< >> sar

ビットシフトを行う演算子ですが、sarだけ未定義操作の実装が異なっていた為
2021.01.17より全シフトで内部処理を64bitに変更し、シフト上限が拡張されます
対象が32bitでも64bit未満までのシフトが適正、未定義は64bit以上に統一されます

※シフト量は負数でも未定義、通例シフト量は上限値とANDが取られます

goto

2020.12.11以降で有効な命令となり、goto LABEL;LABEL:へ飛びます
実装上ステートメント中へ飛べますが、基本は文単位で使用してください
ラベル記号がコロンになっているため、三項演算子との隣接もできません

[child_rw]

この既存属性は2020.08.10以降、分割項目用に3パラメータへ拡張されます
2番目のパラメータは一括書き換えを分割項目が含まれていても有効化するか
3番目は有効時に分割項目後も書き換えを続けるかtrue/falseで設定します
既定値はヘッダ6.4未満ならtrue,false,true、以降はtrue,true,trueです

[group]

6.3節では重複定義時の取り扱い説明でしたが、もう一つ拡張機能があり
グループ名をfunc()の様にして記述するとユーザー関数を定義できます
引数なしでも括弧が必須で、仮引数はその中へカンマで区切り宣言します
アドレスコーディングの分割を彷彿とさせますが、コード中から呼び出せ
@不要のssl->func()とし、{define}埋め込みと違い変数は独立します
2021.01.24以降@を前置した際は親dirのコンテキストで実行されます
すると子項目から引数を与えつつ関数本体に親項目を束縛し評価するため
子項目と親項目のオフセットやスコープが異なっても越えて参照できます

ユーザー定義関数のコードは、1度実行されると抽象構文木をキャッシュし
次回以降の呼び出しを効率化しますが、{define}変容時は再解析されます
属性参照は項目ベースなので、次第によって別のキャッシュを生成します
可変長引数も一応、$1$9迄の残余引数と$0でその数を参照できます
実引数が少なくても仮引数は0と成るだけ故に、それ任せという手法も有

[attach][/attach] [detach][/detach]

対象プロセスの捕捉・解放時に実行されるコードを複数行記述できます
記述位置で属性配列を取得して保持し、参照基点にします(項目と同様)
これは[define]の参照や動的スコープ変数を使用する際に影響がでます

アタッチの実行はSSGを開いた時ではなく、初回の項目アクセス時です
表示や選択で現在値を得る前となり(リスト抽出はパラメータ計算後)
ネーミングやリスト抽出のアドレス計算ではプロセスを参照しない限り
捕捉タイミングが無いのでProcessId::nulなどで促すと良いでしょう

もしパース中にアタッチされ参照済みの動的スコープ変数があると
アタッチで行う同変数への代入は元コードで破棄されてしまいます

※この問題は2021.01.28よりスヌーピングを導入し解消されました

デタッチを実行する機会は捕捉プロセスを見失ったか、切り換えた時
SSG又はSpoilerALを閉じた時で、同じPIDのプロセスが存在しなければ
合致する対象プロセスが有っても、ProcessId::nul0を返します

$8 $$

2019.02.12以降、置き換え型バイト列が拡張され08バイトに対応します
$0 $$はバイト列を生成しませんが、パーサによる演算処理は実行されます
64bit演算にはCast64::を、浮動小数点数にはparse_real;を使用します

実数モードでは全オペラントをdoubleとして扱う事に注意してください
Cast32::(float)キャスト相当に成りますが、直接は扱えません
floatのバイト列化を想定した機能で、Cast64::すると復元します
※精度は失われ、分母を2の累乗にできない小数は誤差が生じます
正規数は(1 << 仮数幅 | 仮数) * 2 ** (指数-バイアス-仮数幅)

[format]

“現在値もツリーに表示する”を制御する2019.01.26以降で新設された属性です
[format]対象ビットフラグ,現在値書式,項目名書式という多段も可能な構文です
現在値書式_なら現在値取得自体を行わず、項目名書式は主に桁揃え用です
対象ビットフラグにはコーディングパーサが働き、指定する項目定数は次の通りです

ビット定数 現在値 既定 適用される項目
UNKNOWN void   trace, copy
LONG long [%d] calc, b_calc
INDEX char* [%s] list, b_list, d_list
BOOL char* [%s] toggle, b_toggle
STRING char* [%s] string
VECTOR char* [%s] bitlist, d_toggle
DOUBLE double [%f] f_calc, bf_calc
ANY ?   上記全て
DIR void   dir
ALT ?   現在値を前に配置

else

if文の条件不成立時に実行されるブロックですが、修正パッチ2019.01.18以降は
試験的なfor-else文が正規化され、for以外のループにもelse節を定義できます
これはPythonの文法を取り入れたもので、ループ条件が偽となった時に実行されます
つまりループがbreakされずに終了した時、1度だけ実行されるブロックとなります

括弧でステートメントブロックを形成しない場合は、then節に注意してください
当文法の採用によりif (1) while (0) break; else 2;whileと結合しますが
while (1) if (0) 2; else break;ifと結合し、do-while;は必須です

and or

スクリプト言語などの様な、論理値ではなく最後に評価した値を返す論理演算子です
修正パッチで論理演算は短絡評価となり、条件分岐を置き換えられる場合があります

[allocate]

HowToSSGの繰り返しになりますが、SpoilerALまたは対象プロセスにメモリを確保します
プロテクト==Local⇒SpoilerALでHeapAlloc、対象へは VirtualAllocExを用います
HeapAllocC/C++ におけるmallocnewの実装でも使われる一般的な関数ですが
一方のVirtualAllocExは最下層に位置し、アクセス保護も指定可能なれど粗粒度です
アドレスは粒度境界(e.g.64KB)で、サイズがページ単位(e.g.4KB)に切り上げられます
つまり対象のアドレス空間を64KB以上占有し、最低でも4KBのメモリが割り当てられます

もっとも[allocate]はアドレスコーディングで参照される時に初めて割当を試みます

従って基本的にデータ領域ならLocalを使い、他のプロテクトは適宜設定するべきですが
Localはヒープ領域で管理情報も含まれ、オーバーランを起こすとヒープ破壊は深刻です
十分な初期サイズを指定したり、reallocで適切なサイズに設定しながら使用しましょう

※動的スコープ変数へのMemory::アドレス代入はreallocでの移動に注意してください
Microsoft Developer Networkにもヒープ:喜びと苦悩メモリAPI比較と記事があります

[define]

C/C++ におけるプリプロセッサマクロを模した、引数なしマクロといった機能です
単純なテキスト置換 なので、アドレスコーディングに限らず様々な活用法があります
大別すると属性へは静的置換、項目のアドレスコーディングなどは動的置換になります

[allocate]0,4,Local
[define gVar][:Memory::0:L]

上記の様に[allocate]やポインタ変換演算子と組み合わせ、間接代入を使う事で
グローバル変数も模せましたが、ログがパース前に置換されたコードになりますし
こういったパターンに限っては動的スコープ変数の領分たり得るでしょう
アドレス演算子で動的スコープ変数のアドレスを取得して項目アドレスとすれば
ユーザー入力を直接設定できますし、細々とした[allocate]は不要になります

但し{define}でコードを丸々挿入するのに比べ、動的スコープ変数は真に変数なので
動的値が必要な場合、いつどこで計算して代入しておくのか考慮しなければなりません
[enabled]は常に項目アクセスより先行しますが、ネストしている場合は短絡評価です
アドレスネーミングには介入しませんし、それ自体も非表示の項目では評価されません

試験的ながらdirへコードを記述すると、ディレクトリ拡張時に限り評価されるため
常に最新の値を必要とする訳ではない場合や、段階的に計算する等には妥当でしょう

動的展開

[repeat]の変換式とは逆に、[subject]等へ記述した{define}は動的展開されます

[involve]EX
[group]Label
	[subject]{offset} == <# [.0.] #>:split,label
[/group]
[/involve]

[define offset]1
[replace]{offset},EX->Label

[define offset]2
[replace]{offset},EX->Label

その結果、上記は意図した表示になりません。これは項目が属性を参照で保持しており
[define]もまた属性であり、同名で定義された[define]は既存の属性を上書きします
対して属性は基本的に属性へ掛かる物ではなく、属性は他属性への参照を保持しない為
[replace]など属性へ記述した{define}はSSG読み込み時に静的展開で処理されます
この違いを吸収するには[undef]を使用し、既存の属性参照を上書きしない様にします
あるいはこの仕様を逆手に遅延展開内で再定義すると{define}の動的更新も可能です

[variable]

タグ名が実装を表しませんが、アドレスコーディングへプロローグを設定する属性です
付随する[expr]は属性を生成せず、既存の[variable]を加筆するタグとなっています
置き換え型バイト列を含め、属性下のアドレスコーディング全てに前置される仕様から
[define]に代替されましたが、if文で限定する等の道は残っているかもしれません

残りの端々

最大文字数はヌル終端文字を含めるのか

末尾に付加するバイト列と同様含めませんが、version : 6.4未満ではリスト抽出のみ必要です
文字数のチェック時も加味しません。書式指定する際は最終文字数以上に設定してください

文字列項目がunicodeutf8で文字化けする事例

残念ながら仕様になります、というのも元々SpoilerALはSHIFTJIS_CHARSETが前提です
Unicode文字セットを直接は扱えないので、適宜ANSIコードページへ変換していますが
文字列項目だけは俗に言うベストフィットマッピング(©cなど)を使用しません
同じ文字を書き込んでも元に戻せない事を示すためで、その他では概ね表示されます

ダブルトグル及びビットリストの罠

これら既定だとツリーに黄色で表示される項目は、選択した行のみを書き換えるのではなく
全行をチェック状態に応じ処理するので、項目を開いたより後のメモリ変容は破棄されます
この6.1以前からの仕様により、ダブルトグルでは領域が重なると後続に上書きされます

HowToSSGの処理リスト.LSTにおける3行目は4行目にオーバーライドされます

ファンネルファイルの評価方式

SSGヘッダ6.2以下では、項目に[enabled]が掛かっていれば再評価され
また条件式よりも後に記述される書き込むアドレスが先に評価されます
その結果が0であると条件式の評価もバイト列の評価もスキップされます

明文化されていない文字バイト列

6.1以前からs文字列というバイト列書式がANSIコード限定で存在します
特殊な16進表記にも対応する様ですが、命令とは組み合わせられず
使用例も見られないため、修正パッチでのサポートは限定的です

終了アドレスを使用しない

toggle項目などONのバイト列に指定可能な、終了アドレスのバイトも含める変則的な物です
問題なのはtoggle項目がSSG展開時に、[input]命令用として項目サイズの解決を試みます
伴ってアドレス計算も必要になりますが、SSG展開時には未だプロセスが設定されていません
終了アドレスがオフセットに非ず、完全な動的解決の場合サイズは0とされ不整合になります
またアドレス補正の試作においても、開始アドレスが0へ固定されて不正なサイズとなります
従って2020.08.10より6.3以上では、コーディングを終了アドレスが無ければ評価しません
バイト列反復命令を推奨します。尤も反復サイズを動的解決するなら同じ問題が発生します

リスト抽出テクニック

nocache及び6.3以上のリスト抽出は1行の最大文字数/行数/ステップサイズにも式が書けます
[allocate]したメモリにアドレス部で制御文、組み込み関数、間接書込などを使い構築すれば
従来の固定長&一定公差を脱却できます。アドレス変数$Listも使え、除算は括弧内で行います

実はアドレスネーミングと同じく必要な接頭辞は_だけで、memのくだりは検証されません

項目名の取得プロシージャ

  1. {define}の動的置換が行われます
  2. <# #>及び<@ @>が書式化されます
  3. '+'をセパレータとして分割されます
  4. 分割された各要素がトリミングされます(項目名と'+'前後の空白が削られます
  5. 要素が@で始まればチェインファイル名として取得、各行を結合し、1.に再帰します
    _ならアドレスネーミングを解決し、それ以外はエスケープシーケンスが解釈されます
    @によるチェインファイル指定は6.1以前からの明文化されていない仕様です
  6. 各要素が連結され最終的な項目名になります
これは<# #>及び<@ @>が単なるアドレスネーミングの糖衣構文ではない事を示します
'+'より先に解釈され'+'が不要であり、<# #>をアドレスネーミングの引数としたり
<@ @>でアドレスネーミングをスイッチする等、柔軟性に富んだ項目名が生成可能です
またアドレスネーミングと違い項目名に限らず現在値補足文字や値の固定名にも使えます
_fmt<# #>と違いGetAddressで計算され即値ならオフセットが掛かる事にも注意

アドレスネーミングによる現在値の表示は控える

かねてより項目の現在値をアドレスネーミングで表示しようとするSSGが多く見受けられます
しかしこれは利用時に表示を切り換えられず、現在値もツリーに表示すると2重描写されます
そればかりか[enabled]によるアクセス制御も効かないので、必要最低限に留めてください
特に数値の書式化は文字列参照でない限り、アクセスエラーが発生しても解りづらくなります