CALL secara Mendalam

CALL dengan BY REFERENCE dan BY VALUE, CANCEL, serta aturan data bersama antarprogram.

Daftar isi

Pernyataan CALL memanggil program lain di dalam satu run unit dan mengirim data kepadanya melalui frasa USING, sehingga logika panjang dapat dipecah menjadi subprogram kecil. Topik ini membahas tiga bentuk pengiriman parameter (BY REFERENCE, BY CONTENT, dan BY VALUE), jalur nilai kembali melalui register RETURN-CODE, serta pernyataan CANCEL yang mengembalikan subprogram ke status awalnya. Ketiga demo disusun sebagai pasangan program utama dan subprogram yang dikompilasi bersama dengan satu perintah cobc.

Parameter melalui USING#

Subprogram menerima parameter melalui PROCEDURE DIVISION USING, dan setiap parameter dinyatakan lebih dahulu pada LINKAGE SECTION yang tidak memesan storage sendiri. Pengiriman default berupa BY REFERENCE, artinya pemanggil menyerahkan alamat storage aslinya, sehingga perubahan yang dilakukan subprogram langsung terlihat oleh pemanggil. Bentuk BY CONTENT menyalin isi parameter ke buffer milik subprogram, sehingga perubahan apa pun hanya menyentuh salinan tersebut dan tidak memengaruhi data pemanggil. Program utama berikut memanggil subprogram yang sama dua kali dengan kedua bentuk itu.

cobol utama.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. UTAMA.
      *--------------------------------------------------------------
      * Perbandingan BY REFERENCE dan BY CONTENT pada CALL.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 NILAI PIC 9(4) VALUE 100.
       PROCEDURE DIVISION.
       UTAMA.
           CALL "UBAH-NILAI" USING NILAI
           DISPLAY "BY REFERENCE : " NILAI
           MOVE 100 TO NILAI
           CALL "UBAH-NILAI" USING BY CONTENT NILAI
           DISPLAY "BY CONTENT   : " NILAI
           STOP RUN.

Subprogramnya hanya berisi satu parameter LINKAGE SECTION yang dinaikkan 100 sebelum kendali dikembalikan.

cobol ubah-nilai.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. UBAH-NILAI.
      *--------------------------------------------------------------
      * Subprogram: menambah parameter melalui LINKAGE SECTION.
      *--------------------------------------------------------------
       DATA DIVISION.
       LINKAGE SECTION.
       01 X PIC 9(4).
       PROCEDURE DIVISION USING X.
           ADD 100 TO X
           EXIT PROGRAM.
text Keluaran
BY REFERENCE : 0200
BY CONTENT   : 0100

Keluaran memperlihatkan perbedaan kedua bentuk melalui subprogram yang persis sama, yaitu menambah 100 ke parameternya. Pemanggilan pertama menyerahkan alamat NILAI, sehingga ADD 100 TO X menulis langsung ke storage pemanggil dan hasilnya 0200. Pemanggilan kedua menyalin isi NILAI ke buffer, sehingga penambahan yang sama hanya mengubah salinan dan NILAI tetap 0100.

Kompilasi kedua berkas dalam satu perintah berikut, lalu jalankan ./utama. Nama berkas eksekutabel mengikuti berkas pertama pada perintah cobc.

bash
# kompilasi program utama bersama subprogramnya
cobc -x utama.cbl ubah-nilai.cbl

BY VALUE dan RETURN-CODE#

Bentuk BY VALUE mengirim nilai dengan cara menyerupai pemanggilan fungsi C, yaitu argumen diubah ke wujud biner dan diteruskan sebagai nilai, bukan sebagai alamat field. Bentuk ini diperuntukkan bagi parameter numerik dan interop dengan bahasa C. Subprogram menyatakan parameternya dengan USING BY VALUE, dan GnuCOBOL 3.2 menandai penanganannya dengan peringatan -Wunfinished karena implementasinya masih dapat berubah. Untuk komunikasi antarprogram COBOL murni, BY REFERENCE dan BY CONTENT merupakan bentuk yang lebih mapan, sedangkan status kembalian subprogram dinyatakan lewat register khusus RETURN-CODE yang terbaca pemanggil segera setelah CALL berakhir.

cobol kode-akhir.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. KODE-AKHIR.
      *--------------------------------------------------------------
      * RETURN-CODE sebagai jalur kembalian subprogram.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 SUHU-PAGI  PIC 9(3) VALUE 12.
       01 SUHU-SIANG PIC 9(3) VALUE 30.
       01 HASIL      PIC 9(3).
       PROCEDURE DIVISION.
       UTAMA.
           CALL "JUMLAHKAN" USING SUHU-PAGI SUHU-SIANG
           MOVE RETURN-CODE TO HASIL
           DISPLAY "Jumlah : " HASIL
           STOP RUN.

Subprogramnya menjumlahkan dua parameter dan menyimpan hasilnya pada RETURN-CODE.

cobol jumlahkan.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. JUMLAHKAN.
      *--------------------------------------------------------------
      * Subprogram yang mengisi RETURN-CODE.
      *--------------------------------------------------------------
       DATA DIVISION.
       LINKAGE SECTION.
       01 ANGKA-1 PIC 9(3).
       01 ANGKA-2 PIC 9(3).
       PROCEDURE DIVISION USING ANGKA-1 ANGKA-2.
           COMPUTE RETURN-CODE = ANGKA-1 + ANGKA-2
           EXIT PROGRAM.
text Keluaran
Jumlah : 042

Subprogram menjumlahkan kedua parameternya ke RETURN-CODE, dan pemanggil memindahkannya ke field HASIL sebelum ditampilkan. Pemindahan diperlukan karena RETURN-CODE disimpan sebagai angka biner bertanda sembilan digit, sehingga menampilkan register ini langsung dengan DISPLAY menghasilkan bentuk seperti +000000042. Isi RETURN-CODE juga menjadi kode keluar proses ketika program selesai, sehingga ./kode-akhir berakhir dengan kode keluar 42 dan kode tersebut dapat diperiksa oleh skrip shell.

Tabel berikut merangkum ketiga bentuk pengiriman parameter.

Bentuk pengirimanYang diterima subprogramPerubahan yang terlihat pemanggil
BY REFERENCEAlamat storage asli parameterYa, menulis langsung ke storage pemanggil
BY CONTENTSalinan isi parameter selebar fieldTidak, salinan dibuang saat kembali
BY VALUENilai biner menyerupai argumen CTidak, diperuntukkan bagi parameter masukan

Kompilasi kedua berkas dalam satu perintah berikut, lalu jalankan ./kode-akhir.

bash
# kompilasi program utama bersama subprogram penjumlah
cobc -x kode-akhir.cbl jumlahkan.cbl

CANCEL dan status awal#

WORKING-STORAGE subprogram dipertahankan sepanjang run unit, sehingga nilai yang tertinggal pada pemanggilan sebelumnya masih terbaca pada pemanggilan berikutnya. Sifat ini berguna untuk penghitung dan penyangga, tetapi menyulitkan apabila status awal dibutuhkan kembali. CANCEL “NAMA” menjawab kebutuhan itu dengan membebaskan modul dari memori, sehingga CALL berikutnya memuat ulang modul dengan nilai sesuai VALUE deklarasinya. Program berikut memanggil subprogram penghitung tiga kali, membatalkannya, lalu memanggilnya sekali lagi.

cobol cek-penghitung.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. CEK-PENGHITUNG.
      *--------------------------------------------------------------
      * Status awal subprogram dan CANCEL.
      *--------------------------------------------------------------
       PROCEDURE DIVISION.
       UTAMA.
           CALL "PENGHITUNG"
           CALL "PENGHITUNG"
           CALL "PENGHITUNG"
           DISPLAY "Setelah CANCEL"
           CANCEL "PENGHITUNG"
           CALL "PENGHITUNG"
           STOP RUN.

Subprogramnya menyimpan satu penghitung pada WORKING-STORAGE-nya sendiri.

cobol penghitung.cbl
       IDENTIFICATION DIVISION.
       PROGRAM-ID. PENGHITUNG.
      *--------------------------------------------------------------
      * Subprogram dengan penghitung WORKING-STORAGE persisten.
      *--------------------------------------------------------------
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 JUMLAH-PANGGILAN PIC 9(2) VALUE 0.
       PROCEDURE DIVISION.
           ADD 1 TO JUMLAH-PANGGILAN
           DISPLAY "Subprogram dipanggil ke-" JUMLAH-PANGGILAN
           EXIT PROGRAM.
text Keluaran
Subprogram dipanggil ke-01
Subprogram dipanggil ke-02
Subprogram dipanggil ke-03
Setelah CANCEL
Subprogram dipanggil ke-01

Tiga pemanggilan pertama menaikkan penghitung yang sama dari 01 hingga 03 karena JUMLAH-PANGGILAN tersimpan di WORKING-STORAGE subprogram sepanjang run unit. Setelah CANCEL, pemanggilan keempat memuat ulang modul dan penghitung kembali ke VALUE 0, sehingga keluarannya kembali menunjukkan ke-01. Perlu dicatat bahwa data tidak pernah dibagi secara otomatis antarprogram yang dipanggil dengan CALL, karena setiap program memiliki WORKING-STORAGE sendiri. Item yang diberi kata IS GLOBAL hanya dibagi kepada program yang bersarang di dalam program induknya, bukan kepada modul luar.

Kompilasi kedua berkas dalam satu perintah berikut, lalu jalankan ./cek-penghitung.

bash
# kompilasi program utama bersama subprogram penghitung
cobc -x cek-penghitung.cbl penghitung.cbl

Kesalahan umum#

  • Jumlah, urutan, atau lebar parameter pada CALL USING tidak cocok dengan PROCEDURE DIVISION USING subprogram. Data terbaca bergeser atau program berakhir dengan error saat berjalan. Padankan kedua daftar parameter beserta lebarnya.
  • Mengharapkan perubahan pada parameter yang dikirim BY CONTENT. Subprogram hanya mengubah salinannya, sehingga parameter keluaran dikirim BY REFERENCE.
  • Literal CALL tidak persis sama dengan PROGRAM-ID subprogram. Pencarian modul saat program berjalan membedakan huruf besar dan huruf kecil, dan modul yang tidak ditemukan menghentikan program dengan pesan semacam module '...' not found. Tulis literal sama persis dengan PROGRAM-ID.
  • Menganggap WORKING-STORAGE subprogram selalu segar. Nilainya dipertahankan antarpanggilan, sehingga kosongkan field yang sensitif di dalam subprogram atau jalankan CANCEL bila status awal dibutuhkan.

Ringkasan#

  • CALL USING mengirim parameter dengan BY REFERENCE secara default sehingga subprogram menulis langsung ke storage pemanggil, sedangkan BY CONTENT menyalin isi parameter sehingga perubahan subprogram tidak sampai ke pemanggil.
  • BY VALUE meneruskan argumen sebagai nilai biner menyerupai pemanggilan C dan diperuntukkan bagi parameter numerik serta interop, dengan catatan penanganannya masih ditandai peringatan -Wunfinished oleh GnuCOBOL 3.2.
  • RETURN-CODE menyimpan status kembalian subprogram, terbaca pemanggil segera setelah CALL, dan menjadi kode keluar proses ketika program selesai.
  • WORKING-STORAGE subprogram bertahan sepanjang run unit, dan CANCEL memuat ulang modul sehingga nilainya kembali sesuai VALUE awalnya.

Referensi#