プリプロセッサ †
プリプロセッサとはコンパイル(オブジェクトファイル作成)に先駆けて行われる前処理を行うツール
のことで、主にスクリプトの加工を行う。
HSPでは、hspcmp.dll がプリプロセッサとコンパイルを行う ( これにより生成されたオブジェクトファイル(*.ax)は、実行されるときに hsp3.exe などのランタイムに渡される )。
※掲載されているソースコードは、一部にプログラムガイドからの引用を含みます。
#include "filename"
#addition "filename" ; HSP 3.0以降限定?
"filename"で指定されたファイルをその位置に展開(挿入)する。
ファイルが存在しない場合は #include はエラーになるが、 #addition はエラーにはならない
以下に #include の動作を示す。
例.1−1/kz3
- sum.as
1
2
3
|
| repeat 10, 1
s += cnt
loop
|
- incsum.as
1
2
3
|
| #include "sum.as"
mes s
stop
|
- 展開後 incsum.as イメージ
1
2
3
4
5
|
| repeat 10, 1 s += cnt
loop
mes s stop
|
例.1−2/kz3
- ascii.as
- setascii.as
1
2
3
4
|
| #include "ascii.as"
repeat 26
poke ascii, cnt, 'A'+ cnt
loop
|
- mesascii.as
1
2
3
|
| #include "setascii.as"
mes ascii
stop
|
- 展開後mesascii.asイメージ
1
2
3
4
5
6
|
| sdim ascii, 26 + 1 repeat 26 poke ascii, cnt, 'A'+ cnt
loop
mes ascii stop
|
- 単純置換マクロ
#define 新規名称 元名称
日本語の命令に置き換えることも可能です。
例.2−1−1
1
2
3
4
|
| #define 表示 mes
s = "テスト"
表示 s
stop
|
- 識別子定義
#define 識別子
後に書く#ifdefなどに用いる識別子を定義する他に、空文字に置換(置換対象の削除)するという使い方もある。
例.2−2−1
1
2
3
4
5
6
7
8
9
10
|
| #define KZ3DEBUG #ifdef KZ3DEBUG
#define DBG_PREFIX "_DBG"+
#else
#define DBG_PREFIX
#endif
mes DBG_PREFIX "HSP"
stop
|
これを見て分かるように、単純置換マクロも元の名称に対する識別子を定義していると言える。
元の名称が指定されない場合は空となる。
- 引数付き置換マクロ
ルールが他より複雑です(説明が長くなる)ので、詳しい解説についてはマニュアルを参照してください。
使い方のサンプルのみを載せたいと思います。
- デバッグモードとリリースモードで処理を分ける
例.2−3−1
1
2
3
4
5
6
7
8
|
| #ifdef _DEBUG
#define dbg_mes(%1) dialog %1, , "debug dialog"
#else
#define dbg_mes(%1)
#endif
dbg_mes "Debug mode exec!"
stop
|
_DEBUG というマクロが定義されるときは、デバッグモード( スクリプトエディタからの実行 )です。実行ファイルを作って実行する場合、_DEBUG は定義されません。
#const マクロ名 定数式
#defineと同様ですが、定数(数値)の置き換え・計算結果の置き換えをします。
値の確定している場合に使用することで、&size(px){Text you want to change};高速化が期待できます。
1
2
3
4
5
|
| #const ALL 50
#const KAZU 100 * ALL
mes "ALL = " + ALL
mes "KAZU = " + KAZU
stop
|
また、#const の式では、演算子に優先順位のない HSP2.x 系でも、演算子の優先順位が、
[*,/] > [+,-] > [比較演算子,<<,>>] > [!] > [&,|,^]
になりますので、注意が必要です。
- 例えば、HSP2.x における #define と #const(優先順位がある)での違いは
1
2
3
4
5
|
| #const val_const 10+10*10 #define val_define 10+10*10
mes "#conde では "+ val_const
mes "#define では "+ val_define
stop
|
となります。また、#if #ifdef #ifndef の式にも演算子の優先順位があります。
プログラミングガイドに載っている#constのサンプルはそれの有用性を正しく示してないので動作の違いがつかめません。
#constの有用性が分かる(であろう)サンプルを作りましたが載せるには長い(簡単なレクチャーツールになってしまった)ので
添付したいと思います。以下のファイルで確認してみてください。(DefineConst.as)--kz3
defcnst.as
1
2
3
4
5
6
|
| #if 0 mes "ABC" mes "DEF" #else mes "GHI" #endif
|
演算子の優先順位は#constと同じです。
1
2
3
4
5
6
7
8
|
| #define SW
#ifdef SW
#ifdef SW2
mes "AAA" #else
mes "BBB" #endif
#endif
|
#ifdefがマクロで定義されている場合ONになるに対して
#ifndefはマクロで定義されている場合OFFになります。
また、演算子の優先順位は#constと同じです。
- 補足
同じ意味ですが、他と言い方をそろえる為に。
ifdefは指定した識別子が定義済みの場合、真になる。
ifndefは指定した識別子が未定義の場合、真になる。
#undef マクロ名
すでに登録されているマクロ名を取り消します。
プリプロセッサ命令は次のような書き方ができる。それぞれ一長一短ある。
- 書式1
1
2
3
4
5
6
7
8
9
|
| #include "xxxx.as"
#define KZ3DEBUG
#ifdef KZ3DEBUG
#define dbg_mes(%1) mes %1
#else
#define dbg_mes(%1) #endif
#define char_size 32
#define map_size 640
|
- 長所
- プリプロセッサ部分がまとまっており、命令の位置も揃えられる。
- 短所
- ネスト構造を把握しにくい。
- 書式2
1
2
3
4
5
6
7
8
9
|
| #include "xxxx.as"
#define KZ3DEBUG
#ifdef KZ3DEBUG
#define dbg_mes(%1) mes %1
#else
#define dbg_mes(%1) #endif
#define char_size 32
#define map_size 640
|
- 長所
- ネスト構造を把握しやすい。
- 短所
- プリプロセッサ記述子*1の位置がまばらになるので、通常の命令と併用した際にプリプロセッサ命令が紛れやすい。
- 書式3
1
2
3
4
5
6
7
8
9
|
| #include "xxxx.as"
#define KZ3DEBUG
#ifdef KZ3DEBUG
# define dbg_mes(%1) mes %1
#else
# define dbg_mes(%1) #endif
#define char_size 32
#define map_size 640
|
- 長所
- ネスト構造は書式1より把握しやすく、プリプロセッサ記述子が揃うので書式2より把握しやすい。
- 短所
- ネストが深くなるほどプリプロセッサ記述子と命令とが離れるため書式2より通常命令に紛れる。
- 書式4
1
2
3
4
5
6
7
8
9
10
11
|
| #include "xxxx.as"
#define KZ3DEBUG
#ifdef KZ3DEBUG
#define dbg_mes(%1) mes %1
#else
#define dbg_mes(%1) #endif
#define char_size 32
#define map_size 640
|
- 長所
- ネスト構造も把握しやすい、プリプロセッサ記述子もだいたい揃っている、通常の命令とも紛れない。
- 短所
- わからないw
- 仮設置。 --kz3
- ん!これはかなりいいページじゃないですか!#includeがわからない人もその挙動がよくわかる。うん。 -- Charlotte
- ありがとうございます^^ -- kz3
- 自分も書き足していこうと思います。 -- Charlotte
- お願いします^^ -- kz3
- 書き足しました。できるだけw -- Charlotte
- 裸で居眠りしちゃったよぉ〜;;(謎)ありがとうございます^^; -- kz3
- #const追記しました。 -- kz3
- スペース1字で字下げですかっ^^; -- kz3
- スペースで字下げって結構しますよ。(例えば変数の代入など -- Charlotte
- #constの所も追加したんですが、こういうことじゃない? -- Charlotte
- お、そうですそうです。;;簡潔だ! -- kz3
- #constでは優先順位が考慮されて、他スクリプト中ではされないってのもアレですよね^^; -- kz3
- #const中の計算式>プリプロセッサhsped2.exe ソース内の計算式>コンパイラhspcmp.dllが解釈している為かな。 -- kz3
- まぁ、hsp3ではそういうこともなくなるので -- Charlotte
- mes "乙" -- 774?
- これは hspcmp.dll と hspcmp.dll を利用できるエディタ(やプログラム)を用意すれば基本的に同様に動作することから正確には hspcmp.dll にプリプロセッサも内蔵されていると見る方が正しいと思います。エディタから hspcmp.dll にスクリプトソースを渡すとコンパイルする前にプリプロセス処理してそれからコンパイル処理すると考えればいいのでは。なので、 hspcmp.dll はコンパイラだけでなくプリプロセッサでもあるということです。 -- Irisawa
- プリプロセス処理した内容はスクリプトソースファイルのあるディレクトリ(スクリプトソースを開いてそのまま実行、または編集して実行した場合)かカレントディレクトリ(全く保存していない空の状態を編集した場合)の hsptmp.i です。 -- Irisawa
- hsptmp.i を出力させるには「#cmdopt ppout 1」が必要です。 --