OpenVMS
ユーザーズ・マニュアル


前へ 次へ 目次 索引


14.16.3 ELSE コマンドの使用

式が偽の場合に 1 つ以上のコマンドを実行するには,動詞として ELSE 文を指定し,残りのブロック構造文の終わりに ENDIF 文を指定します。

次の例では,ELSE コマンドは動詞として使用されています。


$ IF expression 
$   THEN 
$       command 
$       command 
   .
   .
   .
$   ELSE 
$       command 
$       command 
   .
   .
   .
$ ENDIF 

14.16.4 コマンド・ブロックの使用

同じコマンド・プロシージャでコマンドを実行するのか,別のコマンド・プロシージャにコマンドを置いて実行するのかに応じて,コマンド・ブロックにはいくつかの実行方法があります。ガイドラインは次に示します。

IF 式の結果が真の場合には,THEN コマンドの後のコマンド・ブロックを実行できます。コマンド・ブロックを使用する場合には,IF コマンドの後の行に最初のコマンドとして THEN コマンドを指定します。

次の例では,2 つの SET TERMINAL コマンドが実行され,F$MODE が "INTERACTIVE" に等しい場合には,プロシージャは制御をラベル PROCEED に渡します。F$MODE が "INTERACTIVE" に等しくない場合には,プロシージャは終了します。


$ IF F$MODE().EQS. "INTERACTIVE" 
$ THEN 
$    SET TERMINAL/DEVICE=VT320 
$    SET TERMINAL/WIDTH=132 
$    GOTO PROCEED 
$ ENDIF 
$ EXIT 
$PROCEED: 

次の例では,IF コマンドと ELSE コマンド,およびコマンド・ブロックを組み合わせて使用する方法を示しています。


$ INQUIRE DEV "Device to check" 
$ IF F$GETDVI(DEV, "EXISTS")
$ THEN 
$    WRITE SYS$OUTPUT "The device exists." 
$    SHOW DEVICE 'DEV' 
$    SET DEVICE/ERROR_LOGGING 'DEV' 
$ ELSE 
$    WRITE SYS$OUTPUT "The device does not exist." 
$    WRITE SYS$OUTPUT "Error logging has not been enabled." 
$ ENDIF 
$ EXIT 

条件が真の場合には,プロシージャはメッセージを SYS$OUTPUT に書き込み,SHOW DEVICE コマンドと SET DEVICE コマンドを実行します。条件が真でない場合には,プロシージャは 2 つのメッセージを SYS$OUTPUT に書き込みます。

IF-THEN-ELSE を使用する場合には,次のような制限事項があります。

真の文

IF コマンドに続く文は,1 つ以上の数値定数,文字列リテラル,シンボリック名,レキシカル関数で構成し,論理演算子,算術演算子,または文字列演算子によって区切ります。次のいずれかの値を持つ場合に式は真となります。

偽の文

次のいずれかの値を持つ場合に式は偽となります。

式の作成

IF コマンドの式を作成する場合には,特に,次の点に注意してください。

この後に示す例は,IF コマンドと一緒に使用できる式を示しています。さらに詳しい例が必要であれば,『OpenVMS DCL ディクショナリ』のIF コマンドの説明を参照してください。

次の例では,論理演算子を使用し,THEN 文の後の 1 つのコマンドだけを実行します。シンボル CONT が真でない場合には,プロシージャは終了します。


$ INQUIRE CONT "Do you want to continue [Y/N]" 
$ IF .NOT. CONT THEN EXIT 
   .
   .
   .

次の例は,IF 式の中でシンボルとラベルを使用しています。


$ INQUIRE CHANGE "Do you want to change the record [Y/N]" 
$ IF CHANGE THEN GOTO GET_CHANGE 
   .
   .
   .
$ GET_CHANGE: 
   .
   .
   .

CHANGE シンボルが真の場合は,プロシージャはGET_CHANGE ラベルに制御を渡します。それ以外の場合には,IF コマンドの後のコマンドを実行します。

次の例は,2 つの異なる IF コマンドを示しています。


$ COUNT = 0 
$ LOOP: 
$    COUNT = COUNT + 1 
$    IF COUNT .EQ. 9 THEN EXIT 
$    IF P'COUNT' .EQS. "" THEN EXIT 
   .
   .
   .
$ GOTO LOOP 

最初のIF コマンドは 2 つの整数を比較し,2 番目の IF コマンドは 2 つの文字列を比較しています。整数比較には .EQ. 演算子が,文字列比較には.EQS. 演算子が使用されています。

最初に,COUNT の値が整数の 9 と比較されます。値が等しいとプロシージャは終了し,値が等しくないとプロシージャは継続されます。8 つのパラメータ(許容最大数)を処理した後,ループが終了します。

2 番目の IF コマンドでは,P'COUNT' シンボルの文字列値を空の文字列と比較して,シンボルが未定義かどうかを調べます。COUNT シンボルの反復置換を強制するには,一重引用符を使用しなければなりません。たとえば,COUNT が 2 の場合は,最初の変換結果は P2 になります。次に,P2 の値を文字列比較に使用します。

IF 式の結果が真の時に別のコマンド・プロシージャを実行することもできます。次の例では,IF 式の結果が真のときに,コマンド・プロシージャ EXIT_ROUTINE.COM を実行します。


$ GET_COMMAND_LOOP: 
$    INQUIRE COMMAND - 
     "Enter command(DELETE, DIRECTORY, EXIT, PRINT, PURGE, TYPE)" 
$    IF COMMAND .EQS. "EXIT" THEN @EXIT_ROUTINE 

14.16.5 GOTO コマンドの使用

GOTO コマンドは,コマンド・プロシージャ内のラベルの付いた行に制御を渡します(ラベルの使い方についての詳細は,第 13 章 を参照してください)。GOTO コマンドは,THEN 句で使用すると特に便利であり,プロシージャを前後に分岐させることができます。たとえば,コマンド・プロシージャでパラメータを使用する場合には,プロシージャの先頭でパラメータをテストし,適切なラベルに分岐できます。

GOTO コマンドまたは GOSUB コマンドの分岐先ラベルは,独立した IF-THEN-ELSE 構造または独立した サブルーチン の内部に存在できません。

次の例では,IF コマンドは,P1 が空文字列でないことをチェックします。


$ IF P1 .NES. "" THEN GOTO OKAY 
$ INQUIRE P1 "Enter file spec" 
$ OKAY: 
$ PRINT/COPIES=10 'P1' 
   .
   .
   .

P1 が空文字列の場合には,GOTO コマンドは実行されず,INQUIRE コマンドはパラメータ値を要求するプロンプトを表示します。それ以外の場合には,GOTO コマンドは INQUIRE コマンドの後に分岐します。どちらの場合も,プロシージャは,OKAY というラベルの付いた行の後の PRINT コマンドを実行します。

次の例では,GOTO コマンドはエラー・メッセージを戻します。これは,分岐先(TEST_1)が IF-THEN 構造の内部に存在するからです。


$ GOTO TEST_1 
$ EXIT 
$ IF 1.EQ.1 
$       THEN WRITE SYS$OUTPUT "What are we doing here?" 
$ TEST_1: 
$       WRITE SYS$OUTPUT "Got to the label" 
$ ENDIF 
$ EXIT 

14.16.5.1 再実行の回避

正常に実行されたジョブの一部が再実行されないようにするときにも GOTO コマンドを使用できます。この場合は,次のようにします。

手順 操作
1 プロシージャの中の開始ポイントにラベルを付ける。
2 ラベルの後,SET RESTART_VALUE = ラベル名 コマンドを使用して,再開ポイントをそのラベルに設定する。

SET RESTART_VALUE = ラベル名 コマンドの実行後にバッチ・ジョブが中断された場合,システムはバッチ・ジョブを再開するときにグローバル・シンボル BATCH$RESTART に該当するラベル名を割り当てる。

3 プロシージャの先頭で,$RESTART シンボルの値をテストする。

$RESTART が真の場合には,BATCH$RESTART シンボルを転送ラベルとして使用して GOTO 文を実行する。

$RESTART グローバル・シンボル

$RESTART は,システムがユーザ用に残してある予備グローバル・シンボルです。いずれか 1 つのバッチ・ジョブが中断後に再開された場合は,$RESTART は真であり,そうでない場合は,$RESTART は偽です。予備グローバル・シンボル $RESTART は削除できません。

コマンド・プロシージャの中に SET RESTART_VALUE コマンドがあり,この要素の中でジョブを再実行したい場合には,SET ENTRY/NOCHECKPOINT コマンドを入力して,グローバル・シンボル BATCH$RESTART を削除します。中断されたジョブを再起動した場合には,ジョブは中断されたセクション内で実行されます。

次のコマンド・プロシージャは,バッチ・ジョブの中で値を再開する方法を示しています。


$ ! Set default to the directory containing 
$ ! the file to be updated and sorted 
$ SET DEFAULT DISK1:[ACCOUNTS.DATA84] 
$ 
$ ! Check for restarting 
$ IF $RESTART THEN GOTO 'BATCH$RESTART' 
$ 
$ UPDATE_FILE: 
$ SET RESTART_VALUE = UPDATE_FILE 
   .
   .
   .
$ SORT_FILE: 
$ SET RESTART_VALUE = SORT_FILE 
   .
   .
   .
EXIT 

このコマンド・プロシージャを再開可能なバッチ・ジョブとしてキューに登録するには,ジョブを登録するときに SUBMIT コマンドと一緒に /RESTART 修飾子を指定します。割り込まれたジョブを再開する場合は,割り込みのあった場所からジョブの実行が開始されます。たとえば,SORT_FILE ルーチンの中でジョブに割り込みがあった場合は,ジョブを再開すると,SORT_FILE ラベルから実行が開始されます。

システムで障害が発生した場合には,プロセス環境の大部分は維持管理されません。システム障害が発生した後も管理されるシンボルは,$RESTART と BATCH$RESTART だけです。したがって,コマンド・プロシージャで使用したシンボルやプロセス論理名は,それぞれの SET RESTART_VALUE コマンドの後で再定義するか,または $RESTART が真のときに実行される THEN ブロックの内部で再定義しなければなりません。シンボルと論理名を THEN ブロックの内部で定義した場合には,コマンド GOTO 'BATCH$RESTART' を THEN ブロックの最後のコマンドとして指定しなければなりません。

14.16.6 GOSUB と RETURN コマンドの使用

GOSUB コマンドは,コマンド・プロシージャの中のラベルの付いたサブルーチンに制御を渡します。コマンド・プロシージャの中にラベルがない場合には,実行は継続されず,強制終了されます(ラベルについての詳細は,第 13 章 を参照してください)。GOSUB コマンドは,プロシージャ・レベルあたり最大 16 までネストすることができます。

GOSUB コマンドは,ローカル・サブルーチン・コールの 1 つで,新しいプロシージャ・レベルは作成しません。このため,現在のコマンド・レベルで定義されているすべてのラベルとローカル・シンボルを GOSUB によって起動されたサブルーチンで使用できます。

RETURN コマンドは,サブルーチンを終了して,GOSUB コマンドの後のコマンドに制御を戻します。RETURN コマンドで $STATUS の値を指定すると,DCL がサブルーチンの終了時に $STATUS に割り当てる値を無効にできます。この値は,0 〜 4 の整数か同値式でなければなりません。$STATUS の値を指定すると,DCL はこの値を条件コードとして解釈します。$STATUS の値を指定しないと,$STATUS の現在の値がセーブされます。

次の例は,GOSUB コマンドを使用して制御をサブルーチンに渡す方法を示しています。


$! 
$! GOSUB.COM 
$! 
$ SHOW TIME 
$ GOSUB TEST1            (1)
$ WRITE SYS$OUTPUT "GOSUB level 1 has completed successfully." 
$ SHOW TIME 
$ EXIT 
$! 
$! TEST1 GOSUB definition 
$! 
$ TEST1: 
$     WRITE SYS$OUTPUT "This is GOSUB level 1." 
$     GOSUB TEST2       (2)
$     RETURN %X1        (3)
$! 
$! TEST2 GOSUB definition 
$! 
$ TEST2: 
$     WRITE SYS$OUTPUT "This is GOSUB level 2." 
$     WAIT 00:00:02 
$     RETURN            (4)

例を確かめる場合は,次の点に注意してください。

  1. 最初の GOSUB コマンドは TEST1 のラベルが付いたサブルーチンに制御を渡す。

  2. プロシージャは,TEST1 サブルーチンの中のコマンドを実行して,TEST2 のラベルが付いたサブルーチンに分岐する。

  3. TEST1 サブルーチンの中の RETURN コマンドは,メイン・コマンド・プロシージャに制御を戻し,正しく実行されたことを示す 1 の値を $STATUS に渡す。

  4. TEST2 サブルーチンの中のRETURN コマンドは,TEST1 サブルーチンに制御を戻す。このコマンドは 3 番目のコマンドの前に実行されることに注意。

14.17 新しいコマンド・レベルの作成

新しいコマンド・レベルを作成するには,次の 2 種類の方法があります。

14.17.1 CALL コマンドの使用

CALL コマンドは,コマンド・プロシージャの中のラベルが付いたサブルーチンに制御を渡して,新しいコマンド・レベルを作成します。CALL コマンドを使用すると,1 つのファイルの中に 2 つ以上の関連コマンド・プロシージャを保持できるため,プロシージャを管理しやすくなります。サブルーチン・ラベルは一意でなければならず,コマンド・プロシージャの中の CALL コマンドの前後に置きます。サブルーチン・ラベルの入力規則については,第 13 章 を参照してください。

ラベルに加えて,サブルーチンには最大 8 個のオプション・パラメータを渡すことができます。パラメータについての詳細は,第 14.2 節 を参照してください。

CALL コマンドを使用する場合には,次の規則に従ってください。

14.17.1.1 CALL コマンドの省力時の設定

CALL コマンドを使用する場合には,次の省略時の設定が使用されます。

14.17.1.2 サブルーチンの始まりと終わり

SUBROUTINE コマンドと ENDSUBROUTINE コマンドは,CALL サブルーチンの始まりと終わりを定義します。SUBROUTINE コマンドのすぐ前にサブルーチンへのエントリ・ポイントを定義するラベルを置きます。ENDSUBROUTINE コマンドのすぐ前に EXIT コマンドを置くことができますが,サブルーチンを終了する必要はありません。ENDSUBROUTINE コマンドは,サブルーチンを終了して,CALL コマンドのすぐ後のコマンド行に制御を渡します。

サブルーチンの中のコマンド行が実行されるのは,サブルーチンを CALL コマンドで呼び出す場合だけです。コマンド・プロシージャを行ごとに実行する場合,コマンド言語インタプリタは,SUBROUTINEコマンドと ENDSUBROUTINE コマンドの間のすべてのコマンドをスキップします。

サブルーチン・エントリ・ポイントの有効範囲を定義したり,ラベル参照を使用するときには,次のような制限事項が適用されます。

次の例では,呼び出しは正しくありません。これは,CALL BAR コマンドが MAIN サブルーチンの外部に存在するからです。


$ CALL BAR 
$ 
$ MAIN: SUBROUTINE 
$ 
$     BAR: SUBROUTINE 
$     ENDSUBROUTINE 
$ 
$ ENDSUBROUTINE 

この CALL コマンドが正しく機能するようにするには,このコマンドを,SUBROUTINE と ENDSUBROUTINE で囲まれる部分に指定しなければなりません。

この例に示した呼び出しは,IF-THEN-ELSE ブロックの内部に存在するため,実行できません。


$ IF 1 
$ THEN 
$    BOB:SUBROUTINE 
$    ENDSUBROUTINE 
$ ENDIF 
$ CALL BOB 

次の例には,SUB 1 と SUB2 という 2 つのサブルーチンがあります。これらのサブルーチンは,CALL コマンドで呼び出されるまでは実行されません。


$ 
$! CALL.COM 
$ 
$! Define subroutine SUB1. 
$! 
$ SUB1: SUBROUTINE 
        .
        .
        .
$       CALL SUB2       !Invoke SUB2 from within SUB1. 
        .
        .
        .
$       @FILE           !Invoke another command procedure file. 
        .
        .
        .
$       EXIT 
$ ENDSUBROUTINE !End of SUB1 definition. 
$! 
$! Define subroutine SUB2. 
$! 
$ SUB2: SUBROUTINE 
$       EXIT 
$ ENDSUBROUTINE !End of SUB2 definition. 
$! 
$! Start of main routine. At this point, both SUB1 and SUB2 
$! have been defined but none of the previous commands have 
$! been executed. 
$! 
$ START: 
$       CALL/OUTPUT=NAMES.LOG  SUB1 "THIS IS P1" 
        .
        .
        .
$       CALL SUB2 "THIS IS P1" "THIS IS P2" 
        .
        .
        .
$ EXIT          !Exit this command procedure file. 

CALL コマンドが SUB1 サブルーチンを起動して,出力をNAMES.LOG ファイルに切り換えます。SUB1 サブルーチンは SUB2 サブルーチンを呼び出しています。プロシージャは SUB2 を実行して,プロシージャ実行(@)コマンドによってコマンド・プロシージャ FILE.COM を起動します。SUB1 のすべてのコマンドが実行されると,メイン・プロシージャの中の CALL コマンドが SUB2 をもう一度呼び出します。SUB2 の実行が終わると,プロシージャは終了します。


前へ 次へ 目次 索引