조건(Condition)
본 장에서는 OpenFrame PL/I의 조건 설정에 대해서 설명한다.
1. 조건 처리
조건 처리(Condition Handling)은 PL/I 프로그램이 수행될 때 발생할 수 있는 예외 처리이다.
조건은 특정 조건이 만족하면 발생할 수 있고, 사용자가 직접 해당 조건을 발생시킬 수 있다. 만약 조건이 발생하게 되면 현재 프로그램은 중단되고, 사용자가 지정한 ON-unit을 수행하거나 사용자가 지정한 ON-unit이 없을 경우 내부적으로 지정된 default action을 수행하게 된다. ON-unit이 수행된 후에도 조건의 특성에 따라 다시 해당 라인으로 돌아와 PL/I 프로그램을 계속 수행하거나, 프로그램이 종료된다.
1.1. ON statement
ON statement는 조건이 발생했을 때 지정한 ON-unit을 수행하도록 ON-unit을 등록한다.
항목 | 설명 |
---|---|
condition |
하나 이상의 조건을 지정한다. 조건에 대한 설명은 조건 종류를 참고한다. |
SNAP |
지원되지 않음 |
SYSTEM |
해당 조건에 대해서 기본 동작을 수행하도록 지정한다. 기본 동작에 대한 설명은 조건 종류를 참고한다. |
ON-unit |
해당 조건이 발생했을 때, 수행될 statement들을 기술한다. ON-unit은 하나의 statement 또는 begin-block이 될 수 있다. ON-unit은 ON statement를 수행할 때 수행되지 않고, 해당 조건의 발생 조건이 만족되었을 때 수행된다. |
등록한 조건의 발생조건을 만족했을 때 ON-unit이 수행되며 같은 조건을 여러 번 등록하게 되면, 제일 마지막에 등록된 ON statement의 ON-unit이 실행되게 된다. ON statement로 등록한 조건은 ON statement가 포함된 블록이나 프러시저가 종료될 때 해제되며, REVERT statement를 통해서 사용자가 직접 해제할 수 있다.
다음은 ZERODIVIDE 조건을 등록하는 예제이다.
ON ZERODIVIDE BEGIN; DISPLAY('ZERODIVIDE condition raised'); END; A = B / 0;
ZERODIVIDE 조건은 0으로 나눌 때 발생하는 조건이다. "A = B / 0" 구문에 의해 ZERODIVIDE 조건이 발생하게 되고, ON statement로 등록한 ON-unit이 수행되어 DISPLAY 문장이 수행된다.
1.2. REVERT statement
REVERT statement는 ON statement를 사용하여 등록한 ON-unit을 해제한다.
항목 | 설명 |
---|---|
condition |
하나 이상의 조건을 지정한다. 조건에 대한 설명은 조건 종류를 참고한다. |
REVERT statement는 현재 블록이나 프러시저에 등록된 ON-unit을 해제하며, 현재 블록이나 프러시저에 등록된 ON-unit이 없을 경우 REVERT statement는 수행되지 않는다. 상위 블록이나 프러시저에서 등록한 ON-unit은 해제할 수 없다.
다음은 REVERT statement를 이용하여 등록한 ON-unit을 해제하는 예제이다.
ON ZERODIVIDE BEGIN; DISPLAY('ZERODIVIDE condition raised'); END; REVERT ZERODIVIDE; A = B / 0;
"A = B / 0;" 구문에 의해 ZERODIVIDE 조건이 발생하지만, ON statement로 등록한 ON-unit이 REVERT statement로 해제되어 해당 ON-unit은 수행되지 않는다. 현재 등록되어 있는 ON-unit이 없을 경우 조건 특성에 따라 default action을 수행하는데, ERROR 조건을 발생시키거나 프로그램 수행을 계속한다. ZERODIVIDE는 default action으로 ERROR 조건을 발생시킨다.
1.3. SIGNAL statement
SIGNAL statement는 사용자가 직접 ON-unit을 수행하도록 조건을 발생시킨다.
항목 | 설명 |
---|---|
condition |
조건을 지정한다. 조건에 대한 설명은 조건 종류를 참고한다. |
사용자가 등록한 ON-unit이 있을 경우 해당 ON-unit을 수행하며, 사용자가 지정한 ON-unit이 없을 경우 내부적으로 지정된 default action을 수행하게 된다.
다음은 SIGNAL statement를 사용하여 사용자가 직접 ON-unit을 수행시키는 예제이다.
ON ZERODIVIDE BEGIN; DISPLAY('ZERODIVIDE condition raised'); END; SIGNAL ZERODIVIDE;
SIGNAL statement로 인해 ZERODIVIDE 조건의 ON-unit이 수행된다. I/O 관련 조건의 경우 해당 조건이 발생하더라도 파일이 다를 경우 해당 ON-unit은 수행되지 않는다.
1.4. 조건 접두사
사용자는 조건 접두사(Condition Prefix)를 통해 조건을 활성화하거나 비활성화할 수 있다.
조건 접두사는 statement, begin-block, procedure 앞에 올 수 있으며, begin-block, procedure 앞에 올 경우 해당 블록이나 프러시저 내의 모든 statement에 조건 접두사가 적용된다.
다음은 조건 접두사를 사용하여 해당 조건을 활성화, 비활성화하는 예제이다.
(SIZE):A:PROCEDURE; ... (NOSIZE) B = C; D = E; ... END A;
기본적으로 PROCEDURE A 안의 statement들은 SIZE 접두사를 통해 SIZE 조건을 체크한다. NOSIZE 접두사가 붙은 "B = C;" 구문에서는 SIZE 조건을 체크하지 않는다. 조건 접두사의 우선순위는 statement 앞의 붙은 조건 접두사가 있으면 해당 접두사를 가장 먼저 적용하고, 없을 경우 상위 블록의 접두사 순서대로 적용한다. 아무런 조건 접두사가 없을 경우 default 접두사를 적용한다.
조건이 enable되면 컴파일러는 조건을 발생할 수 있는지 check를 해서 만족할 경우 해당 조건의 ON-unit을 찾아 수행한다. 조건 접두사를 통해 조건을 비활성화하고 조건이 발생할 경우 프로그램은 에러에 빠질 수 있다.
I/O 관련 조건과 일부 조건은 조건 접두사를 통해 조건을 비활성화할 수 없다. 조건에 대한 활성/비활성화에 대한 기본값은 조건 종류에서 각 조건의 상태 설명을 참고한다.
2. 조건 종류
본 절에서는 여러 조건에 대한 설명한다.
현재 OpenFrame PL/I에서 지원하는 조건은 다음과 같다.
조건 | 설명 |
---|---|
다른 모든 조건이 발생하고, 해당 조건에 대한 ON-unit이 존재하지 않을 때 발생한다. |
|
기저부 변수(Based variable)를 AREA에 할당하지 못하거나 AREA assignment를 수행하지 못할 때 발생한다. |
|
사용자가 조건 이름을 정의하고, 정의한 이름으로 조건을 등록하고 수행할 수 있다. |
|
ASSIGNMENT statement나 I/O 도중 발생할 수 있다. |
|
GET statement나 READ statement로 데이터셋의 마지막 레코드를 읽을 경우 발생한다. |
|
PRINT 파일에서 지정한 PAGESIZE 값(기본값 60)보다 현재 라인 수가 더 클경우 발생한다. |
|
ERROR 조건은 여러 조건들의 기본 동작 또는 일부 조건들의 정상 동작으로 발생된다. |
|
메인 프러시저가 종료될 때 발생한다. |
|
FIXED DECIMAL 타입의 산술 연산 결과 값이 15자리를 넘을 경우 발생한다. |
|
여러 statement에 따라서 KEY 조건을 사용한다. |
|
GET statement에서 data-directed I/O 도중 발생할 수 있다. |
|
floating-point의 최댓값을 넘을 경우 발생한다. |
|
READ, WRITE, REWRITE statement의 변수의 길이에 따라서 사용된다. |
|
ASSIGNMENT statement나 I/O 도중 발생할 수 있다. |
|
I/O 도중 RECORD나 KEY 조건을 제외한 다른 에러 상황에서 발생한다. |
|
파일을 열지 못했을 때 발생한다. |
|
floating-point의 값이 0이 아닌 IEEE floating-point로 표현될 수 있는 최솟값보다 작을 경우 발생한다. |
|
ZERODIVIDE는 0으로 나누려고 시도할 때 발생한다. |
ATTENTION, INVALIDOP, STORAGE, STRINGRANGE, STRINGSIZE, SUBSCRIPTRANGE은 지원하지 않는다. |
각 조건에 대한 자세한 내용은 각 절의 상세 설명을 참고한다. 각 절에서는 조건에 대해 상태, 문법, 기본 동작, 정상 동작, 코드에 대한 설명한다.
항목 | 설명 |
---|---|
상태 |
조건의 기본 상태에 대한 설명이다. 활성, 비활성, 항상 활성으로 나눌 수 있다. |
문법 |
해당 조건의 문법에 대한 설명이다. |
기본 동작 |
해당 조건이 발생했을 때 ON-unit이 없을 경우 동작에 대한 설명이다. |
정상 동작 |
해당 조건이 발생했을 때 ON-unit이 있을 경우 ON-unit을 수행한 이후에 대한 설명이다. |
코드 |
조건에 대한 코드값 설명이다. 조건 코드에 대한 설명은 ONCODE를 참고한다. |
2.1. ANYCONDITION(약어: ANYCOND)
ANYCONDITION은 다른 모든 조건이 발생하고, 해당 조건에 대한 ON-unit이 존재하지 않을 때 발생한다.
사용자가 직접 SIGNAL statement를 사용하여 ANYCONDITION을 발생시킬 수 없다.
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
항상 활성 |
문법 |
|
동작 |
|
코드 |
없음 |
2.2. AREA
AREA 조건은 다음과 같은 상황에서 발생한다.
-
기저부 변수(Based variable)를 AREA에 할당할 때 AREA에 기저부 변수(Based variable) 크기 만큼 할당할 공간이 부족한 경우
-
AREA 변수를 다른 AREA 변수에 assignment를 수행할 때 target AREA에 할당된 크기가 source AREA의 크기보다 클 경우
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
항상 활성 |
문법 |
|
동작 |
|
코드 |
360, 361, 362 |
2.3. CONDITION(약어: COND)
CONDITION 조건은 사용자가 조건 이름을 정의하고, 정의한 이름으로 조건을 등록하고 수행할 수 있다.
CONDITION 조건은 SIGNAL statement로만 수행할 수 있다. CONDITION 조건을 등록하고 수행하기 위해서는 CONDITION attribute를 이용하여 조건 이름을 정의해야 한다.
다음은 CONDITION attribute를 이용하여 조건 이름을 정의하는 예이다.
DCL TEST CONDITION;
다음은 조건 이름으로 조건을 등록하고 수행하는 예이다.
ON CONDITION (TEST) BEGIN; ... END; ... SIGNAL CONDITION (TEST);
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
항상 활성 |
문법 |
|
동작 |
|
코드 |
500 |
2.4. CONVERSION(약어: CONV)
CONVERSION 조건은 ASSIGNMENT statement나 I/O 도중 발생할 수 있다.
CONVERSION 조건이 발생할 수 있는 자세한 상황은 다음과 같다.
-
Character를 Bit로 변환하는 경우 Character에 0 또는 1이 아닌 값이 존재할 때
-
Character를 산술 데이터로 변환하는 경우 숫자가 아닌 값이 존재할 때
-
Character Picture로 변환하는 경우 Picture 정의에 허용되지 않는 값이 존재할 때
CONVERSION 조건이 발생하면 ON-unit에서 ONCHAR 또는 ONSOURCE 내장함수(built-in function)를 통해 CONVERSION이 발생한 데이터 값을 볼 수 있다. 또한 ONCHAR, ONSOURCE 의사 변수(pseudo variable)를 통해 CONVERSION이 발생한 데이터 값을 수정할 수 있다. 자세한 설명은 ONSOURCE와 ONCHAR를 참고한다.
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
활성 |
문법 |
|
동작 |
|
코드 |
600, 612, 615, 618 |
2.5. ENDFILE
GET statement나 READ statement로 데이터셋의 마지막 레코드를 읽을 경우 발생한다.
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
항상 활성 |
문법 |
|
동작 |
|
코드 |
70 |
2.6. ENDPAGE
PRINT File에서 지정한 PAGESIZE 값(기본값 60)보다 현재 라인 수가 더 클 경우 발생한다.
ON-unit에서 PAGE 옵션이나 PAGE format 항목으로 새로운 페이지에서 시작할 수 있으며 라인 수는 1로 초기화된다. 만약 새로운 페이지를 시작하지 않으면 라인 수는 계속 증가하며 새로운 페이지를 시작하기 전까지 ENDPAGE 조건은 발생하지 않는다.
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
항상 활성 |
문법 |
|
동작 |
|
코드 |
90 |
2.7. ERROR
ERROR 조건은 여러 조건들의 기본 동작 또는 일부 조건들의 정상 동작으로 발생된다. 정의되지 않은 에러 상황에서도 ERROR 조건이 발생될 수 있다.
ERROR 조건의 ON-unit을 수행하는 도중 ERROR 조건이 발생하면 또 다시 ERROR 조건의 ON-unit을 수행하기 때문에 무한 반복에 빠질 수 있다. ERROR 조건의 ON-unit 제일 처음에 "ON ERROR SYSTEM;" 구문을 넣으면 ERROR 조건에 대한 기본 동작을 수행하도록 지정하여 ERROR 조건에 대한 무한 반복 문제를 방지할 수 있다.
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
항상 활성 |
문법 |
|
동작 |
|
코드 |
1000 이상 |
2.8. FINISH
메인 프러시저가 종료될 때 발생한다.
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
활성 |
문법 |
|
동작 |
|
코드 |
4 |
2.9. FIXEDOVERFLOW(약어: FOFL)
FIXED DECIMAL 타입의 산술 연산 결과 값이 15자리를 넘을 경우 발생한다.
다음과 같은 경우 FIXEDOVERFLOW 조건이 발생한다.
DCL A FIXED DEC(15) INIT(1234567890); DCL B FIXED DEC(15) INIT(123456); DISPLAY(A * B);
위 예제에서 A * B 연산의 결과가 16자리이기 때문에 FIXED DECIMAL의 최대 자리수를 넘게 되고 FIXEDOVERFLOW 조건이 발생한다.
연산의 결과가 FIXED BINARY일 경우 FIXEDOVERFLOW 조건은 발생하지 않는다. ADD, SUB, MUL, DIV 내장함수으로는 FIXEDOVERFLOW 조건이 발생하지 않는다.
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
활성 |
문법 |
|
동작 |
|
코드 |
310 |
2.10. KEY
KEY 조건은 다음과 같은 상황에서 발생한다.
-
READ, REWRITE, DELETE statement에서 KEY 옵션에 대한 레코드가 존재하지 않을 때
-
WRITE, LOCATE statement에서 KEYFROM 옵션에 대해 데이터셋에 이미 해당 KEY가 존재할 때
-
Indexed 데이터셋에서 정의한 KEY 길이와 KEY 옵션으로 지정한 변수의 길이가 다를 경우
LOCATE statement를 사용할 경우 KEY 조건은 다음 LOCATE statement나 FLUSH statement 또는 CLOSE statement를 사용할 때 발생한다.
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
항상 활성 |
문법 |
|
동작 |
|
코드 |
50, 51, 52 |
2.11. NAME
NAME 조건은 GET statement에서 data-directed I/O 도중 다음과 같은 상황에서 발생한다.
-
매칭되는 이름이 존재하지 않거나 올바르지 않을 때
-
배열 첨자가 없거나 옳바르지 않을 때
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
항상 활성 |
문법 |
|
동작 |
|
코드 |
10 |
2.12. OVERFLOW(약어: OFL)
OVERFLOW는 floating-point의 최댓값을 넘을 경우 발생한다.
floating-point의 최댓값은 다음과 같다.
-
FLOAT DECIMAL digit number 1~6, FLOAT BINARY digit number 1 ~ 21 : 3. 40282347E+38F
-
FLOAT DECIMAL digit number 7 ~ 16, FLOAT BINARY digit number 22 ~ 53 : 1.7976931348623157E+308
음수 값도 마찬가지로 해당 최댓값을 넘을 경우 OVERFLOW가 발생한다. |
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
활성 |
문법 |
|
동작 |
|
코드 |
300 |
2.13. RECORD
RECORD 조건은 다음과 같은 상황에서 발생한다.
-
데이터셋의 레코드 길이가 READ statement의 변수의 길이보다 클 경우
-
데이터셋의 레코드 길이가 WRITE, REWRITE statement의 변수의 길이보다 작을 경우
RECORD 조건이 발생하면 초과된 길이는 절단(truncate)된다.
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
항상 활성 |
문법 |
|
동작 |
|
코드 |
21, 22 |
2.14. SIZE
SIZE 조건은 ASSIGNMENT statement나 I/O 도중 발생할 수 있다.
SIZE 조건이 발생할 수 있는 자세한 상황은 다음과 같다.
-
ASSIGNMENT statement 수행시 가장 왼쪽의 숫자의 손실이 일어나는 경우
-
I/O 수행시 가장 왼쪽의 숫자의 손실이 일어나는 경우
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
비활성 |
문법 |
|
동작 |
|
코드 |
340 |
2.15. TRANSMIT
TRANSMIT 조건은 I/O 도중 RECORD나 KEY 조건을 제외한 다른 에러 상황에서 발생한다.
OpenFrame PL/I는 OpenFrame의 파일 시스템을 사용하기 때문에 TRANSMIT 조건이 발생할 경우 OpenFrame의 에러 메세지를 참고한다.
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
항상 활성 |
문법 |
|
동작 |
|
코드 |
41, 42 |
2.16. UNDEFINEDFILE(약어: UNDF)
UNDEFINEDFILE 조건은 파일을 열지 못했을 때 발생한다.
다음과 같은 상황에서 발생한다.
-
이미 파일이 열려 있을 때
-
DD를 찾을 수 없을 때
-
데이터셋의 정보를 가져올 수 없을 때
-
데이터셋의 속성과 파일에서 지정한 속성들 사이에 충돌이 발생할 때
-
Indexed 데이터셋의 키 길이가 0일 때
-
Indexed 데이터셋에서 KEYLOC 옵션의 값을 정의했을 때 KEYLENGTH + KEYLOC의 값이 레코드 길이보다 클 때
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
항상 활성 |
문법 |
|
동작 |
|
코드 |
93 |
2.17. UNDERFLOW(약어: UFL)
UNDERFLOW는 floating-point의 값이 0이 아닌 IEEE floating-point로 표현될 수 있는 최솟값보다 작을 경우 발생한다.
Floating-point 최솟값은 다음과 같다.
-
FLOAT DECIMAL digit number 1~6, FLOAT BINARY digit number 1 ~ 21 : 1. 17549435E-38F
-
FLOAT DECIMAL digit number 7 ~ 16, FLOAT BINARY digit number 22 ~ 53 : 2. 2250738585072014E-308
음수 값도 마찬가지로 해당 최솟값보다 작을 경우 UNDERFLOW가 발생한다. |
다음은 조건에 대한 상세 설명이다.
구분 | 설명 |
---|---|
상태 |
활성 |
문법 |
|
동작 |
|
코드 |
330 |