JCLのSYSIN DDでシンボルを使ってみた

# はじめに
再利用するためにJCLを汎用的に作ろうと思ったら、可変の文字列をシンボル(変数)にしておいて、先頭部分で変数をセットする、ということをよくやりますよね(変更箇所を一箇所にまとめて、変更の抜け、漏れを無くす、かつ、不要な箇所を変更させないため)。
その際、SYSIN DDに代表されるようなイン・ストリームデータセット(ストリーム内データセット)では"シンボル"が使えない、ということがありましたが、それはもはや過去の話です。
なんとz/OS V2.1からSYSINでもシンボルが使えるようになってました！
なぜいままでこれが出来なかったのか不思議なくらいなのですが、非常にありがたい機能なので何はともあれやってみました。

参考: [JES ストリーム内データでのシンボルの使用](http://www.ibm.com/support/knowledgecenter/ja/SSLTBW_2.2.0/com.ibm.zos.v2r2.ieab600/jclsymstr.htm)

# JCL中のSYSINでのシンボルの使用
## JCLその1
マニュアルにサンプルが載ってます。
参考: [SYMBOLS パラメーターの例](http://www.ibm.com/support/knowledgecenter/ja/SSLTBW_2.2.0/com.ibm.zos.v2r2.ieab600/iea3b6_Example_of_the_SYMBOLS_parameter.htm)
このサンプルを元に試してみました(サンプルとほぼ同様ですが、Syntaxの確認のため書き方少し変えてます)。

```jcl:REALLOC.jcl
//REALLOC  JOB   MSGCLASS=X,CLASS=A,NOTIFY=&SYSUID               
//*-----------------------------------------------------         
//E1  EXPORT SYMLIST=(DSNAME,VOLSER)                             
//S1  SET    DSNAME=CICSSHR.AAA.TEST,VOLSER=Z9CI01               
//DEALLIB EXEC PGM=IDCAMS,REGION=300K                            
//DD1       DD UNIT=3390,DISP=OLD,VOL=SER=&VOLSER                
//SYSPRINT  DD SYSOUT=*                                          
//SYSIN     DD *,SYMBOLS=JCLONLY                                 
     DELETE &DSNAME -                                            
            NONVSAM PURGE SCRATCH FILE(DD1)                      
     ALLOCATE DSNAME('&DSNAME.') -                               
         UNIT(3390) VOLUME(&VOLSER.) -                           
         NEW CATALOG DSNTYPE(LIBRARY) SPACE(10,10) DIR(5) TRACKS 
/*                                                               
```

この例では、データセットのリアロケーションを行っていますが、データセット名とボリューム名をそれぞれDSNAME, VOLSERというシンボルで表しています。
SYSIN DD中で、「&DSNAME.」「&VOLSER.」で示されている箇所です！
ポイントは以下の3つです。

1. EXPORTステートメント
2. SETステートメント
3. SYSIN DDのSYMBOLSパラメーター

SETでシンボルを定義し、EXPORTでSYSINで使用したいシンボルを指定します。
SYSIN DDで、SYMBOLS=JCLONLY を指定します。
(SYMBOLSパラメーターの指定によってシステム上に定義してあるシンボルなども使用できるようですが、詳細はマニュアル参照のこと...)

JOBLOGのSYSPRINTを見てみると、きちんと変数が解釈されて実行されているのがわかります。

```joblog:SYSPRINT
IDCAMS  SYSTEM SERVICES                                          
                                                                 
     DELETE CICSSHR.AAA.TEST -                                   
            NONVSAM PURGE SCRATCH FILE(DD1)                      
IDC0550I ENTRY (A) CICSSHR.AAA.TEST DELETED                      
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0        
                                                                 
     ALLOCATE DSNAME('CICSSHR.AAA.TEST') -                       
         UNIT(3390) VOLUME(Z9CI01)   -                           
         NEW CATALOG DSNTYPE(LIBRARY) SPACE(10,10) DIR(5) TRACKS 
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0        
                                                                 
IDC0002I IDCAMS PROCESSING COMPLETE. MAXIMUM CONDITION CODE WAS 0
```

## JCLその2
SYMBOLSパラメーターでロギング用のDD指定ができるようなのでやってみました。

```jcl:REALLOC.jcl
//REALLOC  JOB   MSGCLASS=X,CLASS=A,NOTIFY=&SYSUID                 
//*-----------------------------------------------------           
//E1  EXPORT SYMLIST=(DSNAME,VOLSER)                               
//S1  SET    DSNAME=CICSSHR.AAA.TEST,VOLSER=Z9CI01                 
//DEALLIB EXEC PGM=IDCAMS,REGION=300K                              
//DD1       DD UNIT=3390,DISP=OLD,VOL=SER=&VOLSER                  
//SYSPRINT  DD SYSOUT=*                                            
//MESSAGE   DD SYSOUT=*                                            
//SYSIN     DD *,SYMBOLS=(JCLONLY,MESSAGE)                         
     DELETE &DSNAME -                                              
            NONVSAM PURGE SCRATCH FILE(DD1)                        
     ALLOCATE DSNAME('&DSNAME.') -                                 
         UNIT(3390) VOLUME(&VOLSER.) -                             
         NEW CATALOG DSNTYPE(LIBRARY) SPACE(10,10) DIR(5) TRACKS   
/*                                                                 
```

MESSAGE DDを追加し、```SYMBOLS=(JCLONLY,MESSAGE)```と指定しています。
JOBLOGのMESSAGE DDの結果を見てみると...

```joglog:MESSAGE
SYSIN    : RECORD 1 BEFORE SUBSTITUTION                                    
SYSIN    :      DELETE &DSNAME -                                           
SYSIN    : RECORD 1 AFTER SUBSTITUTION                                     
SYSIN    :      DELETE CICSSHR.AAA.TEST -                                  
SYSIN    : RECORD 2 BEFORE SUBSTITUTION                                    
SYSIN    :             NONVSAM PURGE SCRATCH FILE(DD1)                     
SYSIN    : RECORD 2 AFTER SUBSTITUTION                                     
SYSIN    :             NONVSAM PURGE SCRATCH FILE(DD1)                     
SYSIN    : RECORD 3 BEFORE SUBSTITUTION                                    
SYSIN    :      ALLOCATE DSNAME('&DSNAME.') -                              
SYSIN    : RECORD 3 AFTER SUBSTITUTION                                     
SYSIN    :      ALLOCATE DSNAME('CICSSHR.AAA.TEST') -                      
SYSIN    : RECORD 4 BEFORE SUBSTITUTION                                    
SYSIN    :          UNIT(3390) VOLUME(&VOLSER.) -                          
SYSIN    : RECORD 4 AFTER SUBSTITUTION                                     
SYSIN    :          UNIT(3390) VOLUME(Z9CI01)   -                          
SYSIN    : RECORD 5 BEFORE SUBSTITUTION                                    
SYSIN    :          NEW CATALOG DSNTYPE(LIBRARY) SPACE(10,10) DIR(5) TRACKS
SYSIN    : RECORD 5 AFTER SUBSTITUTION                                     
SYSIN    :          NEW CATALOG DSNTYPE(LIBRARY) SPACE(10,10) DIR(5) TRACKS
```

ご丁寧に一行ずつシンボルが解釈されている様子が確認できした。

# カタログ式プロシージャーでのシンボルの利用
ついでに上のJCLをカタプロ化して、変数部分を引数渡しにしてみます。

```proc:REALLOC.proc
//REALLOC  PROC PDSNAME=,PVOLSER=                               
//*-----------------------------------------------------        
//E1  EXPORT SYMLIST=(DSNAME,VOLSER)                            
//S1  SET    DSNAME=&PDSNAME.,VOLSER=&PVOLSER.                  
//DEALLIB EXEC PGM=IDCAMS,REGION=300K                           
//DD1       DD UNIT=3390,DISP=OLD,VOL=SER=&VOLSER               
//SYSPRINT  DD SYSOUT=*                                         
//SYSIN     DD *,SYMBOLS=MESSAGE     
     DELETE &DSNAME -                                           
            NONVSAM PURGE SCRATCH FILE(DD1)                     
     ALLOCATE DSNAME('&DSNAME.') -                              
         UNIT(3390) VOLUME(&VOLSER.) -                          
         NEW CATALOG DSNTYPE(LIBRARY) SPACE(10,10) DIR(5) TRACKS
/*                                                              
```

この例では分かりやすさのためにプロシージャーの引数は頭に"P"をつけて、PDSNAME、PVOLSERとしていますが、同じ名前でもOKです。

以下のような感じで引数を指定してカタプロ実行できました。

SDSFコマンドによる実行
```=> S REALLOC,PDSNAME=CICSSHR.AAA.TEST,PVOLSER=Z9CI01 ```

JCLによる実行

```jcl:REALLOCP.jcl
//REALLOCP JOB   MSGCLASS=X,CLASS=A,NOTIFY=&SYSUID              
//*-----------------------------------------------------        
//P1      EXEC REALLOC,PDSNAME=CICSSHR.AAA.TEST,PVOLSER=Z9CI01  
/*                                                              
```

素敵です。
この例だと単純なのでアレですが、ミドルウェアなどを扱う際はSYSINで制御することが色々あるのでこれは重宝しそうですね！