みなさん、こんにちは。
前回で fl マクロの長い講義が一段落しました。疲れました?今回はここまで、取りこぼした小ネタを拾ってみたいと思います。
第5回で、#push/#pop built-in function
を説明しました。variable
の宣言と解放でしたね。ではここで次のコマンドを打ってみてください。
これはあなたの TACL 環境に宣言されている variable
の一覧です。だから結果は人によってまちまちです。サンプルを挙げてみましょう。
Directory :
FI | FL | FS |
LS | *UTILS | *UTILS_GLOBALS |
V | _COMPLETION | _COMPLETION^PROCDEATH |
_FROM_TACLBASE | _PROMPTER | _TACLBASE_FILE |
こんな感じで表示されます。ここで試しに1つ追加で variable
を宣言してみましょう。
おお、忘れてた。variable
名で使える文字種ですが、alphanumeric
に加えて "^"
と "_"
がOKです。
は大丈夫ですが、
などはだめなんです。で、話を戻して
と打つとどうでしょうか。test^var^1
が追加されましたね。varinfo
してみると、
Variable | L/D | Frm Mode | Type | File |
Process | ||||
TEST^VAR^1 | 1/1 | TEXT | 0 |
などと今まで通り表示されます。
ここでもう一度 test^var^1
を #push
してみましょう。
特にエラーは発生しません。同じ variable
を二重に宣言しただけです。
と思ったら大間違い。varinfo
を打ってください。
Variable | L/D | Frm Mode | Type | File |
Process | ||||
TEST^VAR^1 | 2/2 | TEXT | 0 |
判りますか? L/D
のところが 2/2
に代わりましたね。#push
の機能は、文字通り stack
を push
するものです。2回 #push
を実行したということは2個の test^var^1 variable
を stack
に積んだということになります。積まれた2つの variable
を区別するには、variable
名にレベル番号を付与してやります。test^var^1.1
とか test^var^1.2
とかです。具体的に見てみましょう。
いかがですか。それぞれ別の variable
として区別されていますね。L/D
のところは、L
が level
、D
が depth
です。レベル番号をつけないとトップレベルを指しますので、test^var^1
は test^var^1.2
と同じ意味です。
もちろん stack
に variable
が積み上がるとそれだけメモリーを消費しますので、必要のないものは #pop
で解放するようにしてください。stack
が積み上がっている場合、#pop
は最後に #push
したものから順番に解放していきます。
さらに安全策として #frame/#unframe built-in function
を紹介しておきます。#frame
と #unframe
はセットで使います。#frame
を実行後に #push
したすべての variable
は #unframe
実行時に自動的に #pop
されます。マクロの最後に #unframe
と書いておけば、マクロ内で #push
した variable
をすべて解放することができます。
なお、#frame
はネストできますので、複数の階層で variable
を管理することができます。そんな例は見たことはありませんが。ここで、#frame
の階層と variable
の L/D
は全く別物ということに注意してください。varinfo
の出力で、Frm Mode
として表示されているのが #frame
の階層番号です。L/D
とは別の値になってます。ま、この機能を使う人はいないよね。
もうひとつ思い出したので書いておきましょう。fl
マクロの作成で load
コマンドを多用しましたね。こんな感じです。
この /keep 1/
とはなんでしょうか。 "/"
は実行オプションを指定する記法なので特に意味はなし。意味があるのは keep 1
の部分です。
これを指定しないと、読み込むマクロは #push
されます。つまり2回 load
すると最初のマクロは消えずに下位の level
として残り、新しく読み込まれたマクロが上位の level
として追加されます。keep
で level
を指定するとその level
までマクロが #pop
されて、新しいマクロがその level
に配置されます。keep 1
なら、新しいマクロが macro.1
に相当する(つまり全部消して新しいのだけ残す)ということです。これも keep 1
以外はまず使いませんね。
なお、#push/#pop
は built-in variable
も #push/#pop
できます。一時的に built-in variable
の値を変えてまた戻したい場合、
などとやるよりも
とやる方がすっきりします。お勧めの小技です。
あ、そうそう #unframe
は variable
の掃除をしてくれます。マクロもまた variable
です。ということで、#frame
⇒ load
⇒ #unframe
とやると load
したマクロがきれいさっぱり消えてしまいます。愉快ですね。
うーむ、長くなってきたので、ここらで一服。お茶かたばこでもどうぞ……
休憩は済みましたか?それではもう一度 variables
コマンドの出力結果に戻りましょう。最初の行にある Directory :
ですが、":"
は単なる飾りじゃなくて、ちゃんと意味があるんですよ。variable
は directory
構造を持つことができ、その区切り文字が ":"
なんです。つまり Directory :
は root directory
であることを示しているのです。出力結果の中に *UTILS
とか *UTILS_GLOBALS
がありましたね。*
はその variable
が directory
であることを示しています。試しに UTILS directory
の下を覗いてみましょう。
TACL> variables utils
Directory :UTILS.1
*DP | *EMF | *EMSDINFO | *FIXERRS | *LMAP | PATHMAKER | |
PMPROJECT | ||||||
*RUNV | *TACL | *VIEWPT | *VPTLIB | *ZBAT | *ZPATHMKR |
今度はタイトル部分が Directory :UTILS.1
になりました。.1
というのは level
番号ですね。directory
も variable
なので #push/#pop
の対象になり得ます。utils
の中にも *
が付いたものがいっぱいです。その中から tacl directory
を覗いてみます。
見たことのある variable
がずらずら現れました。いわゆる TACL コマンドの実態は、ここに格納された variable
なのです。fileinfo variable
を例に取ってみましょう。昔やったコマンドで
TACL> varinfo fileinfo
Variable | L/D | Frm Mode | Type | File |
Process | ||||
:UTILS.1:TACL.1 | ||||
FILEINFO | 1/1 | ALIAS | 0 |
というのがありましたね。よく見ると、fileinfo
の上に :UTILS.1:TACL.1
と書いてあります。つまり fileinfo variable
は :UTILS.1:TACL.1 directory
の下にあるよ、と言っていたのです。ここでやっと話がつながりましたね。つまりこの fileinfo variable
を fully qualified name
で表示すると
となるわけです。
普段は :utils:tacl:
をさっくり省略して使っているわけですが、ではなんで :utils:tacl:
を省略できるのでしょうか。それは #uselist built-in variable
に理由があります。
TACL> #uselist
#uselist expanded to:
: :UTILS.1 :UTILS.1:TACL.1 :UTILS.1:DP.1
:UTILS:TACL
に path
が通っている、というわけですね。level
番号が付いてますから、UTILS
を変に #push
してしまうとすべての TACL コマンドが使えなくなってしまうこともあり得ます。もちろん UTILS.1
を #pop
してもアウトです。コマンドが使えなくなります。
それと、ここまで utils
と :utils
を同じものとして説明してきましたが、root
の :
を省略できたのも #uselist
に :
が入っているおかげでした。
さらに directory
にはもうひとつ秘密があります。seginfo
コマンドというものを実行してみましょう。
TACL> seginfo
Pgs | Pgs | Bytes | Bytes | ||||||
Segment File | Access | Now | Max | Now | Max | % | UC | Directory | |
$WORK01.#0012480 | PR | 14 | 1036 | 15584 | 2121728 | 0 | 5 | : | |
$SYSTEM.SYS17.TACLSEGF | SH | 252 | 1036 | 510852 | 2121728 | 24 | 4 | :UTILS.1 |
Segment File
なるものが登場しました。2行ありますね。$WORK01.#0012480
が1行目です。特殊な名称のこのファイルは temporary file
というものです。この行の Directory
欄に :
と記載されています。この temporary file
が root
である : directory
に割り当てられています。root
を仮想メモリに逃がすことで物理メモリの必要量を削減しています。
このファイルは Access
が pr (private)
になっているので書き込み可能領域です。特に指定しなければ、自作のマクロはここに格納されます。書き込み可能なので特に問題はありません。
2行目の $SYSTEM.SYS17.TACLSEGF
は UTILS
に割り当てられています。このファイルはマクロを格納したバイナリファイルです。こちらは Access
が SH (shared)
になっていますので、書き込み不可です。このファイルが割り当てられた directory
である utils
には variable
を #push
したりマクロを load
したりすることはできません。UTILS
にマクロを追加しようとしてもエラーになってしまうということです。
このセグメントファイルは HPE から直接提供されたものではなく sysgen
時に作成されたファイルです。さきほど UTILS
配下に TACL コマンドが格納されていると説明しました。その UTILS directory
の実態が TACLSEGF ファイルで、このファイルの中に TACL マクロが格納されています。TACL プロセス起動時に TACLSEGF ファイルが(自動的に) attachseg
されるので、ログオンしたユーザは TACL マクロを使用することができるのです。
整理します。マクロの配布方法はテキスト(ソース)ファイルから load
するやり方と、バイナリファイルを attachseg
する方法があります。ここまでの講座では load
しか説明していませんし、現場でも恐らく load
しか使っていないと思います。しかし自作のマクロでもバイナリのセグメントファイルを作成・配布することはできます。
attachseg
と load
の違いはなんでしょうか。本質的な差はないのですが
attachseg
の方が高速に配布できます。load
だと通常 root :
に全部配布します。これは本当はあまり美しくないやり方です。PCにファイルを作るとき、全てのファイル root ¥
配下に置いたりしますか? directory
を使って整理するでしょ?全部デスクトップに置いているって?美しくないですねぇ。セグメントファイルならどこかの directory
に割り当てて使いますので、用途や環境毎に美しく整理整頓できます。
load
した時に配布された variable
が画面に表示されます。attachseg
時は variable
名は表示されませんので、load
よりも少しだけ秘匿性が高くなります。(load
でも表示しない方法はあるし、attachseg
でもロジックまで隠ぺいできるわけではないので秘匿性も限定的)というくらいですかね~
セグメントファイルの詳しい扱い方までは説明しませんので、興味があれば直接問い合わせてください。
directory
は必ずセグメントファイルと紐付くわけではありません。セグメントファイルを使わない directory
もあり得ます。セグメントファイルを使うには directory
と紐付けないといけないというだけです。
ちなみに、TACLSEGF
のように TACL に関連するファイルは、他にどのようなものがあるかご存じですか?
$SYSTEM.SYSnn | ||||||
CODE | EOF | LAST MODIFIED | OWNER | RWEP | PExt | |
SExt | ||||||
TACL | O 100 | 4351080 | 10DEC2008 6:42 | 255,255 | NUNU | 112 |
112 | ||||||
TACLBASE | 101 | 172528 | 10DEC2008 11:37 | 255,255 | NUNU | 14 |
28 | ||||||
TACLINIT | 101 | 8338 | 19APR1995 22:30 | 255,255 | NUNU | 14 |
28 | ||||||
TACLSEGF | O 440 | 512000 | 30SEP2009 15:21 | 255,255 | NUNU | 14 |
14 | ||||||
$SYSTEM.SYSTEM | ||||||
CODE | EOF | LAST MODIFIED | OWNER | RWEP | PExt | |
SExt | ||||||
TACLLOCL | 101 | 2344 | 05MAR2010 19:47 | 255,255 | NUNU | 112 |
112 | ||||||
$vol.subvol | ||||||
CODE | EOF | LAST MODIFIED | OWNER | RWEP | PExt | |
SExt | ||||||
TACLCSTM | 101 | 2150 | 15MAR2006 10:24 | 255,255 | AAAA | 14 |
42 |
こんな感じですね。簡単に説明しときましょ。
fi variable
などの全ユーザ共通マクロは TACLLOCL
の中で load
することが多いですね。TACLCSTM
の中で load
するなり attachseg
するなりして使用します。このファイルは自分のデフォルト subvol
の中にあります。ついでなので、root directory
以外に load
する手順を紹介しておきます。まず、コマンド用に directory
を作成します。こんな感じ。
そして、current directory
を移動して
そこに load
します。
#home
は current directory
を示す built-in variable
です。この時点で macsrc
に定義したマクロは使用できますが、こんな使い方になります。
以前は root
に置いていて、なおかつ root
が #uselist
に含まれているので、
でも使えましたが、今回は mycmd directory
に掃き出したので directory
名を修飾しないと使えません。これでは不便ですので、root
にあるのと同じように使用するために #uselist built-in variable
に追加します。
以上の処理を TACLCSTM
に書いておけば、directory
を整理しつつ、特に意識することなく自前の TACL マクロを使うことができるようになります。
今日はここら辺で終わりにします。お疲れ様でした。次回からは外部プログラムとの連携でもやってみますか。それでは次回をお楽しみに!Au revoir!