PROCライブラリーを一時的に変更する

By 神居 - Last updated: 金曜日, 5月 17, 2019

STARTコマンドで指定するプロシージャーやJCLから呼び出すカタログ・プロシージャーを格納するプロシージャー・ライブラリーは、通常JES2の起動プロシージャーに定義されていて、システム稼働中に変えることはできませんでした。しかし、現在のz/OSではJES2コマンドで簡単にPROCLIB定義を変えることができます。業務系のシステムで使うことはないでしょうが、開発やテスト系のシステムでは役に立つこともあるかも知れません。
一時的に、現在のPROCLIBとは無関係に独自のデータセット内のプロシージャー(JCL)を使うには、以下の手順でJES2コマンドを実行します。


独自のデータセットをPROCLIBとして追加登録する

これで、ART1.PROCLIBが独自のPROCライブラリーPROC01として登録されます。ただし、この時点ではART1.PROCLIBは、まだPROCライブラリーとしては使われません。



追加登録した独自のデータセットをPROCLIBから削除する


複数のデータセットをPROCLIBとして追加登録する

追加登録するプロシージャー・ライブラリーに、複数のデータセットを連結する場合は、DDパラメーターに連結順序を指定します。この例は、以下のDDステートメントと同じです。

$DPROCLIBコマンドで、現行のプロシージャー・ライブラリーを確認できます。PROC01として独自のプロシージャー・ライブラリーを追加登録する際に、独自のデータセットの後ろに、現在のプロシージャー・ライブラリーを構成するデータセットを追加指定すれば、一時的な変更中であっても、他の人の作業やジョブの実行に影響を与える心配はありません。

Filed in 知っておくと便利なテクニックなど

プロシージャー内のSYSINデータを記号パラメーターで変更する

By 神居 - Last updated: 水曜日, 5月 1, 2019

z/OS V1R13からは、プロシージャー内に直接ストリーム内データセット(SYSINデータ)を定義できるようになっています。さらに、z/OS V2R1からは、ストリーム内データセット(SYSINデータ)内でも記号パラメーターによるデータの置換ができるようになっています。これらは、昔からみんなが「出来たらとても便利なのに…」という機能の代表的なものと言えます。
元々のMVSとJES2の組み合わせでは出来なかったことなので、現在でも、プロシージャー内であるが故にDD * としたい数行のデータを別メンバーとして登録したり、SYSINデータをプロシージャー内ではなく呼び出すJCL側で定義して、データの一部をエディターで変更してからサブミットしたり、といったことを行っているかも知れません。
しかし、新しくサポートされた(と言っても5年くらいは前ですが)これらの機能はJCLの作成や運用をとても便利にします。ぜひとも覚えて、実務に応用していただければ、と思います。


サンプルJCLとプロシージャー

プロシージャー化しているのは、AMSのREPROによるVSAMデータセットのアンロード処理です。プロシージャーVSAMUNLDの呼び出し時に、入力データセット名を記号パラメーター(JCLシンボル)&DSで渡しています。プロシージャー内では記号パラメーター&DSを、SYSUT2 DDステートメントのDSNパラメーターとSYSIN DD *で定義しているストリーム内データの中にあるIDS(&DS)の部分で使っています。ここの&DSの箇所も実際のDSNに置き換えることができます。
従来であれば、ストリーム内データの中で記号パラメーターを使っても、このサンプルであれば、ただの文字「&DS」としてしかユーティリティーには渡りませんでした。しかし、このサンプルのようにEXPORTステートメントとDD *ステートメントのSYMBOLSパラメーターを指定することで、&DSの部分が「TRU1.CUSTOMER」のように実際のDSNに置き換えることができるようになっています。

サンプルではストリーム内プロシージャーを使用していますが、カタログ式プロシージャーでも勿論使用することができます。

Filed in ありがたいサンプルJCL

アセンブラーで区分データセットのディレクトリー部を読み込む

By 神居 - Last updated: 水曜日, 5月 1, 2019

区分データセットのディレクトリー部は、構造的には256バイト固定長の非ブロック化レコードの順次データセットと同じです。そのため、区分データセット内にどのようなメンバーが格納されているかを知るために、BSAMまたはQSAMによってディレクトリー・ブロックを読み取る方法が昔から使われてきました。この記事は、以前に掲載した「COBOLで区分データセットのディレクトリー部を直接読むサンプル」をアセンブラー言語用に作り直したものです。


QSAMのGETマクロでPDSディレクトリー部を読み込む

実際のディレクトリー・ブロックには、8バイトのキーが付いており、キー部8バイト+データ部256バイトでDASD上に書き込まれています。PDSのDIRブロックの8バイトのキーには、そのディレクトリー・ブロックに格納された最後のメンバーエントリーのメンバー名が入っています。このキーは、割当て済みのDIRブロックから使用済みの最後のブロック位置を判定する目的などで利用できます。OSのように直接チャネル・プログラムを使ってアクセスする場合、目的のメンバーが格納されているDIRブロックを1回のサーチ動作で探すこともできます。
アクセス方式によってキーにアクセスするにはBSAMを使用する必要がありますが、サンプルの処理ではキーを使用しないので、ここではCOBOLのサンプル同様にQSAMでアクセスしています。非ブロック化レコードなので、BSAMでもQSAMでもアクセス単位はブロックですが、順次データセットのアクセスでは一般的に使われるQSAMを使用しています。

読み込んだPDSディレクトリー・ブロックは、文字'>>>'と'<<<'で囲んでSYSUT2データセットへ書き出しています。>>>と<<<に囲まれた部分が読み込んだディレクトリー・ブロック内容です。ISPFブラウザーなどのHEXモードで表示すれば、区分データセットのディレクトリー・ブロックの構造が目視できます。
※区分データセットのディレクトリー内容は「ファイルシステム・区分データセットのディレクトリー構造」にも解説してあります。
なお、PDSEであっても、PDS同様に従来から知られているBSAMやQSAMによってディレクトリー・ブロックを読み込むことができます。PDSEの内部構造にはPDSと同じディレクトリー・ブロック・データはありませんが、アクセス方式によってアクセスする場合は、プログラムに対しては従来の区分データセットのメンバー部がエミュレートされるようになっています。


DESERVマクロでPDSディレクトリー部を読み込む

QSAMやBSAMでディレクトリー・ブロックを直接読み込むのではなく、DESERVマクロを利用する方法です。DESERVは、DFSMS/MVS V1R3からサポートされた比較的新しいサービスです。ディレクトリー・ブロックがそのままのイメージで入ってくるのではなく、DESERV内部の型式に展開された内容でメンバー・ディレクトリー情報が渡されます。そのため、サンプル・プログラムの出力もメンバー名+ディレクトリー部のユーザー・データで書き出しています。ユーザー・データ部分(>>>と<<<に囲まれた部分)はバイナリーのまま出力していますので、必要に応じてISPFブラウザーなどのHEXモードでの表示に切り替えて下さい。

DESERVマクロは少々複雑です。特に、返答領域であるSMDE(システム管理ディレクトリー項目)は、従来のPDSデータセットのメンバー・エントリーよりも構造が複雑です。マッピングされるDSECTも多く、BSAM/QSAMによるディレクトリー部アクセスに比べると煩雑になります。ISPF等で編集するJCLやソース・プログラムなどのライブラリー・データセットであれば、PDSでもPDSEでもBSAM/QSAMによる方法が手軽でしょう。
ただし、ロード・モジュールを格納しているPDSEデータセットの場合は、ロード・モジュールの形式がプログラム・オブジェクトと呼ばれる新しい形式に変わっています。プログラム・オブジェクトは、別名であれば1024バイトという長い名前を付けることもできます。その場合は、DESERVマクロでないとアクセスできません。

Filed in MVS実践アセンブラー・プログラミング

QSAMでPDSメンバーにアクセスする

By 神居 - Last updated: 火曜日, 4月 30, 2019

順次データセットは、QSAMを利用すれば論理レコード単位で簡単にアクセスできます。区分データセット用にはBPAMが提供されています。しかしながら、BPAMの場合はブロック(物理レコード)単位でないとアクセスできず、ブロックを論理レコードにバラしたり(あるいは論理レコードをまとめてブロックにまとめたり)バッファリングの制御なども自分でやらねばなりません。バッファリング制御はオプション処理的なものなので、やらなくてもアクセス自体はできます。しかし、ブロッキングとデブロッキングの処理は避けることができません。決して難しい処理ではありませんが、面倒であることは確かで、やらずに済むならそれに越したことはありません。
JCLでは、DSN=dsname(member)のようにデータセット名の後ろに()でメンバー名まで指定すれば、区分データセットのメンバーをQSAMでアクセスすることができます。これは、区分データセットのメンバー自体が、順次データセットと同じ構造を持っているからです。予めアクセスするメンバーが決まっているならJCL側の定義と組み合わせてQSAMでアクセスすることもできます。例えば、パラメーター・メンバーなどはその代表的なものの1つです。ところが、1つや2つのメンバーではなく、数十あるいは全部のメンバーに順番にアクセスしたい、となった場合はどうでしょうか?JCL側ではメンバー名まで定義できないことになります。そのような場合は、アクセスするメンバーを、JCLで定義する代わりに動的割り振り(DYNALLOC)でアロケーションしてQSAMでアクセス方法もあります。しかし、DYNALLOCは比較的オーバーヘッドが大きい処理なので、アクセスするメンバー数が多くなるとパフォーマンスの問題が出てきます。ISPFの起動プロシージャー内で、沢山のデータセットをALLOCコマンドで割り振っているとISPFが起動されるまでに時間が掛かることと同じです。
ここでは、メンバーをQSAMでアクセスでき、アロケーションのオーバーヘッドも掛からない方法として、JFCBを使用した区分データセットのオープン方法を紹介します。

このようなJCLで、SYSUT1 DDステートメントに定義された区分データセットの全メンバーを、SYSPRINT DDステートメントに定義されたデータセットへプリントするプログラムの例です。


DDステートメント定義情報の変更を行ってからデータセットをオープンする

JFCBを使用したデータセットのオープン処理を行うため、最初にJFCBを読み込みます。JFCBは、JCLのDDステートメントの定義情報だと考えればいいです。読み込んだJFCBには、JCLのDSNパラメーターで指定されたデータセット名は格納されていますが、メンバー名は当然ながら入っていません。メンバー名指定なしの区分データセットをQSAMでオープンすると、ディレクトリー部の先頭に位置付いてしまい、レコード形式などが不一致となるのでS013でABENDします。DSNパラメーターにメンバー名が入っていれば、オープンした時にそのメンバーの先頭に位置付けられてQSAMでアクセスができます。
従って、読み込んだJFCBのメンバー名フィールドにアクセスしたいメンバー名をセットすれば、JCL DDステートメントのDSNパラメーターに(メンバー名)まで指定したことと同じ状況を作り出せます。オープン前にJFCBを読み込み、その内容(JCL DDステートメント情報)を変更してからオープンすることもできます。

ポイントになる箇所は太字で示してあります。メンバー名はJFCBELEMフィールドに設定します。DDステートメントにDSN=dsname(member)と定義されると、JFCBのJFCBDSNMにdsnameが、JFCBELEMにmemberが格納されます。従って、オープン前にJFCBELEMにメンバー名を設定すれば、DDステートメントでメンバー名まで指定したことと同じになります。なお、オープン時に区分データセットのメンバー部に位置付けさせるためには、メンバー名の設定に加えて、JFCBIND1フィールドのJFCPDSフラグをオン(1)にする必要があります。JFCPDSフラグは1度オンにすれば、MVS(DFSMSdfp)側で変更されることはありません。
JFCBの準備ができたら、データセットをQSAMでオープンします。RDJFCBマクロで使用したDCBを指定してOPENマクロを発行します。この時、OPENマクロにTYPE=Jパラメーターを追加します。TYPE=Jは、JFCBがユーザー側で提供されたことを示します。TYPE=Jパラメーターを忘れると変更後のJFCBは反映されません。メンバーの読み込みならGETマクロ、メンバーの書き込みならPUTマクロを使用します。QSAMなので論理レコード単位でのアクセスです。1つのメンバーの処理を終えたら、データセット(メンバー)をクローズします。別のメンバーへの処理を行うのであれば、JFCBELEMに次のメンバー名を設定してオープンから繰り返します。
なお、メンバー内容を書き込みする場合、クローズ時にメンバー・ディレクトリーのユーザー・データ部分は消えてしまいます。ISPFエディターで保管したメンバーを、アプリケーション・プログラムのQSAMアクセスで書き直すような場合、メンバーのISPF統計データは消えてしまうことは知っておく必要があります。必要であれば、BLDLマクロなどでメンバー・ディレクトリーの情報を読み取っておき、後でBPAMでオープンし直してSTOWマクロで必要なユーザー・データを書き込む、などの処理を追加します。
※JFCBの読み込み方とRDJFCBマクロの使い方は、「DD文定義情報を得る(DEVTYPEとRDJFCB)」に解説してあります。


サンプル・プログラム(PDSPRINT)ソース・コード

PDS内メンバーのQSAMアクセスをセットアップした後、PDSデータセットのディレクトリー部をやはりQSAMでオープンします。
GETマクロでPDSディレクトリーブロックを1ブロック読み込み、その中に登録されているメンバーエントリーを取り出します。メンバー名をJFCBにセットしたら、PDSメンバーをオープンしてGETマクロで1レコード読み込み出力側のデータセットに書き出します。メンバーがEODになるまで処理を繰り返し、PDSメンバーをクローズします。
読み込み済みディレクトリーブロック内の次のメンバーエントリーに位置付けて、メンバー名をJFCBにセットする処理から繰り返します。ディレクトリーブロック内の全てのメンバーを処理し終えたら、次のディレクトリーブロックの読み込みから繰り返します。次に処理すべきメンバーエントリーのメンバー名がxFFFFFFFFFFFFFFFFであれば(これ以上メンバーがないことを示す)、PDSデータセットのディレクトリー部と出力側のデータセットをクローズしてプログラム処理を終了します。
※PDSディレクトリーの読み込み方は、「アセンブラーで区分データセットのディレクトリー部を読み込む」に解説してあります。

Filed in MVS実践アセンブラー・プログラミング

サブプール・ゼロ(0)の落とし穴

By 神居 - Last updated: 火曜日, 4月 30, 2019

プログラムの外側に領域を確保して使用する際、GETMAINマクロで長さだけを指定すると、領域はサブプール0に獲得されます。これ自体は何も問題ありませんし、使い方として誤ってもいません。ただ、獲得された領域を使用する際に、バグって領域を超えてアクセスした場合、レジスター保管域を壊してしまう可能性があります。特に、プログラム内で最初に発行されるGETMAINで獲得された領域を使用する場合です。

MVSは、タスクで最初に実行されるプログラム(ATTACHされるプログラム)が使用するレジスター保管域(RSA)の領域をサブプール0に確保します。MVSがGETMAINするRSA領域は144バイトですが、その後ろにEXECステートメントのPARMパラメーターで指定された文字列格納領域が続きます。PARMパラメーターを指定しなくても、パラメーター・リスト領域と長さ格納域は必要になるので、最低でも160バイトは使用されます。
既にサブプール0の最初のページが切り出された状態で、サブプール指定なしのGETMAINが発行されると、要求された領域長が未使用領域長以下(例えば、2000とか3000バイト)なら、最初のレジスター保管域と同じサブプールが使われます。MVSはページ内の後方から領域を割り当てるため、プログラムが確保した領域は、下図に示すように、MVSが最初に獲得したレジスター保管域の直前に配置されます。
そのため、プログラムにバグがあり領域を超えて書き込みを行うようなことがあると、レジスター保管域内を破壊してしまうことになります。レジスター保管域を超えてもなお書き込みを続けようとするとページの末尾に達します。その後ろのページが割当て済みであれば、そこを破壊するか、記憶保護キー不一致(S0C4)でABENDさせられます。割当て済みのページが続いていなければ、ページ変換例外(S0C4)でABENDさせられます。
後続の領域を破壊した時点でABENDすればまだ原因は追跡し易いですが、別の処理や別プログラムで使用している領域を壊すだけ壊して抜けてしまうと、その後全く別の部分でエラーになることが予想できます。例えば、呼び出し元へ戻る際にABENDしたり、誤った内容でレジスターを復元してしまう、といったものです。そのような場合のデバッグはかなり面倒です。(例えば、レジスター保管域をNULLでクリアーしてしまうと、レジスター復元後はGR13以外のすべてのレジスターが0になってしまうので、どこから調べていいのか途方に暮れてしまうかも知れない)

このようなことは、0以外のサブプールを明示すれば回避できます。MVSは、例え未使用領域が残っていても、同じページを複数のサブプールで共用するようなことはしません。従って、1から127のいずれかのサブプールを明示すれば、MVSが獲得したレジスター保管域やPARMパラメーター領域と同じページに割り当てられることはありませんし、これらの領域よりも高位のアドレス領域が割り当てられるので、レジスター保管域やPARMパラメーター領域の後ろにプログラムで使用する領域が割り当てられます。

とは言え、こんなことまで気にしながらプログラム・コードを考えるのは面倒です。実際には、プログラムを作るための知識ではなく、「こういうことも起き得るのだ」と言うデバッグする時の知識の1つとして知っておけばいいでしょう。

Filed in MVS実践アセンブラー・プログラミング

Xephon IBMメインフレーム技術情報誌がダウンロードできます

By 神居 - Last updated: 土曜日, 11月 17, 2018

1990年代、メインフレーム全盛期の最終期に英国のXephonという会社からIBMメインフレームに関する月刊の技術情報誌が刊行されていました。OSであるMVSだけでなく、ネットワークのSNA、セキュリティのRACF、オンライン処理のCICS、MQなどの分野別の技術情報誌として刊行されていました。世界中のシステム・プログラマーからの投稿に基づく技術情報が掲載されており、アセンブラーやREXXによる実際に利用できるツール・プログラムなどが満載されています。筆者が当時在籍した会社でも部門で購入していました。
既にというか、とっくに廃刊になっていて今となっては冊子としての入手はできません。しかし、現在では当時は有料であった冊子のバックナンバーのpdfが無料でダウンロードできるようになっています。すべてではありませんが、MVS UpdateというMVS、OS/390、z/OSの基本部分に関するものは、1998年1月から2005年12月までの刊行分がダウンロードできます。マニュアルに載っていないノウハウやMVS内部の仕組みなどを解説やサンプル・プログラムで得ることができる、今となっては大変貴重な技術資料です。MVS(z/OS)以外の、AIX、CICS、DB2、MQ、RACF、SNA、VSAM、VMの各分野の技術情報誌もダウンロードできます。
すべて英語ではありますが、今がダウンロードする最後のチャンスでしょう。海外のサイトなら今でもメインフレームの技術情報は溢れていますが、最近は以前から利用できたサイトが次々の閉鎖されているのも事実です。運営者も年齢を重ねているのでしょうか、いつアクセスできなくなるとも限りません。興味のある方は是非ダウンロードしてはいかがでしょうか。

現在、Xephonのマガジンは「CBTTAPE.ORG」というサイトからダウンロードできます。
CBTTAPEのサイトにアクセスしたら、画面中程にある「Xephon Magazines in PDF format are available to download now!」を探してみて下さい。そこのリンクからpdfが格納されているディレクトリーが示される画面に行くことができます。わかりにくい時は、CBTTAPEの画面で「xephon」の文字列を検索してもいいでしょう。直接のurlは「http://www.cbttape.org/xephon/」です。

Filed in メインフレーム関連書籍

CLISTでISPFを学ぶ(1)

By 神居 - Last updated: 日曜日, 9月 30, 2018

CLISTでISPFを学ぶ(1):JCLをサブミットして、ジョブログ(実行結果)ISPFブラウザーで確認する

ISPF(Interactive System Productivity Facility:対話式システム生産性向上機能)は、z/OSを使う上で必須で使えなければならない機能です。ISPFを利用する機能として、JCLやプログラムのソースを編集しサブミットしたり、データセットの一覧を表示して改名や削除などのさまざまな操作を行うことができるPDF(Program Development Facility)や、ジョブの実行結果を見たりするSDSF(System Display and Search Facility)が有名で、開発部門、運用部門、管理部門などメインフレーム運用に携わるあらゆる業務で日常的に使われています。
しかしながら、ISPFとはPDFやSDSFのことを指すのではありません。PDFやSDSFなどのさまざまな機能プログラムやツールを、TSO画面を通じて対話式で処理を実行するための土台となるものです。多くのエンジニアが日々の業務で使用するツールがPDFやSDSFであるために、ISPF=PDF+SDSFと思われていることも多いですが、実際はISPFという土台の上でPDFやSDSFという対話型処理を行うプログラムが実行されています。これは、OSとアプリケーションの関係に似ています。OSという土台の上でアプリケーション・プログラムが動くわけです。ISPFでは、土台となる機能が「DM(Dialog Manager):ダイアログ・マネージャー」と言い、DMという土台の上で動くプログラムを「ダイアログ」と言います。PDFは、ISPFが提供する代表的なダイアログの1つです。
メーカーやベンダーから提供されるダイアログを使うだけのことが多いですが、土台であるISPF/DMのしくみを学び、直接自分で土台を使うことができるとz/OSの操作や運用の幅が広がります。ダイアログは必ずしもプログラムである必要はなくCLISTでもかまいません。CLISTだけでの処理はコマンド・ラインがベースになりますが、ISPF/DMのサービスを呼び出すことによって画面パネルを使用した対話型処理として実装することができます。少し複雑な処理であれば、REXXを利用するといいでしょう。REXXは、メインフレームからSystem i、AIX、z/LinuxなどのIBMコンピューターに共通のスクリプト言語です。

ISPF/DMに関連するマニュアルには以下のものがあります。実際に作ってみる際は、本サイトの記事だけでなくマニュアルも併せて参照して下さい。

最初に紹介するのは、CLISTからユーザー独自のISPFパネルを表示して、入力されたデータ内容に応じた処理を行うサンプルです。以前に、CLIST入門編の最後に紹介した「JCLをサブミットして結果をISPFブラウザーで表示するCLIST」をISPFパネル入力にしたものです。CLISTによるデータ入力の基本はコマンドライン・ベースですが、ISPFパネルを利用すると、より実践向けにできます。ISPFサービスの呼び出しについては、以前のCLIST入門(9)にも解説があります。



業務で使う、ちょっとした定型的な処理などは、ISPFのサービスを組み合わせることで簡単なパネル・アプリケーションとして作ることもできます。この連載では、ISPFの土台であるISPF/DMの使い方の基本を紹介して行こうと思います。

Filed in CLIST(コマンドプロシージャ)とISPFダイアログ

記号*を活用する

By 神居 - Last updated: 金曜日, 7月 13, 2018

シンボル(記号)*を活用する:レベル1タイトル&#9312


アセンブラーにはロケーション・カウンターという仕組みがあります。アセンブラー言語でプログラムを書く際は、B ERROR、ST R1,AREA2のように命令やデータ領域を名前で指し示すことができます。本来は、B 324(,R12)、ST R1,248(,R12)のように分岐先の命令やデータ領域のアドレスを、ベース・レジスター番号と変位もしくはベース・レジスター番号とインデックス・レジスター番号および変位の組み合わせで書かなければなりません。
しかしながら、ベース・レジスターやインデックス・レジスターの番号はともかくとして、変位に関しては簡単には求められません。参照しようとしているデータ領域が、プログラムやテーブルの先頭から何バイト離れているところにあるのかを正確に求めることはとても大変です。プログラムの先頭から書いた1つ1つの命令の長さを積み上げ、境界調整などが入っていればそこでのアドレスのずれを調整し、データ領域なら変数や定数の長さなどを正確に計算して行かなければなりません。作業自体も大変ですが、一番の問題は間違えやすいということでしょう。プログラムの先頭に近い命令の変位計算で間違えれば、そこから後ろ、つまりそのプログラムで書いた命令やデータ領域のほとんどの変位も間違ってしまいます。こうなるとアセンブラー言語は難しいとか、嫌い、とかではなくそもそも使い物にならなくなってしまいます。
それ故、アセンブラー言語では命令やデータ領域を機械命令が規定する直接の形式(ベース・レジスター番号と変位の組み合わせ)だけでなく、記号(名前)で指定できるようになっているのです。しかし、最終的なオブジェクト・モジュールにする際は記号が示す命令やデータ領域の位置を機械命令が規定するベース・レジスター番号と変位の組み合わせに変換しなければなりません。正確な変位を計算するために使用されるのがロケーション・カウンターです。

プログラム内の各モジュールは、セクションという単位に区分され、命令やデータの集合体はCSECT(制御セクション)、データ領域のレイアウト定義はDSECT(見かけセクション)と呼ばれます。一般的にはソース・プログラム・コードの最初のCSECTがプログラム・モジュールの先頭になり、ロケーション・カウンターもCSECTを先頭(0番地)とするアセンブラーの内部カウンターです。LRなどの2バイト命令を1つ書けばロケーション・カウンターは2つ進み、STやAなどの4バイト命令を1つ書けばロケーション・カウンターは4つ進みます。F型定数を1つ書けばロケーション・カウンターは4つ進み、境界調整が入れば4バイト・バウンダリーに合わせるためのずれの分だけ1?3つ進みます。20バイトの文字列領域を定義すればロケーション・カウンターは20進みます。このようにして、プログラム中に記述された各々の命令やデータ領域がセクションの先頭からどの位離れているかの離れ度合いをロケーション・カウンターによって管理します。

上記に述べたように、アセンブラー言語でもCOBOLやPL/Iなどと同じように命令やデータ領域を記号(名前)で示すことができます。しかし、アセンブラー言語では名前ではなく変位(ロケーション・カウンター)の値自体を積極的に参照して命令やデータを定義したい場合もあります。その際に使用されるのが、記号文字 * です。
*は、現在のロケーション・カウンターの値を示します。今自分がいる位置から何バイト先といった表現をしたい場合や、今自分がいる位置からテーブルの先頭位置を引き算してテーブル領域の長さを求めたい、といったことが簡単にかつ正確に記述できます。


*によって、ベース・アドレスを示す

*記号の使用例の最も代表的なものの1つです。CSECTの直後の*は、プログラム(CSECT)の先頭を示します。つまり、プログラムからの変位0の位置を示すことになります。USING *,12 は、レジスター12番をUSING命令を書いた位置のベース・アドレスを示すベース・レジスターにするという定義です。プログラムの先頭をベース・アドレスにする場合は、プログラム名の代わりに*を指定できます。

上記と全く同じプログラム・コードを*記号を使わないで書き換えたものです。PROGNAMEを変更する場合は、2箇所を同時に直す必要があります。2箇所でも3箇所でもエディターのChangeコマンドで簡単、というのは考えないで下さい。将来の保守を考え、修正箇所をなるべく少なくする、という意味では、記号*を使用する方がベターです。

同じ名前を繰り返し記述することを避ける方法として、名前をそのものを直接記述するのではなく可変記号で記述して、実際の値(この場合はプログラム名)をSETC命令で可変記号に設定する、という方法もあります。このようなコーディング方法も保守性を高める手段の1つですが、この記事は記号*を活用するということなので、あくまでもアドレス位置の指定に*記号を使うことで説明を続けます。どのように書いてもわかりやすく、間違えにくく、保守性も高い、というコーディングをすればいいのです。そのためにも、いろいろな書き方があること知っておくといいです。

比較的古いプログラムに多い書き方ですが、GR15に格納されている入口点アドレスを使わずにBALR命令などで自分自身のメモリー上のアドレスをロードする方法です。この場合、ベース・アドレスはプログラムの先頭ではなく、プログラムの先頭+6番地になります。STM命令で4バイト、BALR命令で2バイト、合わせて6バイト分の命令コードが埋め込まれるからです。BALR命令の結果、BALR命令の次の命令アドレスがGR12に入ります。したがってプログラムのベース・アドレスも先頭から6バイト離れた位置にUSING命令で設定する必要があります。

CSECTの直後にUSINGを書く、と固定化して考えてしまうと上記のような定石とはかけ離れたコーディングをすることになります。誤りではありませんが、わかりにくく、次にそのプログラムをメンテナンスする人が不思議がることになります。1つ前の例のように、BALR命令の次に、*記号を使ったUSING命令を書く方が自然です。ベース・レジスターにはBALR命令の次のアドレスが読み込まれるので、その位置をベース・アドレスに設定するUSING命令を書くわけです。その際にロケーション・カウンターの値を示す*記号を使えば、プログラムの先頭をベース・アドレスにする場合でも、少し離れた位置をベース・アドレスにする場合でも、同じコーディング方法でUSING命令を書くことができます。
記号*は、今現在の自分自身の位置(変位)を示す、ということを知っていれば、アセンブラー・プログラムのコーディングの様々な場面で応用できます。


命令列内のデータ領域を迂回する

レジスター保管域をハウス・キーピングのコードの中に定義した例です。レジスター保管域のように実行中に参照することがないデータ領域にいちいち名前を付けるのも面倒です。私自身は好んで使っていましたが、間違いの元だからきちんとラベルを付けてジャンプするように、と言う人もいるでしょう。

きちんとラベルを付けるとこんな感じです。個人的には好きになれない書き方です(あくまでも面倒という理由です)。レジスター保管域の長さなどは基本的に変わらないから、飛び先の変位を直接書いても問題ないと思います。分岐先を *+4+72 のように書くことは、元々はOSのマクロ命令から習ったことです。OSでもやってるんだから、まぁいいよね、と。もし、誰かに突っ込まれても、OSのマクロでもこういうコーディングしてます、と返せます。OSでもやってる、と言うとたいていの人は反論しません。でも、OSはこういう理由でやっている、アプリケーションはこういう理由からそのような方法は採らない、と説明されれば素直に従いましょう。そのような説明ができる人ならエンジニア、プログラマーとして信頼できるでしょう。

OPENマクロの展開形です。SVC呼び出しのパラメーター領域を、BAL *+8で8バイト先に(BAL命令が4バイト、パラメーターが4バイト)分岐して、命令列中のパラメーター領域を迂回しています。昔これを見て、*と+nの組み合わせで飛び先の変位を直接書いてしまう方法を知りました。もちろん迂回するロジック内の命令やデータがしょっちゅう増えたり減ったりする場合は使えませんが、一度コードを書けば基本的に変わらない部分に*記号で変位を直接書くことは、OSでもやっているコーディング・テクニックなのだと学んだわけです。


データ領域の長さや個数の計算に使う

データ領域の定義でも現在位置を示す記号*はいろいろな目的に使えます。テーブル構造の領域を定義するような際、テーブルを構成するエントリーの長さは計算しなくても、*記号とテーブルの先頭を示す名前の引き算の式で定義できます。この例では、TABENTLN EQU *-TABLEの部分です。なお、DC (TABENTLN*(TABENT#-1))X’00’における*は、位置を示す記号ではなく掛け算を示す記号です。

同じような領域の定義ですが、こちらはレコードのレイアウト定義です。レコードの長さは256バイトとして決めてあります。先頭から必要な項目を並べていき、残りを予約領域として定義するような場合、残りが何バイトあるかをいちいち計算する必要はありません。DC (RECORD+RECORDLN-*)X’00’のように、最後のフィールドの次の位置からRECORDの先頭位置を引き算して、それをレコード長から引けば残りのバイト数が計算できます。それを1バイト領域の複写因数にすれば残り領域を正確に埋めることができます。
アセンブラー言語でのデータ領域の定義では、記号*を使う使わないに関わらず、長さや個数などは直接自分で計算して書くのではなく、式を使ってアセンブラーに計算させることを覚えましょう。EXCELでの表計算のように、1箇所直せば連動して関連する部分も自動計算されるようにしておくと将来のメンテナンスも楽ですし何より正確です。人間は単純な足し算引き算でも間違えます。


配列内の連続したデータの定義に使う

上記のように定義すると、x00からxFFまで1ずつ増やした1バイトの値を256個並べた配列領域を定義できます。実際にアセンブルすると以下のようになります。

上記のように定義すると、xC1からxC9、xD1からxD9、xE2からxE9までの1バイトの値を26個並べた配列領域を定義できます。これはEBCDICコードの文字AからZを示します。文字AはEBCDICコードでxC1(193)、文字JはEBCDICコードでxD1(209)、文字SはEBCDICコードでxE2(226)であることを応用しています。変位の位置も実際にアセンブルすると以下のようになります。

ARRAYもALPHAも、それぞれの領域内の定数の長さは1ですから(複写因数が個数を示す、1バイトが何個という定義をしている)、*が示す変位も1ずつ増えます。ALPHAやARRAYが示すデータ領域の先頭の位置は変わりませんから、記号*が示すロケーション・カウンターの値は1ずつ増えていくことを利用したデータ定義の例です。

Filed in MVS実践アセンブラー・プログラミング

SYSINデータの内容を見る

By 神居 - Last updated: 火曜日, 6月 19, 2018

SDSFを使用してサブミットしたジョブのSYSOUTデータセットの内容を見ることは日常当たり前のようになされています。SDSFでは、SYSOUTだけでなくSYSINデータセットの内容を見ることもできます。

INPUT ONモードにする

SDSFコマンドINPUTを実行するとSYSINデータの表示のオンとオフを切り替えることができます。「INPUT ON」モードでは、SYSINデータセットがSTパネルなどから選択するODS(アクション文字S)やJDS(アクション文字?)パネルに、DD *やDD DATAで定義したSYSINデータの内容やデータセット属性も表示されます。z/OSの各種のユーティリティーを実行した際に記述したSYSINデータの内容を確認することができます。SDSF起動時は常にオフにされるため、このような機能があることに気づかないかも知れません。なお、INPUTコマンドはデフォルトでは管理者権限がないと実行できません(*1)。

*1 ISFPARMSをカスタマイズすれば他の権限のユーザーでもINPUTコマンドが利用可能になる。

INPUT ONでは、SYSINだけでなくCIテキストやジョブ・ジャーナルなどのJES2内部データも表示されるようになります。ジョブログやSYSOUT内容の確認では、通常必要ないものなので常時INPUT ONにすると、うっとおしいかも知れません。実行したユーティリティーなどが思うように動かない場合などに、JCL側で定義したSYSINデータそのままの内容を確認したいときなどに利用できます。こういう機能もある、ということを知っておけば使う場面も出てくるでしょう。

Filed in ISPFとSDSFのちょっと得する使い方

ISPFにSDSFコマンドを登録する

By 神居 - Last updated: 木曜日, 5月 17, 2018

SDSFをISPFコマンドとして登録すると、どのISPFパネルからでもSDSFを起動することができます。カスタマイズされたプライマリー・オプション・メニュー画面には、多くのユーザーでSDSFを「SD」あるいは「S」のオプション・コードで起動することができます。しかし、この場合のオプション・コード「SD」や「S」はプライマリー・オプション・メニュー画面でしか入力できません。この記事で紹介するのは、ISPFのメニュー画面にSDSFを登録することではなく、任意のISPFパネル(例えばDSLISTユーティリティー画面やエディター画面など)からのコマンド入力によってどこからでもSDSFを起動する方法です。

ISPFを2画面分割している状態で、JCLとプログラムをエディターで開いているとします。IBMデフォルトの状態では、JCLをサブミットして実行結果を見る場合、JCLかプログラムのどちらかを終わらせないとSDSFを起動できません。「=SD」などと入力したとしても(画面を閉じて)現在のダイアログを終わらせた上でSDSFを起動することになり、そのSDSFを終わらせればメニュー画面に戻ってしまいます。

現在の画面をそのまま保留にして、画面を上書きする形でSDSFを起動してジョブの実行結果を確認し、終わったら元の画面に戻れれば効率のよい作業ができます。ISPFの中でも多用されるオプション3.4のDSLISTは、メニュー画面からの起動だけでなく、コマンド「DSLIST」によってどのISPFパネルからでも起動でき終われば元の画面に戻れます。同じ事をSDSFでもできるようにします。


ユーザー・コマンド・テーブルを有効にする

独自のISPFコマンドを登録する前に、ISPFでユーザー・コマンド・テーブルの機能を有効にする必要があります。まずは、使用しているISPF環境でユーザーまたはサイト・コマンド・テーブルが有効になっているかを確認します。

ISPFのオプション3.9を実行します。ダイアログボックス右側のCommand serach orderのユーザー・テーブルとサイト・テーブルの両方が空白の場合は、コマンド・テーブルを追加しても使用されません。ISPF構成テーブルを修正して、ユーザー・コマンド・テーブルまたはサイト・コマンド・テーブルを有効にします。
以下にその手順の例を紹介しますが、ISPF全体に対しての修正なので必要ならシステム管理部門にやってもらうかその指示に従って下さい。断られる場合は、こちら(シンプルISPFメニューとクイック起動)の記事で紹介した独自のISPF起動CLISTを作り、自分のISPFだけにユーザー・コマンド・テーブルが有効になるように、ISPLLIBに自分用のロード・モジュール・ライブラリー(例えば、userid.UISPLOAD)を連結します。その後に、作成した自分用のISPFを起動してからユーザー・コマンド・テーブルが有効になるようにします。
任意のISPFパネルで「TSO△ISPCCONF」コマンドを実行すれば、構成テーブル・ユーティリティーが起動します。

構成テーブル・ユーティリティーが起動したら、修正後の構成テーブルのキーワードファイル・メンバーを格納するデータセット名とメンバー名を指定します。共用のISPF環境なら、サンプルのようにISPで始まるDSNのデータセットを準備してそこに格納します。個人のISPF環境なら、userid.UISPCONFのように先頭prefixをTSOのユーザーIDにするといいでしょう。メンバー名はISPCFIGUにします。ISPFは、カスタマイズされた構成テーブルのモジュール名をISPCFIGUにしますのでそれに合わせます(*1)。なお、ここで指定するデータセットはRECFM=FB、LRECL=251の区分データセットとして予め作成しておきます。スペース量は10TRKあれば十分です。
オプション1を選択して、システム・デフォルトの構成テーブル内容を反映した構成テーブルのキーワードファイル・メンバーを生成します。

*1 システム・デフォルトの構成テーブル・モジュール名はISPCFIGで、ISP.SISPLPAに格納されLPAに展開されている。システム・デフォルトを変更することはなく、必ずユーザー用構成テーブル・モジュールを作ることになるが、メンバー名はISPCFIGUで決まっている。ISPFは、起動時にISPLLIB DDステートメントに定義されたライブラリーからISPCFIGUを読み込む。ISPCFIGUがなければシステム・デフォルトのISPCFIGが使われる。

デフォルト値によって構成テーブルのキーワードファイル・メンバーが生成されます。このままPF3キーで終了させます。続いて生成されたメンバー内容がVIEWで表示されますが、再びPF3キーで終了させます。

最初に指定したキーワードファイル・データセットのメンバーとして構成テーブルの内容が保管されます。

次に、作成された構成テーブルのキーワードファイル・メンバーの内容を修正します。オプション2を選択します。

構成テーブル・ユーティリティーからエディターが呼ばれ、構成テーブルのキーワードファイル・メンバーの内容が表示されます。「APPLID_FOR_USER_COMMAND_TABLE」をスキャンして見つけます。/*と*/で囲まれ行全体がコメントになっているので、先頭と末尾の/*と*/を消して有効な行にして、値のNONEをユーザー・コマンド・テーブルの接頭辞(4文字まで)にします。USRとかUSERがわかりやすいでしょう。修正したらPF3キーでエディターを終了します。

このダイアログボックスが出たら実行キーを押します。キーワードファイル・メンバーが保管されたら構成テーブルをロード・モジュール化します。オプション4を選択します。

ダイアログボックスに、構成テーブルのロード・モジュール(ISPCFIGU)の格納先データセットを指定します。全体で共通に使うならISP.UISPLOAD、自分だけに有効にするならuserid.UISPLOADを指定すればいいでしょう。どちらのデータセットも事前に作成しておく必要があります。RECFMとLRECLはISP.SISPLOADと同じにします。スペース量は5TRKあれば十分です。なお、全体で共通に使うなら標準のISP.SISPLOADに格納してもかまいません。メンバー名ISPCFIGUはユーザー用構成テーブル・モジュールなのでデフォルトでは存在しません。もし存在しているようなら以前に別の目的で構成テーブルをカスタマイズしているのですから、その構成テーブルのキーワードファイル・メンバーを修正するべきです。その場合はシステム管理者に確認します。
ロード・モジュールの格納先データセットを指定したら実行キーを押します。モジュールの生成には少々時間が掛かりますがそのまま待ちます。

これでユーザー・コマンド・テーブルを使うためのISPF構成テーブルができあがりました。構成テーブルのロード・モジュールを格納したISP.UISPLOAD(またはuserid.UISPLOAD)をISPFの起動CLISTのISPLLIBに連結定義します。

ISPFを再起動すれば新しい構成テーブルが読み込まれます。ユーザー・コマンド・テーブルが有効になっているかを確認します。任意のISPFパネルで「TSO△ISPVCALL△STATUS」コマンドを実行します。内容が表示されたら「F△'USER△COMMAND'」を検索します。

ユーザー・コマンド・テーブルの接頭辞が「USR」になっています。これでユーザー・コマンド・テーブルを作れば有効になることが確認できました。

ユーザー・コマンド・テーブルを作成する

ISPFのオプション3.9を実行します。ダイアログボックス右側のCommand serach orderのユーザー・テーブルには、構成テーブルで登録した接頭辞が表示されていませんが、これは現時点ではISPTLIBライブラリーにユーザー・コマンド・テーブルのメンバーがまだ入っていないためです。

コマンド・テーブルの接頭辞に、USRやUSERなど構成テーブルに登録した名前を指定して実行キーを押します。

先頭行の左側フィールドにEを入力して実行キーを押します。

登録するコマンド内容のダイアログボックスが出たら、上記のように入力してダイアログボックス下側のUPDATEの文字の部分にカーソルを置いて実行キーを押します。コマンドが登録され1つ前の画面に戻るのでPF3キーを複数回押してユーティリティーを終わらせます。
登録したコマンド・テーブル・メンバーは、DD名ISPTABLに定義されたライブラリーに出力されます。通常、ISPTABLにはユーザー毎のISPFプロファイル・データセットが定義されています。DDLISTコマンドを実行してISPTABLデータセットの中を確認します。

PF8キーで画面をスクロールしてISPTABLを見つけます。ACTフィールドにBを入力して実行キーを押します。メンバーリストが表示されたら、接頭辞+CMDSの名前のメンバーを見つけます。接頭辞がUSRならUSRCMDSです。

それっぽい内容で登録されているはずです。ISPFを再起動すれば登録したユーザー・コマンド・テーブルが反映されます。

再度オプション3.9を実行すると、今度はユーザー・コマンド・テーブルが有効になっていることがわかります。接頭辞USRを指定すると先ほどと異なり、カレント・テーブルなのでVIEWしかできない旨のメッセージが表示されています。

プライマリー・メニュー以外の画面(DSLISTやエディターなど何でもよい)から「SDSF」と入力して実行キーを押してみて下さい。SDSFが起動されるはずです。そのSDSFを終わらせれば元の画面に戻れるはずです。コマンドを登録する際にTRUNCに2を指定したので、SDSFだけでなくSDSやSDでもSDSFが起動できるはずです。SD;DA、SDSF;STのようにSDSFコマンドを続けて指定することもできます。

以前の記事でISPFで3つ以上のパネルを使う方法を紹介しましたが(ISPFで3つ以上のパネルを使う)、画面を切り替えるためにコマンドを入力したり実際には面倒な操作です。コマンドによるダイアログの起動では、「=3.4」や「=SD」などのジャンプ機能と異なり現行画面のダイアログは終了しませんので、後から実行したダイアログが終われば元の画面が再表示されて続きの作業を行うことができます。
ジョブをサブミットした後、実行結果は確認するものの、また元のエディターに戻り作業を続け、ジョブログの内容は一度確認できればそれでよく表示し続ける必要はない、のならば画面を分割する必要なくSDSFを起動して元の画面に戻すことができます。同じようにDSLIST(オプション3.4)もコマンド(「DSLIST△**」「DSLIST△'PROJ1.WORK'」)で起動できますから、2画面の切り替えは継続して表示し続けたいツールに割当て、一時的に内容を確認したいようなものはコマンドで起動するようにすれば、2画面でも3つ以上のユーティリティーやツールを使い分けられます。現在のISPFでは、DSLISTからエディターやブラウズなどほとんどの作業ができますから、DSLISTとSDSFのコマンド起動だけ知っているだけでも日々の作業の操作効率は向上するでしょう。

*2 DSLISTやエディター、SDSFなどの画面を使うISPF機能やユーティリティーのこと。

なお、登録したユーザー・コマンド・テーブルを共用のコマンド・テーブルとして利用する場合は、コマンド・テーブルのメンバーを個人のISPFプロファイル・データセットからDD名ISPTLIBに定義されたライブラリー(ISP.SISPTENUまたはISP.SISPTJPN)に移動するだけです。ただし、コマンド・テーブルを修正した場合は個人のISPFプロファイル・データセットに保管されますので、再度移動する必要があります(個人用にコマンド・テーブルを修正した場合はそのままでかまいません)。

関連マニュアル

  • z/OS SDSF オペレーションおよびカスタマイズ 第10章インストールと構成の考慮事項のISPFの考慮事項
  • 対話式システム生産性向上機能(ISPF)ユーザーズ・ガイド第1巻 第6章MVSでの実行準備
  • 対話式システム生産性向上機能(ISPF)ユーザーズ・ガイド第2巻 第5章ユーティリティー(オプション3)のコマンド・テーブル・ユーティリティー(オプション3.9)
  • 対話式システム生産性向上機能(ISPF)計画とカスタマイズ 第2章ISPF構成テーブル
  • Filed in ISPFとSDSFのちょっと得する使い方

    ジョブ・グループの実行(続き)

    By 神居 - Last updated: 水曜日, 4月 11, 2018

    ジョブ・グループの実行例(開始時刻指定ジョブ)

    ジョブ・グループの実行例(同名ジョブの実行)

    JEC(Job Execution Controls)によるジョブ・グループのジョブ運用では、JES2のデフォルト設定によって同名ジョブを順番に実行するようにしていても、ジョブ・グループに属するジョブの場合は属するグループが異なれば同じ名前のジョブであっても同時に実行されます。
    元々のMVSにおけるJES2では同名ジョブは同時に実行されませんでした。OS/390 V2以降同名ジョブを並行して実行する機能(*1)が追加されましたが、デフォルトでは従来通りに同名ジョブは順番に実行する設定だったので、同名のジョブは同時に実行されないと理解されていることも多いと思います。JECでは、JOBDEFの設定に関わらず条件次第で同名ジョブも並行して実行されることを知っておかないとジョブ・グループのジョブ運用では意図したとおりのジョブの実行順にならない場合があります。

    *1 JES2起動パラメーターのJOBDEFステートメントでDUPL_JOB=NODELAYが指定されていれば同じ名前のジョブも同時に実行される。デフォルトがDELAYなので同名のジョブは同時に実行されない運用が多い。


    JES2のJEC(Job Execution Controls)は新しい機能なのでまだまだ普及していないようです。JECの機能を上手に使えば、同じジョブ内の同時に実行できるステップは比較的容易にジョブ分割することができます。同時に実行できるステップを並行して動かすことは、業務データ量が増えた際などのバッチ処理全体のスループットを改善するための1つの方策です。ジョブ・グループの概念を理解し適用することは、現行のシステム運用の改善策のカードが増えることにも繋がります。
    参考資料「z/OS MVS JCL解説書(SA88-7091)」第30章 JES2実行制御ステートメント

    Filed in オペレーション・運用

    ジョブ・グループの実行

    By 神居 - Last updated: 月曜日, 4月 2, 2018

    ジョブ・グループの実行(z/OS V2.2からのJES2の新たなジョブ・スケジューリング機能⑧)

    グループ化されたジョブは、次に示す順序で実行を行います。

    グループ内ジョブ(SCHEDULE JOBGROUPステートメント定義したジョブ)を、先にサブミット(ジョブ・グループのサブミット前にサブミット)すると JOB NOT RUN – JCLエラー となります。ジョブ・グループの定義については、「ジョブ・グループの定義とジョブ・グループの例-1」を参照して下さい。

    グループ内ジョブは、ジョブ・グループで定義された先行・後続関係やSCHEDULEステートメントで指定された時刻条件などが満たされ次第、実行が開始されます。

    ジョブ・グループ間での先行・後続関係は定義できませんが、グループ内の最後のジョブで、後続ジョブ・グループとグループ内ジョブをサブミットすることは可能です。


    ジョブ・グループの実行例(SDSF操作例)

    Filed in オペレーション・運用

    ジョブ・グループの定義とジョブ・グループの例-4

    By 神居 - Last updated: 木曜日, 4月 20, 2017

    ジョブ・グループの例④

    JOBGRP4

    ※図をクリックすると拡大できます。

    グループ内のジョブおよびジョブセットも、先行するジョブの終了状態や完了コードによって実行を制御することができます。GJOBステートメントとJOBSETステートメントのFLUSHTYPパラメーターによって、先行する親ジョブがすべてフラッシュした場合に後続のジョブ/ジョブセットをフラッシュするか(FLUSHTYP=ALLFLUSH)、先行する親ジョブのいずれか1つがフラッシュした場合に後続のジョブ/ジョブセットをフラッシュするか(FLUSHTYP=ANYFLUSH)を指定することができます。また、AFTERステートメントにWHENパラメーター(EXECステートメントのCONDパラメーターに相当)を指定して先行するジョブの完了コードをテストすることもできます。
    この例では、ジョブVは先行するジョブセット6内のジョブのどれか1つでもフラッシュしたら実行されません。また、ジョブセット7は先行するジョブVがノーマルエンドの場合(完了コードは問わない)に実行され、ジョブセット8は先行するジョブVがABENDした場合に実行されます。ジョブVがABENDするかしないかで後続するジョブを変更するようなことができます。

    Filed in オペレーション・運用

    8.Tcplinkマクロのデータ入力 input、input password、、そしてmessageアンドedit paste

    By 岡田 - Last updated: 日曜日, 3月 19, 2017

    Tcplinkには画面にデータ入力するコマンドとしてinput及びinput passwordがあります。
    しかし、messageコマンドとedit pasteを組み合わせて使うことでもデータ入力が可能です。

    これらのコマンドについて、具体例を挙げて説明いたします

    それぞれのコマンドの特徴

    input,input password,message及びedit pasteについて、仕様と特徴を纏めると以下のようになります
    コマンド 出力先指定 データ入力方法 備考
    input できない(※) 入力画面にデータを入力(値は表示される) 手入力が必要な場合など、簡単な入力に対して有効
    input password 入力画面にデータを入力(値は表示されない)
    message及びedit paste 必須 messageコマンド実行後クリップボードに値をコピー、okボタン押下後edit pasteで書き込まれる 他のアプリから値を持ってくることが容易なため、入力誤りを防ぎたい場合などに有効
    (※)input又はinput passwordコマンド実行時のカーソル位置が出力先となる

    input,input passwordの具体例


    (1)inputコマンド

    Tcplinkマクロとして以下の命令を実行します

    input “値を入力してください”

    マクロを実行すると、以下の入力画面が出てきます。
    1-1

    入力値として”123456″を入れました
    2-1 -2

    OKボタンをクリックすることで、値が画面のカーソル位置に書き込まれます。
    1-3

    (2)input passwordコマンド

    inputコマンドと動作は同じですが、LOGON時のpasswordを入力する時に使われ事を前提としているようで入力値が画面に表示されません。*表示となります

    Tcplinkマクロとして以下の命令を実行します

    input password “値を入力してください”

    1-2

    結果はinputコマンドと同じです
    1-3

    (3)messageコマンドとedit pasteコマンド

    Tcplinkマクロとして以下の命令を実行します

    message “画面にコピーしたい内容をクリップボードにコピーしてください”
    edit paste (06,19)

    1行目のmessageコマンドで以下の画面となります。
    3-1

    画面のOKボタンをクリックするまで、マクロは一時停止状態となります。このタイミングでクリップボードに値をコピーします。

    “23456”をクリップボードにコピーしました

    この後、OKボタンを押すことで、マクロが継続され、edit pasteで値が画面に書き込まれます
    3-2

    edit pasteでは(06,19)・・・6行目19カラム というように画面に書き込む場所を指定する事が必要です。

    但し、messageコマンドとedit pasteの組み合わせは、EXCELやテキストエディタなど他のアプリからクリップボードを経由してTcplink画面に入力データを持ってくる事が容易なため、応用範囲は広いと思われます
    Filed in Tcplinkマクロ活用

    7.TcplinkマクロでISPF・SDSFのFINDから関連データを取得する

    By 岡田 - Last updated: 水曜日, 2月 15, 2017
    前回は、検索コマンドの結果から対象データの存在有無に応じて動作を制御する方法をご説明しましたが、
    今回は検索コマンドの結果から関連するデータ(取得したいデータ等)を得る方法です

    以下の画面にてご説明します
    11

    データセットの中に日付(yyyy/mm/dd)とデータセット名の一覧(DATASET・・)が複数行ある場合、DATASET1の2番目の日付を取得する場合を考えます

    Tcplinkマクロでは、データの取得は”edit copy”という命令を用いますが、取得する開始点(左上)、行数又は終了点(右下)を明示指定する必要があります。

    画面全体をクリップボードにコピーしたい場合、edit copy (1,1) (24,80)といった具合です

    Tcplinkでは変数が使えないため、edit copyコマンドの引数をマクロの中で複数準備する必要があることが想像できます。と同時にマクロ内でカーソル位置を判定させるために、カーソルの場所を求める処理(DATASET1の2件目が見つかった場所)が必要と考えてきました

    <マクロ記述例>
     :
    DATASET1の2件目の検索処理
    カーソルがある場所の特定
    (場所に応じて、以下1行目から24行目までの処理のいづれかの処理を行う)
     :
    カーソルが1行目にあった場合の処理
     :
    カーソルが2行目にあった場合の処理
     :
    カーソルが3行目にあった場合の処理
     :
     :
     :
    カーソルが24行目にあった場合の処理
     :
    以後の処理

    ISPF・SDSFの画面制御コマンドと組み合わせ、取得データを特定の場所に移動させる

    ISPF・SDSFの画面スクロールコマンドはカーソルが存在する場所までスクロールするという仕様を持っています。この仕様はASPENには無かったと記憶しています。

    以下、画面と合わせて説明します

    はじめにDATASET1の検索をします
    12

    FINDコマンドを連続実行(PF5等)し、2番目のDATASET1を見つけました
    この時点でカーソルは4行目のDATASET1の先頭を示しています。
    13

    ここでPF8キーで”下スクロール”します
    14

    下スクロールした結果、カーソルがある4行目が画面の一番上に来ました。
    14

    取得したい日付が特定の場所に持ってくることができました
    あとは特定の場所をedit copyするだけです。画面の場合命令文は edit copy (3,8) (3,17)になります
    15

    ここでは、下スクロールで説明しましたが、同様に横スクロール(PF10,PF11)でも対応が可能です。
    但し、横スクロールの場合、レコードの終わりは画面右端で固定されます。取得したいデータを得る方法は各自確認が必要です。

    Filed in Tcplinkマクロ活用

    メインフレームのアセンブラー入門に使えるz390エミュレーター

    By 神居 - Last updated: 火曜日, 1月 24, 2017

    z390 Portable Mainframe Assembler and Emulator

    「z390 Portable Mainframe Assembler and Emulator」(以下z390と表記)は、IBMのzアーキテクチャーのCPU命令の実行をエミュレートするWindows/Linuxで動くソフトウェアです。
    IBMのメインフレーム用アセンブラー言語で書かれたプログラムをアセンブルしてオブジェクトコードを生成し、それを入力にしたリンケージエディターを実行して実行形式ファイルを作り、PC上で実行させることができます。z390では、単一イニシエーターによるバッチジョブのイメージでメインフレーム・プログラムを実行できます。一般的なAPIとファイルアクセスがサポートされているので、基本的なプログラムであればメインフレームのアセンブラーまたはCOBOLで書いたプログラムをWindowsのコマンド・プロンプトで実行させることができます。
    無料で利用できるオープンソースのソフトウェアで、アセンブラー言語の学習には十分な機能を備えています。企業の業務処理用にアセンブラー言語のプログラムが作られることはほとんどなくなりましたが、メインフレーム・コンピューターとz/OSの内部の仕組みや機能をより深掘りして勉強したい、という方にはうってつけのツールです。インストーラーなしで使えるのでPCを汚すこともなく手軽に試すことができます。



    z390エミュレーターのインストール

    z390エミュレーターは、配布元のWebサイト(http://www.z390.org/)からダウンロードして入手します。

    image002

    配布元サイトに繋げたら、画面左側ナビゲーションの「Download Links」を選択します。

    image005

    ダウンロードするファイルは、Linux用の「z390 v1506 files.zip」です。Windowsであってもこれを選択します。Windows用のSetupファイルでもかまいませんが、インストーラーによって導入され、Cドライブのuserフォルダーから先の奥深いフォルダーに作られてしまい、コマンドプロンプトで使うには面倒です。コマンドプロンプトではなく、Guiウィンドウで試したい場合はそちらを選択してもいいと思います。その場合は、以降の解説はあてはまりませんのでヘルプやドキュメント・ファイルを参照して進めて下さい。
    「z390 v1506 files.zip」をダウンロードしたら、zipファイルの中にあるz390フォルダーをフォルダーごと適当な場所(デスクトップなど)にコピーします。

    続いて以下に示す3つのファイルをダウンロードして、z390フォルダーにコピーします。
    ※以下のファイルは配布元のz390には含まれていない、当サイトが独自にカスタマイズしたものです。

    以下のファイルは必要ならばダウンロードして下さい。

    z390フォルダー内に適当な名前のサブフォルダーを作ります。例えば「myasm」です。そのフォルダーに適当な名前(例えば「myprog.txt」)でアセンブラーのソースプログラム・ファイルを作ります。メモ帳などのテキストエディターで作成して保管すればいいでしょう。
    @z390.lnkをダブルクリックしてコマンドプロンプトを起動して、asmgoバッチファイルでアセンブルと実行を試すことができます。なお、z390エミュレーターはJavaで作られているので、実行にはJavaのランタイムがインストールされている必要があります。ほとんどのパソコンにはJavaはインストールされているでしょう。

    asmgo myasm\sample
    

    asmgoコマンドの後、空白を置いてサブフォルダー名\プログラム名を第1パラメーターとして指定します。プログラム名はソースプログラムのファイル名から拡張子を取ったものです。sample.txtならsampleと指定します。
    第2パラメーターには追加のオプションを指定できます。

    オプション名意味
    noobjアセンブルのみを行い、リンケージと実行はしない
    dump実行時にABENDしたらダンプ・リストも出力する


    asmgo myasm\sample noobj
    asmgo myasm\sample dump
    

    asmgoバッチファイルは、z390エミュレーターのコマンドを実行するためにカスタマイズしたものです。ただのテキストファイルなので、必要ならばメモ帳などで内容を見て自由に直して下さい。z390エミュレーター自体の詳細については、Webサイトにあるドキュメントを参照するかダウンロードして下さい。
    アセンブル・リストやダンプ・リストの形式、PSWの設定値など実機のz/OSとは異なりますが、メインフレームの機械命令の動きを確認したり、アセンブラー言語プログラムの書き方に慣れるには十分利用できるツールです。DC命令で定義した値が実際にどのようにメモリーに格納されるか、命令の実行によってレジスターやメモリー内容がどう変化するか、といったことは実機同様に確認することができます。

    Filed in S/370アセンブラー講座, メインフレーム・エミュレーター

    ジョブ・グループの定義とジョブ・グループの例-3

    By 神居 - Last updated: 火曜日, 1月 24, 2017

    ジョブ・グループの例③

    JOBGRP3

    ※図をクリックすると拡大できます。

    同じデータ依存関係を持つジョブは、ジョブセットにまとめることができます。先行する2つのジョブの出力を入力にする後続ジョブがある場合、先行する複数のジョブをジョブセットにまとめれば、後続ジョブのスケジュールを定義する際は個々の先行ジョブ名の代わりにジョブセット名で記述できます。将来、先行するジョブが3つに増えてもジョブセット内に新しいジョブを追加するだけで済み、後続ジョブのスケジュール定義を修正する必要がありません。
    ジョブNの先行ジョブであるLとMをジョブセットとして定義すれば、ジョブNの先行ジョブを個々のジョブLおよびMではなくジョブセット5とすることができます。

    Filed in オペレーション・運用

    ファイルシステム・区分データセットのディレクトリー構造

    By 神居 - Last updated: 火曜日, 1月 10, 2017

    区分データセットのディレクトリー構造

    区分データセットのしくみについては、以前に「z/OS(MVS),MSP,VOS3のしくみ\基礎編\07.データセットの種類とアクセス法」のディレクトリ部の構造でも解説しましたが、各ディレクトリー・ブロック内のデータ構造についてもう少し詳細を補足します。z/OSでは、拡張区分データセット(PDSE)も使用できますが、ここで解説するディレクトリー・ブロック構造は、従来からある区分データセットについてのものです。

    メンバー・ディレクトリ部の構造

    メンバー・ディレクトリ部の構造



    ディレクトリー・ブロックの構造

    ディレクトリー・ブロックは、256バイトの長さを持ちます。ディレクトリー内では、256バイトのディレクトリー・ブロックが、区分データセット作成時に指定されたディレクトリー・ブロックの数だけ順番に並んでいます。区分データセットのディレクトリー部だけを抜き出せば、256バイトの固定長非ブロック化レコードの順次データセットと同様の構造になっています。
    実際のディスク・トラック上では、256バイトのレコード・データの前に8バイトのキーが付加されています。このキー部には、そのディレクトリーブロックに格納されている最後のメンバー名が格納されています。どのディレクトリー・ブロックに目的メンバーのインデックス・データが書かれているかを探索する際のキーとして利用されます。

    pdsdirectory

    区分データセットのディレクトリーブロック数はどのくらいにすればいいか?

    PDSEデータセットではディレクトリーブロック数を考える必要はないですが、従来のPDS(区分)データセットを作る場合はディレクトリーブロック数を指定しなければなりません。ディレクトリー・ブロック内のデータ構造とユーザー・データ部の長さがわかれば、1つのディレクトリー・ブロックにいくつのメンバーが格納できるかが計算できます。1つのメンバーは、メンバー名の8バイト、TTR(メンバーのレコード・データが区分データセット内のどの位置にあるかを示す)の3バイト、インジケーター・バイトの1バイトの計12バイトを最小でも使用します。これにユーザー・データ部が加わります。ディレクトリー・ブロック内で、メンバー・ディレクトリー・データ用に使用できる最大長は、256バイトから先頭にある有効データ長フィールドの長さ2バイトを引いた254バイトです。したがって、254÷1メンバーあたりのディレクトリー・データ長が、1つのディレクトリー・ブロックに格納できるメンバー数です。ただし、最後のディレクトリー・ブロックには最終エントリーを示すデータ12バイトが予約されるので、1メンバー分少なくなる場合があります。

    代表的なユーザー・データ部の長さ
    ソフトウェアユーザー・データの長さメンバー・ディレクトリー・データの合計長
    ISPFエディター30byte42byte
    PFDエディター28byte40byte
    ASPENエディター30byte42byte
    バインダー(z/OS)
    リンケージ・エディター(MSP)
    24byte36byte
    バインダー(z/OS)別名メンバー34byte46byte
    リンケージ・エディター(VOS3)28byte40byte

    区分データセットにメンバーを格納する代表的なソフトウェアは、ソース・プログラムやJCLならISPFエディター、ロード・モジュールならバインダー(リンケージエディター)です。上記のテーブルには主なソフトウェアがメンバー保管時に付加するメンバー・ディレクトリーのユーザー・データの長さを示しました。このテーブルからメンバーが使用するディレクトリー・データの長さを求め、その値で254を割れば1DIRブロックあたりのメンバー数を求められます。区分データセットに格納する予定(あるいは格納したい)のメンバー数を、そのメンバー数で割れば必要なディレクトリー・ブロック数のおおよその数を求めることができます。
    z/OSでは、ソース・プログラムやJCLの格納データセット(ISPFエディター使用)なら1DIRブロックあたり6メンバー、ロード・モジュールの格納データセットなら1DIRブロックあたり7メンバー(別名なしの場合)です。ディレクトリー・ブロック数を10個にした場合、ソース・プログラムやJCLライブラリーなら60メンバー、ロード・モジュール・ライブラリーなら70メンバー程度が格納できることになります。
    業務用プログラムのロード・モジュールを格納する場合は、別名を付けたりすることもあるので少し多めにしておく方がいいでしょう。データセット自体のスペースは不足しても2次数量で拡張することができますが、ディレクトリーは後で拡張することはできません。

    Filed in .z/OS(MVS),MSP,VOS3のしくみ

    ジョブ・グループの定義とジョブ・グループの例-2

    By 神居 - Last updated: 月曜日, 1月 9, 2017

    ジョブ・グループの例②

    jobgrp2

    ※図をクリックすると拡大できます。

    従来ならステップF→G→Hと順番に実行してからステップIを実行する流れであったジョブ・ステップを、複数ジョブに分割してグループにまとめた例です。ステップFとHはデータの依存関係にありますが、Gにはありません。そこでジョブに分割して、ジョブF→HとジョブGを並行して実行し、それらからの出力を入力にするジョブIを実行します。ジョブIの実行結果によって後続で実行するジョブを変更しています。
    ジョブ・グループでは、このように先行するジョブの実行結果によって後続ジョブを実行する条件付きスケジュールも定義できますが、ジョブJとジョブKはどちらか一方だけが実行されるので、ジョブIの中の後続ステップとしてもかまいません。

    Filed in オペレーション・運用

    6.TcplinkマクロとISPF・SDSF(ASPEN)で不特定文字列を判定。制御する

    By 岡田 - Last updated: 日曜日, 1月 8, 2017
    Tcplinkマクロは変数を使うことが出来ない事を今までに説明してきました。
    そのため、Tcplinkマクロの中で文字列を判定する場合、直接判定すべき文字列を明示指定する必要があります。

    <例> 画面上1行、1カラム目がABCであるかを判定・制御する処理

    if string (01,01) “ABC”
    jump true atari
    :nasi

    文字列ABCが無かった時の処理

    jump tugi
    :atari

    文字列ABCがあった時の処理

    :tugi

    そのため、検索すべき文字列を明示指定できない不特定文字列の判定は難しいと思っていました。
    (不特定の文字列の数が少なければ、上記のif string命令を複数回行う事で対応は可能でしたが、、)

    そんな中、TSO(TSS)のISPF・SDSF(ASPEN)の機能特性を用いることで、不特定文字列の判定と制御ができる方法を見つけました。

    Tcplinkマクロで不特定文字を判定・制御するためISPF・SDSF(ASPEN)の機能特性を確認する

    不特定文字列の判定・制御の準備の前に、利用されているメインフレームエディタで機能特定を確認する必要があります。
    ここで記載している「機能特定」ですが、これは
    ”メインフレームエディタで検索(FIND)や該当行の除外(EXCLUDE)命令を実行した際、対象の文字列が見つかった場合、該当行にカーソルが移動する事” です
    zos(ISPF,SDSF)及びVOS3(ASPEN)は操作の経験があるので記載ができるのですが、MSPでも同様の動作をされると思われますので、活用できると思います

    以下の4つの画面で説明します。本画面はzos(SDSF)のSEの画面です

    画面1:JOBが実行された日付を検索するため、FINDコマンドを実行する時の状態です
    (検索文字列は、後述しています)
    %e7%84%a1%e9%a1%8c121

    画面2:FINDで該当文字列が見つかると、該当する文字列にカーソルが移動します
    %e7%84%a1%e9%a1%8c12

    画面3:同じFINDコマンドですが、今度は見つからない文字列を指定した時の状態です
    %e7%84%a1%e9%a1%8c111

    画面4:文字列が見つからない場合、(画面では表示できていませんが)カーソルはコマンド入力領域の一番左に出ます
    %e7%84%a1%e9%a1%8c2
    画面下 ”02/15”の記載があります。これが現在のカーソル位置を示しています。FIND命令の実行後、02/15にカーソルが移った事を示しています 

    このように画面2と画面4のカーソル位置の違いで、文字列の検索結果が判ります。Tcplinkマクロでは画面4のように02/15のカーソル位置にカーソルが無い場合、FINDで指定した文字列が見つかったと判定・制御ができます。

    尚、特定の場所にカーソルがあるか否かの判定は、Tcplinkマクロのif cursor命令を使います。



    不特定文字列を判定・制御するための準備

    次に、FIND,EXCLUDE命令等で指定する文字列を事前にTcplink画面のどこかで作成する必要があります。
    (Tcplink画面の外で作成した場合、Tcplinkマクロの中で文字列がクリップボードで渡せるようにTcplinkマクロを工夫する必要があります)

    今回は、Tcplinkの空き画面(画面10)を使って文字列を作成します。空き画面の活用については14-3.非定型操作にてEXCEL(vba)とTcplinkマクロを連携する(空き画面活用編) を参照願います

    画面5:検索用文字列作成例
    %e7%84%a1%e9%a1%8c122

    本画面はTcplink空き画面(画面10)で”2017/01/04” から ”04 JAN 2017”を作っています。
    検索用文字列を作るために作成したTcplinkマクロが以下になります

    01: open session TCP3270-Ses10
    02: EDIT COPY (04,18) (04,19)
    03: EDIT PASTE (04,21)
    04: wait 1
    05: EDIT COPY (04,10) (04,13)
    06: EDIT PASTE (04,28)
    07: ;
    08: IF STRING (04,15) “01”
    09: jump true iti
    10: IF STRING (04,15) “02”
    11: jump true ni
    12: IF STRING (04,15) “03”
    13: jump true san
    14: IF STRING (04,15) “04”
    15: jump true yon
    16: IF STRING (04,15) “05”
    17: jump true gou
    18: IF STRING (04,15) “06”
    19: jump true roku
    20: IF STRING (04,15) “07”
    21: jump true nana
    22: IF STRING (04,15) “08”
    23: jump true hati
    24: IF STRING (04,15) “09”
    25: jump true kyuu
    26: IF STRING (04,15) “10”
    27: jump true jyuu
    28: IF STRING (04,15) “11”
    29: jump true jyuuiti
    30: IF STRING (04,15) “12”
    31: jump true jyuuni
    32: ;
    33: :iti
    34: string “JAN” (04,24)
    35: jump owari
    36: :ni
    37: string “FEB” (04,24)
    38: jump owari
    39: :san
    40: string “MAR” (04,24)
    41: jump owari
    42: :yon
    43: string “APR” (04,24)
    44: jump owari
    45: :gou
    46: string “MAY” (04,24)
    47: jump owari
    48: :roku
    49: string “JUN” (04,24)
    50: jump owari
    51: :nana
    52: string “JLY” (04,24)
    53: jump owari
    54: :hati
    55: string “AUG” (04,24)
    56: jump owari
    57: :kyuu
    58: string “SEP” (04,24)
    59: jump owari
    60: :jyuu
    61: string “OCT” (04,24)
    62: jump owari
    63: :jyuuiti
    64: string “NOV” (04,24)
    65: jump owari
    66: :jyuuni
    67: string “DEC” (04,24)
    68: jump owari
    69: ;
    70: ;
    71: :owari

    02-03行目で日付のコピー
    05-06行目で西暦のコピー
    08-30行目で月の判定を行い、該当月を省略形に変換します

    04行目21カラムから31カラムに検索文字列が出来ましたので、画面1のFIND命令に使っています
    Filed in Tcplinkマクロ活用