本サイトはプロモーションを含みます。

Tera Termマクロでincludeを使うときの注意点

TeraTermマクロのincludeコマンドをPHPのincludeと同じような感覚で使うと上手く動きません。

まずは次のマクロを見てください。

val = 123
messagebox val 'main.ttl'

include 'sub.ttl'

messagebox val 'main.ttl'

call sub1
:sub1
messagebox val 'sub1'
val = 321

上のマクロをmain.ttl、下のマクロをsub.ttlというファイル名で保存しています。確かめたいのは、変数とラベルのスコープです。

上のmain.ttlを実行すると、sub.ttlでvalの値が321に変更されて、main.ttlの6行目でvalの値が321として参照できます。これは想定通りです。TeraTermマクロでは変数がグローバル変数として扱われるためです。

ところが、ラベルは違います。main.ttlを実行すると8行目のcall sub1で「Label requiered」エラーが発生します。このエラーは「ラベルが見つからない」という意味です。つまり、main.ttlからはsub1というラベルが見えないようです。

includeの仕様

PHPの気分でincludeを遣うと、次のようにメモリ上に展開されて実行されると想像してしまいがちです。

val = 123
messagebox val 'main.ttl'

:sub1
messagebox val 'sub1'
val = 321

messagebox val 'main.ttl'

call sub1

しかし、TeraTermマクロでincludeすると、マクロの流れは次のようになります。

includeは制御を移すコマンド

includeはその名称から外部ファイルを読み込んでメモリ展開するコマンドだと勘違してしまいがち(わたしは勘違いしました)ですが、TeraTermマクロの場合はそうでなく、正確には外部ファイルに制御を移します

この時点で、それならsub1はsub.ttlのローカルサブルーチンとして扱われるのか?便利じゃん!とわたしは想像しましたが、違いました。次のようなマクロはエラーになります。

val = 123
messagebox val 'main.ttl'

include 'sub.ttl'

messagebox val 'main.ttl'

call sub1
end

:sub1
val = 456
messagebox val 'sub1:main.ttl'
return
:sub1
messagebox val 'sub1'
val = 321

このマクロを実行するとsub.ttlで「Label already defined」エラーとなります。このエラーは「ラベルの多重使用」という意味です。ラベルが多重定義されている、つまりsub.ttlからmain.ttlのsub1が見えている、という事になります。

includeは実行されるまで中身が不明

includeの仕様に1点注意する必要があるのは「includeが実行されるまでファイルの中身が参照されない」という事です。どういう事かというと、includeしているファイル名が存在しなくても実際にincludeされるまで参照されないのでエラーになりません。includeが実行されなければエラーになりません。

つまり、こういう事です。まず、呼び出し元のマクロ(main2.ttl)がメモリに展開されてsub1がラベルとして定義されます。この時点でincludeするsub.ttlの中身は不明です。次にinclude ‘sub.ttl’が実行されます。ここでsub1というラベルが既にmain2.ttlで定義されているため「Label already defined」エラーが発生します。

最初のmain.ttlで「Label requiered」エラーが発生したのは、include先のsub.ttlがメモリ展開されず単に制御を移しただけ、だからです。単にsub.ttlに制御を移しただけなので、main.ttlからはsub1というラベルが見えなかった、という事です。

さいごに

includeコマンドは非常に便利です。しかし、このコマンドが実行時に制御を移すのではなくメモリ展開する仕様であれば、事前にマクロをincludeして必要に応じてcallでサブルーチンを呼び出す、といった使い方ができて便利になるのですが、きっとそのような仕様変更は今後も無いと思います。

さいごに、includeコマンドを使用する際は、次の点に注意してマクロを書いてください。

  • include実行時に初めてファイルを読み込む
  • includeはメモリ展開でなく制御を移すだけ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)