1
0

More than 1 year has passed since last update.

COBOL 処理パターン C言語で作成した外部サブプログラムを呼ぶ

Last updated at Posted at 2021-10-22

「COBOL 処理パターン 外部サブプログラム呼ぶ」 のサブプログラムをC言語で作成してみる。

入出力構成図

[cob06_01.png]

ソースコード

メインプログラム

顧客マスタテーブルの有効件数を数値項目(COMP-X)として定義する。これを引数にして Cプログラムに渡すと、数値項目の桁数によりC側での整数の大きさ(1バイト、2バイト、4バイト、8バイト)が自動的に決まる。

 IDENTIFICATION              DIVISION.
 PROGRAM-ID.                 MAIN01.

 ENVIRONMENT                 DIVISION.
 INPUT-OUTPUT                SECTION.
 FILE-CONTROL.
*入力ファイル 行順編成ファイル(テキストファイル)  
 SELECT  F1  ASSIGN  TO  "./R002.txt"
 ORGANIZATION IS LINE SEQUENTIAL
 ACCESS  MODE  IS  SEQUENTIAL.  
*出力ファイル 行順編成ファイル(テキストファイル)  
 SELECT  F2  ASSIGN  TO  "./R003.txt"
 ORGANIZATION IS LINE SEQUENTIAL
 ACCESS  MODE  IS  SEQUENTIAL.  

 DATA                        DIVISION.
 FILE                        SECTION.
* 入力ファイル
 FD  F1.
 01  F1R.
     05  CUST-CODE           PIC 9(04). 
     05  SALES               PIC 9(10).
* 出力ファイル
 FD  F2.
 01  F2R.
     05  CUST-CODE           PIC 9(04). 
     05  SALES               PIC 9(10).
     05  CUST-NAME           PIC X(20).

 WORKING-STORAGE             SECTION.
 01  END-FLG                 PIC 9(01).
 01  I                       PIC 9(02).
 01  RETURN-VALUE            PIC 9(03).
* 顧客マスターテーブル有効件数(8バイト)
 01 CUST-COUNT               PIC 9(18) COMP-X VALUE 0. 
* 顧客マスターテーブル
 01 CUST-TABLE.
     05 CUSTOMER OCCURS 10 TIMES.
         10 CUST-CODE        PIC 9(04).
         10 CUST-NAME        PIC X(20).

 PROCEDURE                   DIVISION.
******************************************************************
* 主処理 
****************************************************************** 
 PERFORM INIT-RTN
 PERFORM LOOP-RTN UNTIL END-FLG NOT = 0
 PERFORM END-RTN
 STOP RUN.
******************************************************************
* 前処理 
******************************************************************
 INIT-RTN.
*    変数の初期化
     INITIALIZE END-FLG
*    ファイルオープン
     OPEN INPUT F1
     OPEN OUTPUT F2
*    サブルーチンCALL
     CALL "read_table" USING BY REFERENCE CUST-COUNT
                             BY REFERENCE CUST-TABLE
                       GIVING RETURN-VALUE

     DISPLAY CUST-COUNT;

     PERFORM VARYING I FROM 1 BY 1 UNTIL I > CUST-COUNT
         DISPLAY CUST-CODE OF CUSTOMER(I) " "
                 CUST-NAME OF CUSTOMER(I)
     END-PERFORM
*    1件目のレコードの入力
     PERFORM READ-RTN.
 INIT-RTN-EX. 
     EXIT.
******************************************************************
* 繰り返し処理 
******************************************************************
 LOOP-RTN.
*    出力レコードの編集 
     INITIALIZE F2R
     MOVE CUST-CODE OF F1R TO CUST-CODE OF F2R 
     MOVE SALES OF F1R TO SALES OF F2R 
     MOVE SALES OF F1R TO SALES OF F2R 
*    顧客マスターの検索 
     PERFORM VARYING I FROM 1 BY 1 UNTIL I > CUST-COUNT
         IF CUST-CODE OF F1R = CUST-CODE OF CUSTOMER(I)
             MOVE CUST-NAME OF CUSTOMER(I) TO CUST-NAME OF F2R     
             MOVE 99 TO I
         END-IF
     END-PERFORM           
*    レコードの出力     
     WRITE F2R
*    次のレコードの読み込み 
     PERFORM READ-RTN.
 LOOP-RTN-EX. 
     EXIT.
******************************************************************
* 後処理 
******************************************************************
 END-RTN.
     CLOSE  F1 F2.
 END-RTN-EX.
     EXIT.
******************************************************************
* 入力処理  
******************************************************************
 READ-RTN.
     READ  F1 
         AT END
             ADD 1 TO END-FLG
     END-READ.
 READ-RTN-EX.
     EXIT.

サブプログラム

エンディアンの変換が必要
COBOL側はBig Endianだが、C言語側はLittle Endianになっている。引数の数値項目を整数値(COMP-X)とした場合、受け渡しのつどエンディアンの変換を行う必要がある。

エンディアンの変更は、単純なバイトスワップで良い。GNU Cライブラリに byteswap.hにマクロが定義されているのだが、OSXのライブラリにはなぜかないので、自身でマクロを実装している。

//------------------------------------------------------------------------------
//  sublib.c
//------------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#define BUFFER_LEN 64
#define CODE_LEN 4
#define NAME_LEN 20

//バイトスワップ(As Mac OS X does not have byteswap.h)
//2バイト
#define bswap_16(value) \
((((value) & 0xff) << 8) | ((value) >> 8))
//4バイト
#define bswap_32(value) \
(((uint32_t)bswap_16((uint16_t)((value) & 0xffff)) << 16) | \
(uint32_t)bswap_16((uint16_t)((value) >> 16)))
//8バイト
#define bswap_64(value) \
(((uint64_t)bswap_32((uint32_t)((value) & 0xffffffff)) << 32) | \
(uint64_t)bswap_32((uint32_t)((value) >> 32)))

//顧客マスター構造体
struct _customer{
    char code[CODE_LEN];
    char name[NAME_LEN];
};
typedef struct _customer customer_t;

//COBOLインタフェース関数
int read_table(uint64_t *cust_count, char *cust_table){
/* endianの判定
    int x=1; // 0x00000001
    if (*(char*)&x) {
        printf("little endian\n");
        // little endian. memory image 01 00 00 00 
    }else{
        printf("big endian\n");
        // big endian. memory image 00 00 00 01 
    }
*/
    //顧客マスターテーブル
    customer_t custTable[10];
    //ゼロクリア
    for(int i=0; i<10; i++){
        custTable[i] = (customer_t){0};
    }
    //顧客マスターファイルの読み込み
    const char *file = "./M001.txt";
    FILE *fp;
    fp = fopen(file, "r");
    char line[BUFFER_LEN];
    unsigned short count = 0;
    while(fgets(line, BUFFER_LEN, fp) != NULL){
        //改行コードの削除
        char *p = strchr(line, '\n');
        if (p != NULL){
            *p = '\0';
        }
        //顧客コード
        strncpy(custTable[count].code, line, CODE_LEN);        
        //顧客名
        int nlength = strlen(line)-CODE_LEN;
        strncpy(custTable[count].name, line+CODE_LEN, nlength);

        for (int i = nlength; i < NAME_LEN; i++){
            custTable[count].name[i] = '\0';
        }
        count++;
    }
    *cust_count = count; //顧客マスターテーブル有効件数(8バイト)
    *cust_count = bswap_64(*cust_count); //little endian -> big endian
    printf("%d\n", count);

    memcpy(cust_table, (char*)custTable, sizeof custTable);
    return 0;
}

関連記事
COBOL 処理パターン 多段階集計
COBOL 処理パターン マッチング
COBOL 処理パターン テーブル展開
COBOL 処理パターン 外部サブプログラム呼ぶ

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0