FLMREC-API
FLAM Record Interface Version: 5.2.1-42969
FLAM5 Archive Record Interface for COBOL and PL/1

This interface provides COBOL and PL/1 programs with sequential read and write access to FLAM5 archives via load module (CALL) conventions. It is analogous to the FLUC record interface (FLCRECLB.h) but targets FLAM5 archives instead of general-purpose file I/O.

Differences from FLCRECLB

  • Error trace buffer (pcErr): every stub accepts an optional error-trace buffer of FLMERR_SIZ (32768) bytes as its first or second parameter (see Error handling). FLCRECLB stubs do not provide an equivalent trace buffer.
  • Subject is FLAM5 archives: the archive string syntax controls access mode (read / write), location, compression and encryption. Member navigation (FMRNXM), multi-member write (FMRNWM) and table support (FMRSTN / FMRGTN) are available.

Call convention

All parameters are passed by reference (COBOL/PL1 call-by-reference). Scalar integer parameters (boolean flags, lengths, format selectors) are passed as pointer-to-int. String parameters are passed as a (length: int*, data: char*) pair; passing a negative length (-1) causes the stub to treat the data pointer as a null-terminated C string. Handle parameters are passed as pointer-to-pointer (POINTER USAGE).

All stubs carry int* piRtc as their first parameter, return void, and require piRtc to be non-NULL. COBOL and PL/1 callers use CALL syntax and read the return code exclusively from piRtc.

Error handling

Every stub accepts char* pcErr as its first or second parameter. On all stubs pcErr is the second parameter (where present), preceded by int* piRtc (see Call convention). If pcErr is non-NULL it must point to a buffer of at least FLMERR_SIZ (32768) bytes. On error the stub writes a detailed, human-readable trace to this buffer. Pass NULL to suppress the trace; the integer return code is always set.

Use FMRMSG to map a return code to a short English message.

Archive string

The archive string describes the archive location and access mode using the same CLP syntax as the FLCL command line. The first keyword determines the mode:

  • from(...) or read(...) – open for sequential read
  • to.new(...), to.old(...), to.mod(...) or write(...) – open for write

Use FMRHLP and FMRSYN with FMR_DECO_ARC (FMR_READ_ARC) or FMR_COMP_ARC (FMR_WRITE_ARC) for interactive help and syntax information.

Recommended API lifecycle

The standard call sequence for a single archive operation:

1. FMROPN  -- open global session (optional but recommended)
2. FMROPA  -- open archive for read or write
3. FMRSMS  -- set member state (write mode, optional)
   FMRGET / loop -- read records (read mode)
   FMRPUT / loop -- write records (write mode)
4. FMRCLA  -- close archive (commit or rollback)
5. FMRCLS  -- close global session

Calling FMROPN is optional: if ppGbl is NULL in FMROPA, FLAM creates a private session automatically. However, an explicit FMROPN call is recommended because:

  • On z/OS, piSys=1 and piStd=1 load system variables and the DD:STDENV stream before the first archive operation, ensuring correct code page and locale settings.
  • A shared session passed to multiple FMROPA calls avoids repeated environment loading.
  • Errors from FMROPN can be caught explicitly.

In COBOL, pass piSys and piStd as BY REFERENCE integer variables with value 1. Pass a 1-byte dummy PIC X variable (BY REFERENCE, the default) together with a zero-length integer for the optional pcEnv and pcLog parameters. IBM z/OS COBOL does not permit BY VALUE NULL in CALL statements.

COBOL example: read all records from an archive

IDENTIFICATION DIVISION.
PROGRAM-ID. FMRREAD.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-FMR-ERR PIC X(32768).
01 WS-FMR-GBL USAGE IS POINTER VALUE NULL.
01 WS-FMR-HDL USAGE IS POINTER VALUE NULL.
01 WS-FMR-RTC PIC S9(9) COMP.
01 WS-FMR-ONE PIC S9(9) COMP VALUE 1.
01 WS-FMR-ZERO PIC S9(9) COMP VALUE 0.
01 WS-FMR-DUM PIC X VALUE SPACE.
01 WS-ARC PIC X(256)
VALUE "from(file='backup.flam')".
01 WS-ARC-LEN PIC S9(9) COMP VALUE 256.
01 WS-REC PIC X(32768).
01 WS-REC-LEN PIC S9(9) COMP VALUE 32768.
01 WS-SKIP PIC S9(9) COMP VALUE 0.
01 WS-CNV USAGE IS POINTER VALUE NULL.
PROCEDURE DIVISION.
CALL 'FMROPN' USING WS-FMR-RTC, WS-FMR-ERR, WS-FMR-GBL,
WS-FMR-ONE, WS-FMR-ONE,
WS-FMR-ZERO, WS-FMR-DUM,
WS-FMR-ZERO, WS-FMR-DUM
CALL 'FMROPA' USING WS-FMR-RTC, WS-FMR-ERR, WS-FMR-GBL,
WS-FMR-HDL, WS-ARC-LEN, WS-ARC,
BY VALUE 0, BY VALUE NULL,
BY VALUE 0
PERFORM UNTIL WS-FMR-RTC NOT EQUAL 0
CALL 'FMRGET' USING WS-FMR-RTC, WS-FMR-ERR, WS-FMR-HDL,
WS-REC-LEN, WS-REC,
WS-SKIP, WS-CNV
IF WS-FMR-RTC EQUAL 0
PERFORM PROCESS-RECORD
END-IF
END-PERFORM
CALL 'FMRCLA' USING WS-FMR-RTC, WS-FMR-ERR, WS-FMR-HDL,
BY VALUE 1,
BY VALUE 0, BY VALUE 0, BY VALUE NULL
CALL 'FMRCLS' USING WS-FMR-RTC, WS-FMR-GBL
STOP RUN.
void FMRCLA(int *piRtc, char *pcErr, void **ppHdl, const int *piSuccess, const int *piStaFmt, int *piStaLen, char *pcStaBuf)
Closes a FLAM5 archive and releases all resources.
void FMROPA(int *piRtc, char *pcErr, void **ppGbl, void **ppHdl, const int *piArcLen, const char *pcArchive, const int *piFmtLen, const char *pcFormat, const int *piNumber)
Opens a FLAM5 archive for read or write access.
void FMRGET(int *piRtc, char *pcErr, void **ppHdl, int *piLen, unsigned char *pcRec, const int *piSkip, void **ppCnv)
Reads the next record into a caller-supplied buffer (read mode).
void FMROPN(int *piRtc, char *pcErr, void **ppGbl, const int *piSys, const int *piStd, const int *piEnvLen, const char *pcEnv, const int *piLogLen, const char *pcLog)
Opens a global session with optional in-memory logging.
void FMRCLS(int *piRtc, void **ppGbl)
Closes a global session.

COBOL example: write multiple members to an archive

* Open global session (piSys/piStd via BY REFERENCE variables)
CALL 'FMROPN' USING WS-FMR-RTC, WS-FMR-ERR, WS-FMR-GBL,
WS-FMR-ONE, WS-FMR-ONE,
WS-FMR-ZERO, WS-FMR-DUM,
WS-FMR-ZERO, WS-FMR-DUM
* Open archive for write
MOVE "to.new(file='out.flam' comp.lzip())" TO WS-ARC
CALL 'FMROPA' USING WS-FMR-RTC, WS-FMR-ERR, WS-FMR-GBL,
WS-FMR-HDL, WS-ARC-LEN, WS-ARC,
BY VALUE 0, BY VALUE NULL,
BY VALUE 0
* Set member name for first member
MOVE 'file1.txt' TO WS-MBRNAME
MOVE 9 TO WS-MBRNAME-LEN
CALL 'FMRSMN' USING WS-FMR-RTC, WS-FMR-ERR, WS-FMR-HDL,
WS-MBRNAME-LEN, WS-MBRNAME
* Write records for first member ...
* Start new member (finalizes previous one)
CALL 'FMRNWM' USING WS-FMR-RTC, WS-FMR-ERR, WS-FMR-HDL,
BY VALUE 0, BY VALUE NULL,
BY VALUE 0, BY VALUE 0, BY VALUE NULL
* Write records for second member ...
* Close archive, then global session
CALL 'FMRCLA' USING WS-FMR-RTC, WS-FMR-ERR, WS-FMR-HDL,
BY VALUE 1,
BY VALUE 0, BY VALUE 0, BY VALUE NULL
CALL 'FMRCLS' USING WS-FMR-RTC, WS-FMR-GBL

PL/1 example: read all records from an archive (DLL variant)

DCL FMROPN ENTRY(FIXED BIN(31) BYADDR,
CHAR(32767) BYADDR,
POINTER BYADDR,
FIXED BIN(31) BYADDR,
FIXED BIN(31) BYADDR,
FIXED BIN(31) BYADDR,
CHAR(1) BYADDR,
FIXED BIN(31) BYADDR,
CHAR(1) BYADDR)
EXTERNAL;
DCL FMROPA ENTRY(FIXED BIN(31) BYADDR,
CHAR(32767) BYADDR,
POINTER BYADDR,
POINTER BYADDR,
FIXED BIN(31) BYADDR,
CHAR(*) BYADDR,
FIXED BIN(31) BYADDR,
CHAR(1) BYADDR,
FIXED BIN(31) BYADDR)
EXTERNAL;
DCL FMRGET ENTRY(FIXED BIN(31) BYADDR,
CHAR(32767) BYADDR,
POINTER BYADDR,
FIXED BIN(31) BYADDR,
CHAR(*) BYADDR,
FIXED BIN(31) BYADDR,
POINTER BYADDR)
EXTERNAL;
DCL FMRCLA ENTRY(FIXED BIN(31) BYADDR,
CHAR(32767) BYADDR,
POINTER BYADDR,
FIXED BIN(31) BYADDR,
FIXED BIN(31) BYADDR,
FIXED BIN(31) BYADDR,
CHAR(1) BYADDR)
EXTERNAL;
DCL FMRCLS ENTRY(FIXED BIN(31) BYADDR,
POINTER BYADDR)
EXTERNAL;
DCL WS_ERR CHAR(32768);
DCL WS_GBL POINTER INIT(SYSNULL());
DCL WS_HDL POINTER INIT(SYSNULL());
DCL WS_ARC CHAR(256) INIT("from(file='backup.flam')");
DCL WS_REC CHAR(32768);
DCL WS_REC_LEN FIXED BIN(31) INIT(32768);
DCL WS_SKIP FIXED BIN(31) INIT(0);
DCL WS_CNV POINTER INIT(SYSNULL());
DCL WS_RTC FIXED BIN(31);
DCL WS_ARC_LEN FIXED BIN(31) INIT(LENGTH(TRIM(WS_ARC)));
DCL NEG_ONE FIXED BIN(31) INIT(-1);
DCL ZERO FIXED BIN(31) INIT(0);
DCL ONE FIXED BIN(31) INIT(1);
DCL DUMMY_STR CHAR(1) INIT(' ');
/- open global session (piSys=1: system vars, piStd=1: STDENV) -/
CALL FMROPN(WS_RTC, WS_ERR, WS_GBL,
ONE, ONE, ZERO, DUMMY_STR, ZERO, DUMMY_STR);
CALL FMROPA(WS_RTC, WS_ERR, WS_GBL, WS_HDL,
WS_ARC_LEN, WS_ARC, NEG_ONE, DUMMY_STR,
ZERO);
DO WHILE (WS_RTC = 0);
CALL FMRGET(WS_RTC, WS_ERR, WS_HDL,
WS_REC_LEN, WS_REC, WS_SKIP, WS_CNV);
IF WS_RTC = 0 THEN CALL PROCESS_RECORD;
END;
CALL FMRCLA(WS_RTC, WS_ERR, WS_HDL, ONE, ZERO, ZERO,
DUMMY_STR);
CALL FMRCLS(WS_RTC, WS_GBL);

COBOL copybook declarations

01 WS-FMR-ERR PIC X(32768). *> Error trace buffer
01 WS-FMR-GBL USAGE IS POINTER VALUE NULL. *> Global session handle
01 WS-FMR-HDL USAGE IS POINTER VALUE NULL. *> Archive handle
01 WS-FMR-RTC PIC S9(9) COMP. *> Return code

Environment variables

FLAM loads its environment during FMROPN (or automatically during the first FMROPA call when no global session handle is supplied). The LANG environment variable controls the default character set for text conversions. On z/OS, the DD:STDENV stream or a STDENV file can be loaded via the piSys / piStd parameters of FMROPN. Additional variable assignments may be passed via pcEnv without modifying the process environment.

Thread safety

All FLMRECLB stubs are thread-safe on all supported platforms except USS on zSeries. On classical mainframe operating systems (z/OS) the stubs are reentrant and can be used concurrently from multiple tasks. Each archive handle may only be used from one thread at a time; use separate handles per thread for parallel processing.

Hints for z/OS (COBOL and PL/1)

FLAM ships two link-table variants built from the same C source:

FLMRECLB (DLL)
Uses C99 DLL linkage. The calling program must be compiled and linked with options that enable DLL calls:
  COBOL: COBOL ... LONGMIXED DLL
  PL/1:  PLI   ... OPTIONS(DLL)
  
Link-edit with the FLMRECLB DLL side-deck (hlq.FLAM.SIDEDK). All stubs carry piRtc as their first parameter and are called with CALL syntax. PL/1 programs must not use RETURNS(FIXED BIN(31)) for these entries.
FLMRECLM (individual load modules)
Each external entry (FMROPA, FMRSMS, ...) is an independent z/OS load module in hlq.FLAM.LOAD. No side-deck is needed. COBOL programs call these with CALL 'FMRxxx' USING ... (no DLL compile option required). PL/1 programs declare each entry with OPTIONS(ASM FETCHABLE) and use CALL syntax; IBM Enterprise PL/I 5.3 forbids OPTIONS(ASM) combined with RETURNS on load module entries (IBM1690I), so the return code is carried in the first piRtc parameter instead.

We recommend establishing application-default runtime options with the CEEUOPT assembler language source program. The recommended runtime options are available as members CEEUOPTx (x=3 for 31-bit, x=6 for 64-bit) in the hlq.FLAM.SRCLIB partitioned data set.

Sample programs: write a dataset to a FLAM5 archive

The following ready-to-run samples in hlq.FLAM.SRCLIB demonstrate how to use this interface to compress a sequential dataset into a FLAM5 archive member. Both programs share the same design:

  • The input dataset is opened via the FLUC record interface (FCROPN from FLCRECLB) using the compact file string read.file='DD:INPUT' and format FORMAT.RECORD(). FLUC fills the state buffer with the actual DCB attributes (ORGF, RECF, RECL) of DD:INPUT.
  • The state string returned by FCROPN is passed directly to FMRSMS – no manual STATE(...) construction is needed, and the program handles any record format automatically.
  • The archive file path is supplied as the JCL PARM field (USS pathname). If the archive does not yet exist it is created with to.new(); if it already exists the member is added or overwritten with to.mod(flam(mbrmode=overwrite)).
  • Records are transferred in a FCRGET / FMRPUT loop.
  • The fully qualified DSN of DD:INPUT is retrieved via FCRGFN and printed in the protocol log.
SOFMRPUT
COBOL sample (Enterprise COBOL for z/OS). Compiled with DYNAM,RENT,APOST. All CALL statements resolve to individual load modules (FLMRECLM / FLCRECLM) at runtime; no DLL side-deck is needed.
SPFMRPUT
PL/1 sample (Enterprise PL/1 for z/OS), functionally equivalent to SOFMRPUT. Compiled with GOFF,RENT,DLL,LIMITS(EXTNAME(8)). All FLMRECLM and FLCRECLM entries are declared with OPTIONS(ASM FETCHABLE) and called with CALL syntax; no DLL side-deck is needed for those entries.
SCFMRPUT
C sample (CSRC/SAMPLE/SCFMRPUT.c), functionally equivalent to SOFMRPUT and SPFMRPUT but uses the native FLMREC.h C API directly (not the FLMRECLB stubs) with FLCBYT.h for input file access. Accepts the input file path as argv[1] and the archive path as argv[2]. Linked with the FLCBYT and FLMREC side-decks.