Devin.KR

서브프로그램과 카피북 - 나누어 재사용하기

개발자KR 조회 0

이 장에서 배우는 것

앞 장까지는 프로그램 하나가 파일을 읽고, 계산하고, 보고서까지 모두 맡았다. 프로그램이 커지면 한 파일에 수백 줄이 쌓이고, 같은 레코드 정의를 여러 프로그램에 복사해 붙이게 된다. 이 장에서는 일을 나누는 두 가지 방법을 배운다. 하나는 다른 프로그램을 불러 쓰는 서브프로그램(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 는 처음 호출될 때 한 번 초기화되고, 이후 호출 사이에는 값이 남아 있다. 호출할 때마다 새로 시작하는 변수가 아니다.

MAIN 은 거래 레코드를 사본으로 넘기고 계좌 레코드와 결과 코드는 원본 그대로 공유한다.

BY REFERENCE 와 BY CONTENT

인자를 넘기는 방식은 두 가지다. BY REFERENCE 는 데이터가 있는 자리를 알려 준다. 서브프로그램이 그 값을 고치면 호출자의 변수도 바뀐다. 아무것도 쓰지 않으면 이 방식이 기본이다. BY CONTENT 는 값을 임시 사본으로 만들어 그 사본의 자리를 넘긴다. 서브프로그램이 사본을 고쳐도 호출자의 원래 값은 그대로다.

두 가지 인자 전달 방식의 차이
구분BY REFERENCEBY 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-RECMAIN 의 FD, APPLYTRX 의 LINKAGE
ACCTREC.cpy계좌 레코드 ACCT-RECMAIN 의 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 을 쓰지 않는다.

카피북 하나를 두 프로그램이 COPY 하므로 한 곳만 고치면 두 곳의 정의가 같이 바뀐다.

여러 파일 컴파일

소스가 둘 이상이면 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 REFERENCECALL 의 USING 안원본을 공유한다. 생략하면 이 방식이다
BY CONTENTCALL 의 USING 안사본을 넘긴다
LINKAGE SECTION서브프로그램의 DATA DIVISION넘겨받는 데이터에 이름을 붙인다. VALUE 는 쓰지 않는다
PROCEDURE DIVISION USING서브프로그램받을 이름을 호출자 순서대로 나열한다
GOBACK서브프로그램의 끝호출자로 돌아간다
COPY 이름.어느 DIVISION 이든컴파일할 때 카피북을 끼워 넣는다
cobc -x main.cob 서브.cob명령줄여러 소스를 한 실행 파일로 묶는다

연습 문제

  1. 입금 한도 규칙을 추가한다. 입금 금액이 1,000,000 을 넘으면 새 결과 코드 4(RES-OVER-LIMIT)로 거절한다. 어떤 파일을 고쳐야 하고 각각 무엇을 추가하는지 쓴다.
  2. main.cob 의 CALL 에서 거래 레코드 앞의 BY CONTENT 를 BY REFERENCE 로 바꾸면 실행 결과의 어느 부분이 달라지는지 설명한다.
  3. 출금 금액의 1% 를 수수료로 계산해 돌려주는 서브프로그램 CALCFEE 를 만든다. 금액은 읽기만 하고 수수료는 돌려받는다. 호출하는 CALL 문과 컴파일 명령도 쓴다.
  4. ACCTREC.cpy 의 ACCT-NAME 을 PIC X(9) 에서 PIC X(20) 으로 늘렸다. 다시 컴파일해야 하는 소스는 무엇인가.

정답과 해설

  1. 세 파일을 고친다. 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 를 직접 쓰는 곳은 없다.
  2. 서브프로그램이 MOVE ZERO TO TR-AMOUNT 로 TR-AMOUNT 를 지우는데, 이제 원본을 지운다. 호출이 끝난 뒤 금액을 편집해 보여 주는 칸이 모든 줄에서 0 이 된다. 잔액 계산은 지우기 전에 끝나 있어서 달라지지 않는다. 읽기 전용으로 쓸 인자는 BY CONTENT 로 넘겨야 한다는 점을 보여 주는 사례다.
  3. 서브프로그램 예시는 다음과 같다.
           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 는 정수 칸에 담을 때 소수 부분을 버리므로 수수료는 원 단위 내림이다.
  4. COPY ACCTREC 을 쓰는 모든 소스, 곧 main.cob 과 APPLYTRX.cob 둘 다 다시 컴파일한다. 하나만 다시 컴파일하면 한쪽은 이름 칸이 9자, 다른 쪽은 20자인 정의로 같은 레코드를 해석하게 되어 뒤따르는 잔액 칸의 위치가 어긋난다. 이처럼 카피북은 컴파일할 때 소스에 박히므로, 고친 뒤에는 쓰는 곳 전부를 다시 컴파일하는 것이 규칙이다. 컴파일 명령 하나에 두 파일을 함께 적는 습관이 있으면 이 실수를 피할 수 있다.

댓글 0

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

댓글을 남기려면 로그인이 필요합니다.