COBOL · 기본
데이터 처리로 배우는 COBOL
서브프로그램과 카피북 - 나누어 재사용하기
CALL ... USING, LINKAGE SECTION, BY REFERENCE·BY CONTENT, GOBACK, COPY 문으로 레코드 정의 공유, 여러 파일 컴파일
개발자KR · 원고 갱신
이 장에서 배우는 것
앞 장까지는 프로그램 하나가 파일을 읽고, 계산하고, 보고서까지 모두 맡았다. 프로그램이 커지면 한 파일에 수백 줄이 쌓이고, 같은 레코드 정의를 여러 프로그램에 복사해 붙이게 된다. 이 장에서는 일을 나누는 두 가지 방법을 배운다. 하나는 다른 프로그램을 불러 쓰는 서브프로그램(subprogram)이고, 다른 하나는 자주 쓰는 정의를 별도 파일에 두고 가져다 쓰는 카피북(copybook)이다. 예제는 계좌 한 개에 입출금 거래를 적용하는 일을 서브프로그램으로 떼어 내는 것이다.
- CALL ... USING 으로 다른 프로그램을 부르고 값을 주고받는다.
- LINKAGE SECTION 에 받는 쪽의 데이터 정의를 쓰고, GOBACK 으로 돌아간다.
- BY REFERENCE 와 BY CONTENT 의 차이를 설명하고 상황에 맞게 고른다.
- COPY 문으로 레코드 정의를 한 파일에 두고 여러 프로그램이 공유한다.
- cobc 로 여러 소스 파일을 한 번에 컴파일해 하나의 실행 파일로 묶는다.
문제 상황
신용협동조합의 전산 담당자가 일일 거래 처리 프로그램을 만들고 있다. 입금과 출금을 계좌 잔액에 반영하는 규칙은 곧 다른 프로그램에서도 필요해진다. 창구 입력 점검 프로그램도, 월말 정산 프로그램도 같은 규칙을 써야 한다. 규칙을 각 프로그램에 복사해 두면 한쪽만 고치고 다른 쪽을 빠뜨리는 일이 생긴다. 예를 들어 출금 때 잔액 부족을 판단하는 기준이 바뀌었는데 두 프로그램의 결과가 달라진다.
계좌 레코드 정의도 마찬가지다. 잔액 자릿수를 늘려야 할 때 정의를 복사해 둔 파일이 열 개라면 열 곳을 고쳐야 하고, 하나라도 놓치면 프로그램끼리 레코드를 다르게 해석한다. 규칙은 서브프로그램 한 곳에, 정의는 카피북 한 곳에 두고 나머지가 그것을 가져다 쓰도록 바꾸는 것이 이 장의 목표다.
서브프로그램: CALL, LINKAGE SECTION, GOBACK
부르는 쪽과 불리는 쪽
서브프로그램은 독립된 COBOL 프로그램이다. IDENTIFICATION DIVISION 과 PROGRAM-ID 를 갖고, 따로 컴파일할 수 있다. 부르는 쪽(호출자)은 CALL 문으로 프로그램 이름을 지정하고, 넘겨줄 데이터를 USING 뒤에 나열한다. 넘겨주는 값을 인자라고 부른다.
CALL "APPLYTRX" USING BY CONTENT TR-REC
BY REFERENCE ACCT-REC
BY REFERENCE RES-CODE
END-CALL
불리는 쪽(피호출자)은 PROCEDURE DIVISION 머리에 USING 을 쓰고, 받을 데이터를 LINKAGE SECTION 에 정의한다. LINKAGE SECTION 은 WORKING-STORAGE 와 모양이 같지만 저장 공간을 새로 만들지 않는다. 호출자가 넘겨준 데이터의 위치에 이름을 붙이는 곳이다. 그래서 VALUE 로 초기값을 줄 수 없다.
인자는 이름이 아니라 순서로 짝지어진다. 호출자의 첫째 인자가 피호출자 USING 의 첫째 이름과 연결된다. 두 쪽의 이름이 달라도 되고, 다르게 짓는 일도 흔하다. 대신 순서와 자리 크기가 맞아야 한다. 컴파일러는 파일을 따로 컴파일하기 때문에 이 일치를 검사해 주지 않는다.
서브프로그램은 GOBACK 으로 끝낸다. GOBACK 은 불러 준 곳으로 되돌아가라는 뜻이다. 같은 자리에 STOP RUN 을 쓰면 서브프로그램이 아니라 프로그램 전체가 끝난다. 호출자 쪽 가장 바깥 프로그램은 STOP RUN 으로 끝내는 것이 관례다.
한 가지 더 알아 둘 점이 있다. 서브프로그램의 WORKING-STORAGE 는 처음 호출될 때 한 번 초기화되고, 이후 호출 사이에는 값이 남아 있다. 호출할 때마다 새로 시작하는 변수가 아니다.
BY REFERENCE 와 BY CONTENT
인자를 넘기는 방식은 두 가지다. BY REFERENCE 는 데이터가 있는 자리를 알려 준다. 서브프로그램이 그 값을 고치면 호출자의 변수도 바뀐다. 아무것도 쓰지 않으면 이 방식이 기본이다. BY CONTENT 는 값을 임시 사본으로 만들어 그 사본의 자리를 넘긴다. 서브프로그램이 사본을 고쳐도 호출자의 원래 값은 그대로다.
| 구분 | BY REFERENCE | BY CONTENT |
|---|---|---|
| 넘기는 것 | 원본의 위치 | 값의 사본 |
| 서브프로그램이 고치면 | 호출자의 값이 바뀐다 | 호출자의 값은 그대로다 |
| 쓰는 경우 | 결과를 돌려받을 때 | 읽기만 시킬 때 |
이 장의 예제에서 거래 레코드는 서브프로그램이 읽기만 해야 하므로 BY CONTENT 로 넘긴다. 계좌 레코드와 결과 코드는 서브프로그램이 고쳐서 돌려줘야 하므로 BY REFERENCE 로 넘긴다. 예제의 서브프로그램은 일부러 거래 금액 칸을 0 으로 지운다. 호출자의 금액이 그대로 남는다는 사실에서 BY CONTENT 의 효과를 눈으로 확인할 수 있다.
카피북: COPY 로 정의 공유하기
카피북은 데이터 정의나 문장을 담은 별도의 텍스트 파일이다. 소스에 COPY 이름. 이라고 쓰면 컴파일러가 그 자리에 파일 내용을 그대로 끼워 넣은 뒤 컴파일한다. 파일 확장자는 보통 .cpy 이고, 이름은 COPY 뒤에 쓴 이름과 같게 한다. 이 장에서는 파일 이름을 대문자로 맞춘다. 파일 시스템이 대소문자를 구분하는 환경에서도 같은 이름으로 찾을 수 있게 하려는 것이다. COPY 는 프로그램이 실행될 때가 아니라 컴파일할 때 한 번 일어나는 복사다.
카피북의 내용도 고정 형식 규칙을 따른다. 01 레벨은 8열(A 영역)부터, 하위 항목은 12열(B 영역)부터 시작한다. COPY 문은 자기 줄 끝에 마침표를 붙인다. 주의할 점은 카피북 안에 VALUE 를 넣을 때다. 같은 카피북을 LINKAGE SECTION 에서 쓰면 VALUE 는 허용되지 않으므로, 여러 곳에서 공유하는 정의에는 초기값을 넣지 않는 편이 안전하다.
| 파일 | 담긴 정의 | 쓰이는 곳 |
|---|---|---|
| TRANSREC.cpy | 거래 레코드 TR-REC | MAIN 의 FD, APPLYTRX 의 LINKAGE |
| ACCTREC.cpy | 계좌 레코드 ACCT-REC | MAIN 의 WORKING-STORAGE, APPLYTRX 의 LINKAGE |
| RESCODE.cpy | 결과 코드 RES-CODE 와 조건 이름 | MAIN 의 WORKING-STORAGE, APPLYTRX 의 LINKAGE |
결과 코드를 카피북에 둔 이유는 숫자의 뜻을 한 곳에만 적기 위해서다. 서브프로그램은 SET RES-NO-FUNDS TO TRUE 처럼 이름으로 코드를 쓰고, 호출자는 WHEN RES-NO-FUNDS 처럼 이름으로 검사한다. 숫자 1 이 무슨 뜻인지는 카피북만 알면 된다.
이름의 일부를 바꿔 가져와야 할 때는 REPLACING 을 쓴다. 예를 들어 COPY ACCTREC REPLACING ==ACCT-REC== BY ==SAVED-REC==. 은 01 레벨의 이름만 바꾼다. 바꿀 대상은 낱말 하나씩 통째로 일치해야 하므로, ACCT-NO 같은 하위 항목 이름은 그대로 남는다. 이 장의 예제는 REPLACING 을 쓰지 않는다.
여러 파일 컴파일
소스가 둘 이상이면 cobc 에 파일을 모두 나열한다. -x 옵션은 첫 번째 파일을 실행 파일의 시작점으로 삼고, 나머지 파일은 같은 실행 파일에 묶어 넣는다. 이 책의 규칙대로 시작점은 main.cob 이므로 main.cob 을 맨 앞에 쓴다.
cobc -x -Wall main.cob APPLYTRX.cob
카피북은 명령에 쓰지 않는다. 컴파일러가 COPY 문을 만날 때 현재 폴더에서 찾는다. 다른 폴더에 두었다면 -I 폴더이름 옵션으로 찾을 위치를 알려 준다. 서브프로그램을 고쳤다면 실행 파일을 다시 만들어야 한다. 카피북을 고쳤다면 그것을 COPY 하는 모든 소스를 다시 컴파일해야 한다. 카피북은 컴파일 때 소스에 박히므로, 다시 컴파일하지 않은 프로그램은 옛 정의를 그대로 가진다.
완성 코드
다섯 파일을 같은 폴더에 둔다. 입력 파일 trans.dat 의 각 줄은 정확히 20자이고, 거래번호 4자리, 계좌번호 6자리, 구분 1자(D 입금, W 출금), 금액 9자리 순서다.
main.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT TRANS-FILE ASSIGN TO "trans.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD TRANS-FILE.
COPY TRANSREC.
WORKING-STORAGE SECTION.
COPY ACCTREC.
COPY RESCODE.
01 WS-EOF-FLAG PIC X VALUE "N".
88 WS-EOF VALUE "Y".
01 WS-OK-COUNT PIC 9(3) VALUE 0.
01 WS-REJECT-COUNT PIC 9(3) VALUE 0.
01 WS-MSG PIC X(10).
01 WS-AMT-SHOW PIC ZZZ,ZZZ,ZZ9.
01 WS-BAL-SHOW PIC ----,---,--9.
PROCEDURE DIVISION.
MAIN-PARA.
MOVE 100201 TO ACCT-NO
MOVE "KIM MINSU" TO ACCT-NAME
MOVE 100000 TO ACCT-BALANCE
DISPLAY "ACCOUNT " ACCT-NO " " ACCT-NAME
MOVE ACCT-BALANCE TO WS-BAL-SHOW
DISPLAY "OPENING BALANCE " WS-BAL-SHOW
OPEN INPUT TRANS-FILE
PERFORM UNTIL WS-EOF
READ TRANS-FILE
AT END
SET WS-EOF TO TRUE
NOT AT END
PERFORM PROCESS-ONE
END-READ
END-PERFORM
CLOSE TRANS-FILE
MOVE ACCT-BALANCE TO WS-BAL-SHOW
DISPLAY "CLOSING BALANCE " WS-BAL-SHOW
DISPLAY "ACCEPTED " WS-OK-COUNT
DISPLAY "REJECTED " WS-REJECT-COUNT
STOP RUN.
PROCESS-ONE.
CALL "APPLYTRX" USING BY CONTENT TR-REC
BY REFERENCE ACCT-REC
BY REFERENCE RES-CODE
END-CALL
EVALUATE TRUE
WHEN RES-OK
MOVE "OK" TO WS-MSG
ADD 1 TO WS-OK-COUNT
WHEN RES-NO-FUNDS
MOVE "NO FUNDS" TO WS-MSG
ADD 1 TO WS-REJECT-COUNT
WHEN RES-WRONG-ACCT
MOVE "WRONG ACCT" TO WS-MSG
ADD 1 TO WS-REJECT-COUNT
WHEN OTHER
MOVE "BAD TYPE" TO WS-MSG
ADD 1 TO WS-REJECT-COUNT
END-EVALUATE
MOVE TR-AMOUNT TO WS-AMT-SHOW
MOVE ACCT-BALANCE TO WS-BAL-SHOW
DISPLAY TR-SEQ " " TR-TYPE " " WS-AMT-SHOW " "
WS-MSG " " WS-BAL-SHOW.
APPLYTRX.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. APPLYTRX.
DATA DIVISION.
LINKAGE SECTION.
COPY TRANSREC.
COPY ACCTREC.
COPY RESCODE.
PROCEDURE DIVISION USING TR-REC ACCT-REC RES-CODE.
APPLY-PARA.
SET RES-OK TO TRUE
EVALUATE TRUE
WHEN TR-ACCT-NO NOT = ACCT-NO
SET RES-WRONG-ACCT TO TRUE
WHEN TR-TYPE = "D"
ADD TR-AMOUNT TO ACCT-BALANCE
WHEN TR-TYPE = "W"
IF TR-AMOUNT > ACCT-BALANCE
SET RES-NO-FUNDS TO TRUE
ELSE
SUBTRACT TR-AMOUNT FROM ACCT-BALANCE
END-IF
WHEN OTHER
SET RES-BAD-TYPE TO TRUE
END-EVALUATE
MOVE ZERO TO TR-AMOUNT
GOBACK.
TRANSREC.cpy
01 TR-REC.
05 TR-SEQ PIC 9(4).
05 TR-ACCT-NO PIC 9(6).
05 TR-TYPE PIC X.
05 TR-AMOUNT PIC 9(9).
ACCTREC.cpy
01 ACCT-REC.
05 ACCT-NO PIC 9(6).
05 ACCT-NAME PIC X(9).
05 ACCT-BALANCE PIC S9(9).
RESCODE.cpy
01 RES-CODE PIC 9.
88 RES-OK VALUE 0.
88 RES-NO-FUNDS VALUE 1.
88 RES-WRONG-ACCT VALUE 2.
88 RES-BAD-TYPE VALUE 3.
trans.dat
0001100201D000050000
0002100201W000020000
0003100201W000500000
0004100305D000010000
0005100201X000001000
0006100201D000125000
줄별 해설
main.cob
- FD TRANS-FILE 아래의 COPY TRANSREC. 은 거래 레코드 정의를 파일 레코드로 쓴다. 파일에서 읽은 한 줄이 그대로 TR-REC 에 들어온다.
- WORKING-STORAGE 의 COPY ACCTREC. 와 COPY RESCODE. 는 계좌 레코드와 결과 코드를 만든다. 이어지는 WS- 항목들은 이 프로그램에서만 쓰는 값이다.
- WS-AMT-SHOW 는 금액을 천 단위 쉼표와 함께 보여 주는 편집 항목이고, WS-BAL-SHOW 는 앞쪽에 떠 있는 음수 부호를 쓰는 편집 항목이다. 잔액이 음수가 될 가능성에 대비한 것이며, 이번 입력에서는 부호가 보이지 않는다.
- MAIN-PARA 는 먼저 계좌번호, 이름, 시작 잔액을 채운다. 카피북에는 VALUE 를 넣지 않았으므로 값은 여기서 MOVE 로 준다.
- PERFORM UNTIL WS-EOF 반복은 한 줄을 읽을 때마다 PROCESS-ONE 을 부르고, 파일 끝에서 WS-EOF 를 참으로 만들어 끝난다.
- PROCESS-ONE 의 CALL 에서 거래 레코드는 BY CONTENT, 계좌 레코드와 결과 코드는 BY REFERENCE 로 넘긴다. CALL 이 끝나면 RES-CODE 에 서브프로그램이 정한 결과가 들어 있다.
- EVALUATE TRUE 는 RES-OK 같은 조건 이름으로 결과를 가르고, 성공과 거절 건수를 센다. 코드 숫자는 이 프로그램에 한 번도 나오지 않는다.
- 마지막 DISPLAY 직전에 TR-AMOUNT 를 편집 항목으로 옮긴다. 서브프로그램이 금액 칸을 0 으로 지웠지만 사본이었으므로 원래 금액이 그대로 보인다.
APPLYTRX.cob
- PROGRAM-ID. APPLYTRX. 가 CALL "APPLYTRX" 의 이름과 같아야 한다.
- LINKAGE SECTION 에 세 카피북을 COPY 한다. 새 저장 공간이 생기는 것이 아니라 호출자가 넘겨준 데이터에 이름이 붙는다.
- PROCEDURE DIVISION USING TR-REC ACCT-REC RES-CODE 의 순서는 호출자의 USING 순서와 같다.
- SET RES-OK TO TRUE 로 결과를 먼저 정상으로 맞춰 둔다. 서브프로그램은 호출 때마다 결과를 직접 정해 줘야 이전 호출의 결과가 남지 않는다.
- EVALUATE 의 첫째 WHEN 은 거래의 계좌번호가 계좌 레코드와 다른 경우를 거른다. 이어서 입금은 잔액에 더하고, 출금은 금액이 잔액보다 크면 잔액 부족으로 돌려보내며, 그 밖의 구분 문자는 잘못된 구분으로 처리한다.
- MOVE ZERO TO TR-AMOUNT 는 BY CONTENT 의 효과를 보이려는 줄이다. 실제 업무 코드에서는 필요 없다.
- GOBACK 으로 MAIN 의 CALL 다음 줄로 돌아간다.
실행 결과
다섯 파일이 있는 폴더에서 다음 명령을 실행한다. 컴파일 경고는 나오지 않는다.
$ cobc -x -Wall main.cob APPLYTRX.cob
$ ./main
ACCOUNT 100201 KIM MINSU
OPENING BALANCE 100,000
0001 D 50,000 OK 150,000
0002 W 20,000 OK 130,000
0003 W 500,000 NO FUNDS 130,000
0004 D 10,000 WRONG ACCT 130,000
0005 X 1,000 BAD TYPE 130,000
0006 D 125,000 OK 255,000
CLOSING BALANCE 255,000
ACCEPTED 003
REJECTED 003
3번 거래는 잔액 130,000 보다 큰 500,000 을 출금하려 해서 거절됐고, 4번은 계좌번호가 달라서, 5번은 구분 문자가 D 나 W 가 아니어서 거절됐다. 거절된 거래 뒤에도 잔액이 그대로인 점을 확인한다.
실무에서 자주 틀리는 것
인자 순서를 바꿔 호출한다
인자는 이름이 아니라 순서로 연결된다. 아래 호출은 APPLYTRX 가 첫째 자리를 거래 레코드로 해석하는데 계좌 레코드를 넘기고 있다.
*> 틀림
CALL "APPLYTRX" USING BY REFERENCE ACCT-REC
BY CONTENT TR-REC
BY REFERENCE RES-CODE
END-CALL
컴파일은 통과하고, 실행하면 엉뚱한 칸을 거래 금액으로 읽는다. 호출 쪽 순서를 서브프로그램의 USING 과 똑같이 맞춘다.
*> 고침
CALL "APPLYTRX" USING BY CONTENT TR-REC
BY REFERENCE ACCT-REC
BY REFERENCE RES-CODE
END-CALL
서브프로그램을 STOP RUN 으로 끝낸다
*> 틀림: 첫 거래를 처리하고 프로그램 전체가 끝난다
MOVE ZERO TO TR-AMOUNT
STOP RUN.
STOP RUN 은 실행 단위 전체를 끝낸다. MAIN 의 읽기 반복은 첫 거래 뒤에 중단되고 합계도 나오지 않는다. 호출자에게 돌아가려면 GOBACK 을 쓴다.
*> 고침
MOVE ZERO TO TR-AMOUNT
GOBACK.
서브프로그램의 변수가 호출마다 초기화된다고 믿는다
*> 틀림: 호출할 때마다 1 이 나온다고 가정
WORKING-STORAGE SECTION.
01 WS-TRIES PIC 9(3) VALUE 0.
...
ADD 1 TO WS-TRIES
VALUE 는 처음 호출될 때 한 번만 적용된다. 두 번째 호출에서 WS-TRIES 는 앞 호출이 남긴 값에서 출발하므로 1, 2, 3 으로 계속 늘어난다. 호출마다 새로 시작하려면 PROCEDURE DIVISION 첫머리에서 직접 값을 정한다.
*> 고침
APPLY-PARA.
MOVE 0 TO WS-TRIES
ADD 1 TO WS-TRIES
컴파일 명령에 서브프로그램을 빠뜨린다
*> 틀림
$ cobc -x -Wall main.cob
$ ./main
main.cob 만으로도 컴파일은 끝난다. 그러나 실행하면 APPLYTRX 모듈을 찾지 못했다는 취지의 libcob 오류가 나면서 멈춘다. 서브프로그램의 소스도 명령에 함께 적는다.
*> 고침
$ cobc -x -Wall main.cob APPLYTRX.cob
$ ./main
한눈에 보기
| 문장 | 어디에 쓰나 | 역할 |
|---|---|---|
| CALL "이름" USING ... | 호출자의 PROCEDURE DIVISION | 서브프로그램을 부르고 인자를 넘긴다 |
| BY REFERENCE | CALL 의 USING 안 | 원본을 공유한다. 생략하면 이 방식이다 |
| BY CONTENT | CALL 의 USING 안 | 사본을 넘긴다 |
| LINKAGE SECTION | 서브프로그램의 DATA DIVISION | 넘겨받는 데이터에 이름을 붙인다. VALUE 는 쓰지 않는다 |
| PROCEDURE DIVISION USING | 서브프로그램 | 받을 이름을 호출자 순서대로 나열한다 |
| GOBACK | 서브프로그램의 끝 | 호출자로 돌아간다 |
| COPY 이름. | 어느 DIVISION 이든 | 컴파일할 때 카피북을 끼워 넣는다 |
| cobc -x main.cob 서브.cob | 명령줄 | 여러 소스를 한 실행 파일로 묶는다 |
연습 문제
- 입금 한도 규칙을 추가한다. 입금 금액이 1,000,000 을 넘으면 새 결과 코드 4(RES-OVER-LIMIT)로 거절한다. 어떤 파일을 고쳐야 하고 각각 무엇을 추가하는지 쓴다.
- main.cob 의 CALL 에서 거래 레코드 앞의 BY CONTENT 를 BY REFERENCE 로 바꾸면 실행 결과의 어느 부분이 달라지는지 설명한다.
- 출금 금액의 1% 를 수수료로 계산해 돌려주는 서브프로그램 CALCFEE 를 만든다. 금액은 읽기만 하고 수수료는 돌려받는다. 호출하는 CALL 문과 컴파일 명령도 쓴다.
- ACCTREC.cpy 의 ACCT-NAME 을 PIC X(9) 에서 PIC X(20) 으로 늘렸다. 다시 컴파일해야 하는 소스는 무엇인가.
정답과 해설
- 세 파일을 고친다. RESCODE.cpy 에
88 RES-OVER-LIMIT VALUE 4.를 추가한다. APPLYTRX.cob 의 입금 분기에서 금액이 1,000,000 보다 크면 SET RES-OVER-LIMIT TO TRUE 를 하고, 아니면 ADD 를 하도록 IF 로 감싼다. main.cob 의 EVALUATE 에 WHEN RES-OVER-LIMIT 을 넣어 메시지와 거절 건수를 처리한다. 이 분기를 넣지 않으면 새 코드는 WHEN OTHER 로 빠져 BAD TYPE 으로 표시된다. 결과 코드의 뜻을 카피북 한 곳에 두었으므로 숫자 4 를 직접 쓰는 곳은 없다. - 서브프로그램이 MOVE ZERO TO TR-AMOUNT 로 TR-AMOUNT 를 지우는데, 이제 원본을 지운다. 호출이 끝난 뒤 금액을 편집해 보여 주는 칸이 모든 줄에서 0 이 된다. 잔액 계산은 지우기 전에 끝나 있어서 달라지지 않는다. 읽기 전용으로 쓸 인자는 BY CONTENT 로 넘겨야 한다는 점을 보여 주는 사례다.
- 서브프로그램 예시는 다음과 같다.
호출은IDENTIFICATION DIVISION. PROGRAM-ID. CALCFEE. DATA DIVISION. LINKAGE SECTION. 01 LK-AMOUNT PIC 9(9). 01 LK-FEE PIC 9(9). PROCEDURE DIVISION USING LK-AMOUNT LK-FEE. FEE-PARA. COMPUTE LK-FEE = LK-AMOUNT * 0.01 GOBACK.CALL "CALCFEE" USING BY CONTENT TR-AMOUNT BY REFERENCE WS-FEE END-CALL로 한다. WS-FEE 는 main.cob 의 WORKING-STORAGE 에PIC 9(9)로 만들어 둔다. 금액은 BY CONTENT, 수수료는 돌려받아야 하므로 BY REFERENCE 다. 컴파일은cobc -x -Wall main.cob APPLYTRX.cob CALCFEE.cob이다. COMPUTE 는 정수 칸에 담을 때 소수 부분을 버리므로 수수료는 원 단위 내림이다. - COPY ACCTREC 을 쓰는 모든 소스, 곧 main.cob 과 APPLYTRX.cob 둘 다 다시 컴파일한다. 하나만 다시 컴파일하면 한쪽은 이름 칸이 9자, 다른 쪽은 20자인 정의로 같은 레코드를 해석하게 되어 뒤따르는 잔액 칸의 위치가 어긋난다. 이처럼 카피북은 컴파일할 때 소스에 박히므로, 고친 뒤에는 쓰는 곳 전부를 다시 컴파일하는 것이 규칙이다. 컴파일 명령 하나에 두 파일을 함께 적는 습관이 있으면 이 실수를 피할 수 있다.
READER FEEDBACK
질문·의견
내용에 관한 질문이나 더 나은 설명을 위한 의견을 남겨 주세요. 오탈자는 위의 제보 양식이 더 빨리 반영됩니다. 이 댓글은 원래 게시글과 같은 자리에 쌓입니다.
댓글 0
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.