-
Notifications
You must be signed in to change notification settings - Fork 40
Home
リポジトリ管理者(≠修正パッチ原作者)が記すSSG作成の手引きです
リポジトリ管理者による添削の意図や、既存機能の振る舞いを中心に
執筆時点の実装を説くものであり、仕様を保証するものではありません
HowToSSGに則り、[subject]
を項目、[attribute]
を属性と称します
※一部のセキュリティソフトでマルウェアとして検出されるのは仕様です
特にBitDefender系は酷く、Razy・Graftor・Jaikの各亜種と判定されますが
概ねアプリケーション動作と関係ない部分に反応しており対処が困難です
修正パッチを除外するか、誤検出報告を行う、乗り換え等をお奨めします
SpoilerAL自体がリスクウェアですから悪意あるSSGにこそ警戒して下さい
指定されたインスタンスが見つかりませんでした。
パラメーターが間違っています。
アクセスが拒否されました。
- 対象のプロセスが起動していないか権限不足、あるいはプロセス指定に不備があります
- SpoilerALを管理者として実行してください
ユーザーアカウント制御(UAC)は無効にせず、暗転しないも選ばないでください
パフォーマンス上の問題がある場合はやむを得ませんが、デスクトップが保護されません
無効なアドレスにアクセスしようとしています。
メモリ ロケーションへのアクセスが無効です。
- 製品バージョンが異なるか、環境依存となるアドレスが指定されています
この操作を完了するのに十分な記憶域がありません。
-
[repeat]
で終了値
が省略されており、お使いのパッチが旧式版と思われます
メモリの割り当てに失敗しました。
-
2021.01.19
以降、上記エラーがこのメッセージへ変わります
コーディングパーサ外でmalloc
やnew
の失敗により表示され
パース中ならばメモリの確保に失敗しました。
とガイドされます
無効なパラメータが記述されていない限り目にしないでしょう
このプロセスまたはスレッドのアプリケーション分離メタデータが壊れています。
- SSGデバッグモードでこのメッセージが表示される場合、
[allocate]
等によって
ローカル確保されたメモリ上へオーバーランが発生し、ヒープが破損しています
おそらく本体の不具合ではありません。サイズや宛先などSSGの修正が必要です
来歴は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
(ベンダー拡張)を使用してください
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バージョン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の項目は動的に増減しない為、展開前は名称検索が使えません
対応させると全ての遅延展開をせねばならず、循環参照は無限ループします
一度展開すれば探せますが、閉じていると再展開し、別項目になりずれます
また遅延展開された状態が異なると項目設定の保存&復元も機能しませんし
再拡張時に項目再生成が行われるため遅延展開内は値の固定も解除されます
ローカルスコープ属性です。動的スコープ変数名を,
で区切って定義します
変数名に=
を続け、初期整数および小数も設定できますが定数に限ります
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]heap
はheap番号
をキーに開始アドレス
と終端アドレス
を持つ辞書です
即ち32bitキーと32bit×2=64bitデータを蓄積できますが、変数名を32bitキーとするに
FNV-1aハッシュを直接採用し、本来は衝突時に行う完全比較を省略してしまいました
動的スコープ変数名はアルゴリズムに因って混同される組み合わせが稀に存在します
この制約は2020.07.30
バージョンからアルゴリズム変更により解消されました
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
なら何れにしてもキャッシュは働きません
※キャッシュの一意性担保はエラー時の代替え文字列による差別化が有効
既存タグですが、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]
指定の加筆が、リストやチェイン等も含め可能です
これは単にSSCファイル
指定が不要な[replace]
の糖衣構文です(6.2
でも使用可能
[offset]0x01
[subject]<# [.0.], Sig(%d) #>:string,_[.MName::nul.],1
[/offset]
と項目の内包表記が可能な以外、実装は同一、多段も制約も同じなので
[replace]
先の[group]
にて[/offset]
だけ使用しても、1段外れます
同一の[offset]
は排除されます、SSCファイル
部をコメント代わりに差別化しましょう
2019.02.12
より、6.3
以上で反復オフセットたる$Rel
変数が正規化されます
バイト列オフセットになり、*[ 4 :: FF $1 $Rel $$ *]
等の複合バイト列では
6.2
なら0
→2
と変化しますが、6.3
以上は1
→3
となります(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 $$ *]
これら既存タグは
2020.08.10
以降6.3
以上で多段にすると重ね掛けします
[io_fep]
出力時のみ外側から計算され、それ以外は内側から適用されます
この仕様は2021.0225
以降、[script]
オプションによる機能となりました
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
以降は実数モード[:
:]
の不整合も全ver
でfloat
へ統一します
実数モード間接演算は[:
:I]
や[:
:R]
、[:
:F]
など型指定が推奨されます
互換性問題は6.3
以降でも64bitオペランド時なので整数モードだと限定的です
実装当時からですが、*
(
)
と[:
:]
は;
を含むと評価順序が異なります
実行演算子が前後する為で2021.01.18
以降はほぼ同等に修正されましたが
順次評価演算子,
や事前計算、または関数化しましょう(制御構造は不正)
2021.08.22
より.
で始まる変数は、項目単位で保持されるメンバ変数になります
同項目でしか参照しないならば、[scope]
よりも的確な選択肢に取って代わります
SSRファイルの変換式や後述の[if]
ディレクティブ条件式では対象項目がないため
親dir
で参照・代入を行い、通常式に於いても..
で始めると同様の処理をします
2021.08.22
より$$
で始まる変数参照は中身がLocal文字列アドレスと見なされます
指し示す文字列が本当の参照変数名になり、コードの一本化を図ることが出来ます
記号の都合上PHPと同じ文法にしたので、置き換え型バイト列には使用できません
動的スコープ変数が登場しようとも、従来の構文が遺物となる訳ではありません
実装により役割は異なりますし、導入に伴い新たな光明を得るタグもあるでしょう
この節では修正パッチの実装を踏まえ、既存タグとの連携性などを鑑みましょう
CRTライクな関数群については膨大な数になるのでソースを参照してください
従来は[variable]
属性への追記命令でしたが、2021.08.22
より属性外であれば
記述された以降、その[group]
限定で[subject]
の初期化コードとして扱われます
項目スコープ変数の設定を想定しており、[/expr]
か空の[expr]
で無効にします
2021.08.22
より$funcname()
としても後述のユーザー定義関数を呼び出せます
接頭辞の$
は必須で、変数にLocal文字列アドレスを代入しておく必要もあります
文字列リテラルを渡して関数ポインタの様にコールバックとする使い方ができます
※文字列リテラルアドレスはそのコードを抜けると共に寿命が尽きるため注意
2021.03.02
で正式実装された[subject]
の追加を制御できるディレクティブです
主に[repeat]
、特に6.4
のdir
版[repeat]
遅延展開下での使用を想定しており
囲んだ複数行を纏めて制御でき、条件に合わない項目はツリー自体に現れません
[repeat]
はテキスト変換であり、変換式置換後をSSGファイルとして解釈します
その解釈時に評価されるため$Idx
を使用しますが、$Addr
等は参照できません
SSCやSSRのファイル指定を変換式とするより、再帰しないため概ね効率的です
大抵の言語で複合ステートメント、所謂ブロックを記述する文法になりますが
修正パッチは制御構造より先に[define]
が実装された為、その参照専用でした
しかし定義名のトリムが定義時のみで、参照時は無しという実装の抜け道から
2021.01.21
以降は{
}
を複合ステートメントと認識するように変更しました
元々パーサが波括弧を読み取るのは置換漏れ、即ち未定義参照という事ですが
便宜上、直後が空白文字である{
のみ認識し、それ以外はエラー扱いとします
※改行はSSGロード時に除去され、関数外なら直後が改行でも要インデント定義参照の波括弧がローカルを示す
従来、未定義参照を0
と解析していた物も同じくパースエラーになります
L
と隣接している場合は本来なら不正ですコードパースの前処理で
L
と置換後が合体して一つの単語になってしまいます※
L
と{
が隣接時にスペースを挿入する対策が発動すると非効率なので要注意2021.02.02
以降ブロックは同処理が適用されないので空けなくとも構いません
2021.01.17
より正式実装され、対象のプロセスをコマンドラインで限定します
:
や*
よろしく、後ろに続けてコマンドラインに含まれる文字列を指定します
イメージ名のみでは絞り込めなかったり、ウィンドウは別プロセスにあるなど
マルチプロセス用です。デバッグモードで対象のコマンドラインも出力します
※大文字小文字を無視し部分一致、または正規表現およびアンカーを使用
(正規表現モードでは.
⇒\.
、\
⇒\\
など文字によりエスケープが必要)
通常コマンドラインにはフルパスが含まれるため、イメージ名が同じでも
更にはウィンドウが同じでも、ディレクトリから絞り込む方法が使えます
ビットシフトを行う演算子ですが、sar
だけ未定義操作の実装が異なっていた為
2021.01.17
より全シフトで内部処理を64bitに変更し、シフト上限が拡張されます
対象が32bitでも64bit未満までのシフトが適正、未定義は64bit以上に統一されます
※シフト量は負数でも未定義、通例シフト量は上限値とANDが取られます
2020.12.11
以降で有効な命令となり、goto LABEL;
はLABEL:
へ飛びます
実装上ステートメント中へ飛べますが、基本は文単位で使用してください
ラベル記号がコロンになっているため、三項演算子との隣接もできません
この既存属性は2020.08.10
以降、分割項目用に3パラメータへ拡張されます
2番目のパラメータは一括書き換えを分割項目が含まれていても有効化するか
3番目は有効時に分割項目後も書き換えを続けるかtrue
/false
で設定します
既定値はヘッダ6.4
未満ならtrue,false,true
、以降はtrue,true,true
です
6.3
節では重複定義時の取り扱い説明でしたが、もう一つ拡張機能があり
グループ名をfunc()
の様にして記述するとユーザー関数を定義できます
引数なしでも括弧が必須で、仮引数はその中へカンマで区切り宣言します
アドレスコーディングの分割を彷彿とさせますが、コード中から呼び出せ
@
不要のssl->func()
とし、{define}
埋め込みと違い変数は独立します
2021.01.24
以降@
を前置した際は親dir
のコンテキストで実行されます
すると子項目から引数を与えつつ関数本体に親項目を束縛し評価するため
子項目と親項目のオフセットやスコープが異なっても越えて参照できます
ユーザー定義関数のコードは、1度実行されると抽象構文木をキャッシュし可変長引数も一応、
次回以降の呼び出しを効率化しますが、{define}
変容時は再解析されます
属性参照は項目ベースなので、次第によって別のキャッシュを生成します
$1
~$9
迄の残余引数と$0
でその数を参照できます実引数が少なくても仮引数は
0
と成るだけ故に、それ任せという手法も有
対象プロセスの捕捉・解放時に実行されるコードを複数行記述できます
記述位置で属性配列を取得して保持し、参照基点にします(項目と同様)
これは[define]
の参照や動的スコープ変数を使用する際に影響がでます
アタッチの実行はSSGを開いた時ではなく、初回の項目アクセス時です
表示や選択で現在値を得る前となり(リスト抽出はパラメータ計算後)
ネーミングやリスト抽出のアドレス計算ではプロセスを参照しない限り
捕捉タイミングが無いのでProcessId::nul
などで促すと良いでしょう
もしパース中にアタッチされ参照済みの動的スコープ変数があると
アタッチで行う同変数への代入は元コードで破棄されてしまいます
※この問題は2021.01.28
よりスヌーピングを導入し解消されました
デタッチを実行する機会は捕捉プロセスを見失ったか、切り換えた時
SSG又はSpoilerALを閉じた時で、同じPIDのプロセスが存在しなければ
合致する対象プロセスが有っても、ProcessId::nul
は0
を返します
2019.02.12
以降、置き換え型バイト列が拡張され0
~8
バイトに対応します
$0
$$
はバイト列を生成しませんが、パーサによる演算処理は実行されます
64bit演算にはCast64::
を、浮動小数点数にはparse_real;
を使用します
実数モードでは全オペラントをdouble
として扱う事に注意してください
Cast32::
も(float)
キャスト相当に成りますが、直接は扱えません
float
のバイト列化を想定した機能で、Cast64::
すると復元します
※精度は失われ、分母を2の累乗にできない小数は誤差が生じます
正規数は(1 << 仮数幅 | 仮数) * 2 ** (指数-バイアス-仮数幅)
“現在値もツリーに表示する”を制御する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
|
? | 現在値を前に配置 |
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
に;
は必須です
スクリプト言語などの様な、論理値ではなく最後に評価した値を返す論理演算子です
修正パッチで論理演算は短絡評価となり、条件分岐を置き換えられる場合があります
HowToSSGの繰り返しになりますが、SpoilerALまたは対象プロセスにメモリを確保します
プロテクト
==Local
⇒SpoilerALでHeapAlloc
、対象へは
VirtualAllocEx
を用います
HeapAlloc
は C/C++ におけるmalloc
やnew
の実装でも使われる一般的な関数ですが
一方のVirtualAllocEx
は最下層に位置し、アクセス保護も指定可能なれど粗粒度です
アドレスは粒度境界(e.g.64KB
)で、サイズ
がページ単位(e.g.4KB
)に切り上げられます
つまり対象のアドレス空間を64KB
以上占有し、最低でも4KB
のメモリが割り当てられます
もっとも[allocate]
はアドレスコーディングで参照される時に初めて割当を試みます
従って基本的にデータ領域ならLocal
を使い、他のプロテクト
は適宜設定するべきですが
Local
はヒープ領域で管理情報も含まれ、オーバーランを起こすとヒープ破壊は深刻です
十分な初期サイズを指定したり、realloc
で適切なサイズに設定しながら使用しましょう
※動的スコープ変数へのMemory::
アドレス代入はrealloc
での移動に注意してください
Microsoft Developer Networkにもヒープ:喜びと苦悩やメモリAPI比較と記事があります
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}
の動的更新も可能です
タグ名が実装を表しませんが、アドレスコーディングへプロローグを設定する属性です
付随する[expr]
は属性を生成せず、既存の[variable]
を加筆するタグとなっています
置き換え型バイト列を含め、属性下のアドレスコーディング全てに前置される仕様から
[define]
に代替されましたが、if
文で限定する等の道は残っているかもしれません
末尾に付加するバイト列と同様含めませんが、version : 6.4未満ではリスト抽出のみ必要です
文字数のチェック時も加味しません。書式指定する際は最終文字数以上に設定してください
残念ながら仕様になります、というのも元々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
のくだりは検証されません
-
{define}
の動的置換が行われます -
<#
#>
及び<@
@>
が書式化されます -
'+'
をセパレータとして分割されます - 分割された各要素がトリミングされます(項目名と
'+'
前後の空白が削られます - 要素が
@
で始まればチェインファイル名として取得、各行を結合し、1.に再帰します_
ならアドレスネーミングを解決し、それ以外はエスケープシーケンスが解釈されます
※@
によるチェインファイル指定は6.1以前からの明文化されていない仕様です - 各要素が連結され最終的な項目名になります
これは<#
#>
及び<@
@>
が単なるアドレスネーミングの糖衣構文ではない事を示します
'+'
より先に解釈され'+'
が不要であり、<#
#>
をアドレスネーミングの引数としたり
<@
@>
でアドレスネーミングをスイッチする等、柔軟性に富んだ項目名が生成可能です
またアドレスネーミングと違い項目名に限らず現在値補足文字や値の固定名にも使えます
※_fmt
は<#
#>
と違いGetAddress
で計算され即値ならオフセットが掛かる事にも注意
かねてより項目の現在値をアドレスネーミングで表示しようとするSSGが多く見受けられます
しかしこれは利用時に表示を切り換えられず、現在値もツリーに表示すると2重描写されます
そればかりか[enabled]
によるアクセス制御も効かないので、必要最低限に留めてください
特に数値の書式化は文字列参照でない限り、アクセスエラーが発生しても解りづらくなります