みなさん、こんにちは。
これまでは既存のマクロを読み替える例ばかり紹介してきました。そろそろ自分でロジックを組む話に入りましょう。前回予告した variable
の展開が出てきます。今回はエンジン全開で行きますよ。
まず、何か作ってみましょう。fileinfo
マクロではファイルの最終更新日が表示されますが、最終オープン日時を知りたいこともあります。fup
コマンドでも出せますが、表示結果が散漫です。fileinfo
のような書式で出したいので、これを自作します。
最終更新日を取得するには #fileinfo
を使います。#
で始まっているので、これは built-in function
ですね。#xfileinfo
とよく似た名前ですがまったくの別のものです。試しにやってみましょう。LASTOPEN_GMT
オプションを付けて、前々回作成したマクロソースファイル名を指定します。
どうですか。
などと表示されましたね。数値は人によってまちまちですが、18 桁の数字が表示されたと思います。
ここではポイントが2つあります。1点目は “expanded to:
” です。これが「展開」です。built-in function
の処理結果を取り出したり、 variable
に保存された内容を取りだしたりすることを「展開」といいます。この例では#fileinfo built-in function
の処理結果が 212340079887808120
だったということです。うん、あまり大した話じゃなかったですね。ただ、展開の重要な点は、「展開とは置き換えである」ということです。展開の本来的な動作からいうと
これは
と入力したのと同じ意味になります。つまり元のマクロが展開結果に置き換えられたということです。
そしてここにもう1つヤヤコシイ話が出てきます。コマンドラインで数字を入力してもエラーになるだけですよね。でも上記はエラーになっているようにはみえません。実は、built-in function
の場合コマンドラインで直接展開すると “expanded to:
” の注釈付きで展開結果を表示してくれる機能があります。これは built-in function
の特徴で、variable
とは扱いが違うところです。212340079887808120
と展開される variable
を用意して同じように展開させてみると、今度はエラーになります。後ほど variable
の展開を紹介するときに実演してみることにします。私の宿題にしておきましょう。
2つ目のポイントは 212340079887808120
という数字です。TACL では日付・時刻精度を2種類持っています。
Julian timestamp, a four-word timestamp
Local timestamp, a three-word timestamp
Julian timestamp
は紀元前4713年1月1日 12:00 からの経過時刻をマイクロ秒(マイクロ秒:100万分の1秒)の精度で保持しています。Local timestamp
は 1974年12月31日 0:00 からの経過時刻を 0.01 秒(100分の1秒)の精度で保持しています。212340079887808120
は Julian timestamp
です。
このように書くと、「Julian timestamp
の説明に four word
と書いてあるけど、212340079887808120
は 58 bit じゃないか。これなら two word
で十分ではないの?」と、したり顔で指摘する人が出てきたりするものです。この手の質問には先生も手を焼くなぁ……えーと、TACL/TNS は 16 bit machine なのです。よって four word
は 64 bit です。three word
は 48 bit。だから 58 bit の Julian timestamp
を管理するには four word
必要でしょ?
話を戻して、212340079887808120
という数字のままでは何日の何時かさっぱり分かりません。で、変換関数を使います。まず LASTOPEN_GMT
というようにこれは GMT なので JST に変換します。#CONVERTTIMESTAMP
という built-in function
に、GMT ⇒ LCT に相当するオプション 0
を付けます。
展開された結果の最初の 0
はエラーコードです。タイムスタンプとして不正な値なら 1
が返ります。JST に直すと 212340112287808120
ということがわかったので、これを人が読める形にしましょう。
先頭の 2457640
は通算日、ここでは使わないので無視するとして、その後ろに注目すると、
2016年9月8日 16時31分27.808120秒
が得られます。$vol.subvols.macsrc
を最後にオープンしたのはこの時間ということが分かります。
前回までならこのくらいの分量で今日は終わり、となりますが、今回はまだまだ行きますよ。休憩は各自でどうぞ。
以上の流れで情報は得られましたが、1つ1つ手作業でちっともマクロではありません。ここまではあくまでもパーツの紹介。これを1つのマクロに組みあげます。ここからは実行結果は省略していきますので、ぜひ実習を交えて読んでください。
まず、第一ステップ。#fileinfo
の結果を表示するところまでをマクロにしましょう。マクロ名は fl
にします。
以上の7行を macsrc
に追加します。これで macsrc
は ls
マクロと fl
マクロを定義するソースになりました。忘れずに load
したら実行します。
前に #fileinfo
を直接実行したときと同じような表示内容ですが、数字は違いますね。fl
マクロを追加するときにオープンしたため、タイムスタンプが変わっています。
ではマクロの説明をしましょう。
#push fn1
は variable
の宣言です。この形式では TEXT type の variable
が宣言されます。次の
#set fn1 %1%
は、宣言した fn1 variable
にパラメータを代入しています。%1%
は macro
のパラメータでしたね。次が例の built-in function
ですが、パラメータが変わりました。
#fileinfo /LASTOPEN_GMT/ [fn1]
さきほどはファイル名を直書きしましたが、今度は variable
を使っています。[ ]
で fn1
を囲っています。これは fn1 variable
を展開しろ、という意味です。[ ]
で囲わずに
#fileinfo /LASTOPEN_GMT/ fn1
と書いてしまうと、fn1
という名前のファイルの最終更新日を取りだします。[fn1]
とすることで fn1
に格納された名前(%1%
、つまりマクロに与えたパラメータ)のファイルの最終更新日を取りだします。
さて、さきほど宿題にしていたところを実演してみますか。TACL のコマンドラインで次のように操作してみてください。
さあ、どうですか。
とエラー表示されましたね。つまり testmsg
が展開されて
と入力したのと同じことになったわけです。今度は built-in function
ではないので、エラーになってしまいました。なお、[ ]
を付けないで
としても同じ結果になります。variable
名をコマンドラインで入力すると、マクロと解釈して自動的に展開されるからです。
おっと、ここで
とエラー表示された人はいませんか?そのときは
と入力してください。#informat
については次回説明します。
宿題パートの最後に
と入力しておいてください。これは宣言した testmsg variable
の削除です。ソースファイルに戻ってみると、こちらにも最後に
#pop fn1
とあります。これも fn1 variable
を削除しています。#push
と #pop
はペアで使用するようにしましょう。(#pop
を忘れるとどうなるか、とか防衛策は、とかはまた後日)
#fileinfo
の結果は GMT だったので、これを JST に変換するステップを追加します。ソースファイルを修正しましょう。
どうでしょうか。#fileinfo
も [ ]
で囲われてしまいました。さきほどまでは #fileinfo
の結果は画面に表示されていましたが、 [ ]
で囲うことで展開結果を別の variable
に代入することができるようになります。ここでは ts1
という variable
に一度代入して、さらにそれを #CONVERTTIMESTAMP
に与えています。画面には #CONVERTTIMESTAMP
の結果が表示されます。
しかしまだ時刻として読める形ではありません。今日の最後に JST を読める形に変換してみましょう。#interprettimestamp
を使うよう、またまたソースファイルを修正します。
おや、#setmany
って何でしょう。#CONVERTTIMESTAMP
の実行時を思い出してください。結果が2項目ありましたね。
#set ts2 [#CONVERTTIMESTAMP [ts1] 0]
と書くと、1つ目と2つ目の項目が両方とも ts2
に代入されてしまいます。#interprettimestamp
で使用するのは2つ目の項目だけなので、項目を分離しないといけません。そういうケースで使うのが #setmany
で、複数の項目を複数の variable
に分配してくれます。
#setmany err ts2,[#CONVERTTIMESTAMP [ts1] 0]
とすることで、エラーコードを err variable
に、タイムスタンプを ts2
にそれぞれ代入してくれます。#set
と異なり、“,
” が途中に入っていることに注意してください。
それでは実行してみましょう。
日付や時刻がバラバラッと表示されました。一応、役には立ちますが、見た目が、きれいではないですよね。次回はこれを成型することを考えます。
今回は長かった。お付き合いありがとう。お疲れ様でした。Au revoir!