/**
 * @file FL4REC.h
 * @brief Specification of FLAM4 Record Interface
 * @author limes datentechnik gmbh
 * @date   13.11.2019
 * @copyright limes datentechnik (R) gmbh
 *
 * @mainpage FLAM4 Record Interface
 *
 * This interface provides a platform independent record-oriented read
 * and write access to <b>FLAM4</b> files. It contains all functions of the
 * Windows, UNIX and HOST record interfaces to provide backward compatibility,
 * required for sequential access. On Mainframes additional load
 * modules are available for positioning, insert and update of records.
 *
 * @section ITFSTD Interface standards
 * Each function is also available as a separate load module. On open
 * platforms the function names are in lower case with '_' as prefix and
 * 1 as postfix (_flmxxx1), on mainframes in upper case (FLMXXX). The
 * libfl4recuc.dll/so provides the functions in upper case on Windows
 * and Unix systems. This documentation use 'flmxxx' in lower case for
 * each entry.
 *
 * There are 4 types of parameters:
 *
 * <pre>
 * POINTER:   Pointer to an address (usually 32 (PIC S9(9) COMP) or 64 bit)
 * INTEGER:   Pointer to a 32 bit number in two's complement (PIC S9(9) COMP)
 * INTARY2:   Pointer to an array of 2 INTEGERs (2*32 bit)
 * STRING[x]: Pointer to a byte (8 bit) array of length x (PIC X(x))
 * STRING:    Pointer to a variable length byte (8 bit) array (PIC X(n))
 * </pre>
 *
 * The type INTEGER has local endianness. On mainframes, this is usually
 * big endian. This means that the most significant byte is stored first
 * (i.e. at the lowest memory address) and the least significant byte is
 * stored last. On x86 platforms, the byte order is little endian. This
 * means that the byte order is reversed.
 *
 * @section DETAILS Detailed description
 * The interface provides functions similar to the record-oriented file I/O
 * functions used with COBOL, PL/I or assembler on mainframes. Only the file
 * open function differs in that it gives 3 different open function and a
 * few setter (or FLMSET()) which must be called in the right sequence, to
 * open a FLAMFILE of version 4. To simplify the use of FKME (FLAM key
 * management extensions) we have add the callable service FLMKME, which
 * works like FLMPWD.
 *
 * FL4REC consists of a number of subroutines that can be called by any
 * programming language such as COBOL, PL/I, C, FORTRAN, etc., as well as
 * by ASSEMBLER programs. Except for the key descriptions all parameters
 * are implemented as elementary data types (INTEGER, STRING). Deliberately
 * no control blocks are required to avoid alignment problems and additional
 * copying of parameter values before and after a function call. Key
 * descriptions are organized as a structured data type in order to shorten
 * the parameter list.
 *
 * Application programs written in C must include the header
 * <code>FL4REC.h</code>. This C header file contains the definitions of
 * the symbolic constants, as well as the structure of the key description.
 * These definitions must be ported to other programming languages accordingly
 * if C is not used.
 *
 * @section ARGS Function arguments
 * All argument lists begin with an ID, which identifies the compression
 * file uniquely. This flmid argument contains the address of the work
 * area for the compressed file, which was specified by #flmopn(), and must
 * not be modified until #flmcls(). All other arguments are only relevant
 * to the function to which they are transferred.
 *
 * The identification is followed by a return code that informs the caller
 * about successful execution or occurring errors. Processing of a
 * compressed file always starts with function FLMOPN that assigns the
 * program to the compressed file and defines the operation mode. A file
 * opened successfully must always be closed with function FLMCLS. There
 * are no messages generated at the record level interface. During transfer
 * of original data the parameter RECORD always contains the true data
 * without any length fields or record delimiters. Or the parameter RECPTR
 * points to a field with such a content. The parameter RECLEN always
 * contains the length of the true data (exclusive length).
 *
 * COBOL programs can be translated using the <b>DYNAM</b> option. As a result,
 * the FLAM modules are loaded from the library only at the moment of
 * execution. If a dynamic call is not wanted (<b>NO-DYNAM</b> option in COBOL
 * or V constants in ASSEMBLER), the FLAM module FL4REC should be
 * specified explicitly when linking.

 * @section MFEDZ Micro Focus EDZ support
 * The API is supported also in MF-EDZ environments. See install.txt on
 * Windows or Unix for more information.
 *
 * <b>Functions passing pointer adresses, for example #flmloc(), only work if the COBOL
 * compiler directiv AMODE is NOT used. With AMODE mainframe pointers are used in the
 * COBOL program which cannot be converted.</b>
 *
 * For use with Micro Focus Enterprise Server the following environment
 * variables might be used.
 *
 * <dl>
 * <dt>FLAM4MF=unset:</dt><dd>
 *      The filename needs to be specified as either <code>DD:name</code> or <code>//'name'</code> if the Micro Focus support
 *      is needed. Otherwise normal <b>FLAM4</b> use is done.<br>
 *      If <code>DD:name</code> or <code>//'name'</code> cannot be accessed an error is returned.</dd>
 * <dt>FLAM4MF=encoding:</dt><dd>
 *      Micro Focus libraries will be used and an error is returned if they are not found.<br>
 *      The encoding is used to automatically convert all input character strings from this to the local system encoding.
 *      The output character strings are converted from the local system to this encoding.<br>
 *      The command <code>flcl info get.enc</code> prints a list of all supported encodings.<br>
 *      For convenience the strings <code>:EBCDIC</code> or <code>:ASCII</code> might be used.</dd>
 *      If the encoding strings begins with 'IBM' big endian is assumed and binary values will be byte swapped.
 * <dt>FLAM4MF=YES:</dt><dd>
 *      Micro Focus libraries will be used and an error is returned if they are not found.<br>
 *      No character conversion is done.</dd>
 * <dt>FLAM4MF=NO:</dt><dd>
 *      Micro Focus support is switched off, standard <b>FLAM4</b> use.<br>
 *      This must be done in order to work with filenames starting with <code>DD:</code></dd>
 * </dl>
 * For tracing:
 * <dl>
 * <dt>FLAM4MF_TRACEFILE=unset</dt><dd>
 *      Without trace file name tracing of library calls is omitted.</dd>
 * <dt>FLAM4MF_TRACEFILE=filename</dt><dd>
 *      trace output of library function calls is written to <code>filename</code></dd>
 * </dl>
 * For system symbols:
 * <dl>
 * <dt>FLAM4MF_STATIC_SYSVAR=filename</dt><dd>
 *      to define static system variables as environment variables.</dd>
 * <dt>FLAM4MF_STATIC_SYSVAR=filename</dt><dd>
 *      to use the JCL user exit to define dynamic system symbols</dd>
 * </dl>
 * For dynamic system variables the DD:SYSVAR is also supported.
 *
 * To use the function in COBOL the libfl4recuc.dll/so must be copied in
 * the working directory of the EDZ server under FLMOPN.dll/so and
 * FLMERR.dll/so.
 *
 * @section RETCODES Return codes
 * Return codes are mainly the same between HOST and other platforms but
 * in the higher values a few differences exists. This is mainly in cases
 * where the return code is more the reason code for an error. To simplify
 * the error handling a function (FLMERR) which provides the correct error
 * message independent of the platform are add to this interface. Below
 * you can find a list of important FLAM4 return codes. This list covers
 * any return code to control the program, if another return code occur
 * this will mainly a severe error to terminate execution.
 *
 * <table frame="no">
 *      <tr><td align="right" valign="top" width="4%"><b> 0</b></td><td width="8px"></td><td>No error, success
 * </td><tr><td align="right" valign="top" width="4%"><b> 1</b></td><td width="8px"></td><td>A record has been shortened to the length of the record buffer.
 * </td><tr><td align="right" valign="top" width="4%"><b> 2</b></td><td width="8px"></td><td>The end of the file has been reached while reading; no data is transferred.
 * </td><tr><td align="right" valign="top" width="4%"><b> 3</b></td><td width="8px"></td><td>A gap has been found in a relative file; the record length is zero.
 * </td><tr><td align="right" valign="top" width="4%"><b> 4</b></td><td width="8px"></td><td>When a record is converted to fixed format, it is padded with fill characters.
 * </td><tr><td align="right" valign="top" width="4%"><b> 5</b></td><td width="8px"></td><td>A key is missing when reading from or is invalid when writing to an index sequential file.
 * </td><tr><td align="right" valign="top" width="4%"><b> 6</b></td><td width="8px"></td><td>When reading in a group file, a new file is starting; no data is transferred.
 * </td><tr><td align="right" valign="top" width="4%"><b> 7</b></td><td width="8px"></td><td>Password / cryptokey missing on decompression.
 * </td><tr><td align="right" valign="top" width="4%"><b> 8</b></td><td width="8px"></td><td>Parameter or function not supported.
 * </td><tr><td align="right" valign="top" width="4%"><b> 9</b></td><td width="8px"></td><td>When compressing with the statistics switched on, FLAMUP or FLAM reports that the compressed file is larger than the original file (expansion).
 * </td><tr><td align="right" valign="top" width="4%"><b>10</b></td><td width="8px"></td><td>During decompression, the input file has not been recognized as being a FLAM compressed file.
 * </td><tr><td align="right" valign="top" width="4%"><b>11</b></td><td width="8px"></td><td>The format of the FLAMFILE is wrong.
 * </td><tr><td align="right" valign="top" width="4%"><b>14</b></td><td width="8px"></td><td>The checksum of a compressed record is wrong.
 * </td><tr><td align="right" valign="top" width="4%"><b>22</b></td><td width="8px"></td><td>Invalid compression method.
 * </td><tr><td align="right" valign="top" width="4%"><b>29</b></td><td width="8px"></td><td>Password missing or invalid (passed by FLMPWD).
 * </td><tr><td align="right" valign="top" width="4%"><b>30</b></td><td width="8px"></td><td>Input file is empty.
 * </td><tr><td align="right" valign="top" width="4%"><b>31</b></td><td width="8px"></td><td>Input file does not exist.
 * </td></table>
 *
 * @section COMP Programming the Record Interface at Compression
 *
 * The process of creating a FLAMFILE can be divided
 * into three phases:
 *
 * - open sequence
 * - one or more compression cycles
 * - termination (function #flmcls())
 *
 * The open sequence always starts calling the #flmopn() function.
 * #flmopn() caters for the basic parameters (e.g.,
 * Compression/Decompression). #flmopd() defines the
 * file format of the FLAMFILE. #flmopf() defines the
 * compression parameters. If the #flmopd() and #flmopf()
 * are not used, fixed values are used.
 *
 * Subsequently, #flmopd() and/or #flmopf() can be called if
 * #flmopn() was called with continue_param set. When both
 * functions are called, #flmopd() must come first and also have
 * continue_param set.
 *
 * When #flmopd() or #flmopf() are not called by the application
 * program, FLAM uses implicit settings to generate such
 * calls internally. Default values used with the flam command
 * and flamup calls are not effective here.
 *
 * Finally, if encryption is used, a password must be provided
 * by a #flmpwd() call.
 *
 * In the second phase, one compression cycle must be
 * done for each file being compressed.
 *
 * Such a cycle would normally begin with a #flmphd() call to
 * generate a common FLAM fileheader. Only when a single
 * file is compressed without encryption, this may be omitted.
 * If a FLAM fileheader was created, a user-specific header
 * may be appended by invoking #flmpuh(). With Secure
 * FLAMFILEs, this invocation is mandatory even if the
 * header data length is 0.
 *
 * Now data can be submitted for compression by repeated
 * execution of #flmput(). Each such call passes a record in the
 * FLAM terminology, which can be later replicated identically
 * or with modified record attributes thanks to the structure
 * information kept by FLAM. FLAM collects the data
 * passed to it in the compression buffer and controls compression
 * and the resulting output without involving the application
 * program.
 *
 * A compression cycle is terminated by a call to #flmflu()
 * which causes the remainder in the compression buffer to
 * be compressed and the output of the result. This function
 * also returns statistical information to the application.
 * Following this, a new compression cycle may be initiated
 * by another #flmphd() or the FLAMFILE can be closed by
 * calling #flmcls().
 *
 * Control is always returned to the invoking program. There
 * are no error exits and no error messages are generated
 * by the record interface. Rather, a return code is passed
 * back to the application.
 *
 * @section DECO Programming the Record Interface at Decompression
 *
 * As with compression, decompressing a FLAMFILE also
 * consists of three phases:
 *
 * * open sequence
 * * decompression cycle(s)
 * * termination (function #flmcls())
 *
 * The open sequence here consists of the same function
 * calls as at compression. Only the direction of the flow of
 * information is reversed for some of the arguments, e.g.
 * the compression mode. They are returned to the application.
 *
 * Every function used in the compression cycle has its decompression
 * counterpart that performs the complementary
 * operation. The complements for #flmphd() and #flmpuh()
 * are #flmghd() and #flmguh(), respectively, that for #flmput() is
 * #flmget(). A decompression cycle is also terminated with
 * #flmflu(). In addition, there is a function, #flmpos(), which advances
 * the read position in a FLAMFILE to the beginning
 * of the next original file. This function has no counterpart
 * with compression.
 *
 * Typically, a decompression cycle initially invokes #flmghd()
 * which returns details about the original file such as file
 * name, record format, etc. This may be followed by #flmguh()
 * to retrieve the user-specific header, if present. Subsequent
 * #flmget() calls retrieve one record per call, with the
 * last record of an original file being signalled by a special
 * return code. Skipping the remaining records of an original
 * file can be done by #flmpos() which positions to the next file
 * header. A #flmflu() terminates a decompression cycle that
 * may be followed by another cycle or by #flmcls(), which terminates
 * the processing. One #flmflu() or #flmpos() per cycle is
 * mandatory, all other calls are optional.
 *
 * Some of the function are not documented. These functions are for
 * internal use only. The setter for FLMSET are also not documented
 * because these entries are not available as load module. To simplify
 * C programming these functions can be used, the functionality is
 * explained over FLMSET. FLMSET is only available on mainframes, to
 * define additional host specific parameters after FLMOPN.
 *
 **********************************************************************/

/*! @cond PRIVATE */
#ifdef __cplusplus
   extern "C" {
#endif

#ifndef INC_FL4REC_H
#define INC_FL4REC_H

#if defined(__ZOS__) && !defined(FL4REC_REMOTE_IMPL)

#  pragma linkage(FLMCLS,   OS_NOSTACK)
#  pragma linkage(FLMFLU,   OS_NOSTACK)
#  pragma linkage(FLMEME,   OS_NOSTACK)
#  pragma linkage(FLMDEL,   OS_NOSTACK)
#  pragma linkage(FLMFKY,   OS_NOSTACK)
#  pragma linkage(FLMFRN,   OS_NOSTACK)
#  pragma linkage(FLMGKY,   OS_NOSTACK)
#  pragma linkage(FLMGRN,   OS_NOSTACK)
#  pragma linkage(FLMGTR,   OS_NOSTACK)
#  pragma linkage(FLMIKY,   OS_NOSTACK)
#  pragma linkage(FLMLCR,   OS_NOSTACK)
#  pragma linkage(FLMPKY,   OS_NOSTACK)
#  pragma linkage(FLMUPD,   OS_NOSTACK)
#  pragma linkage(FLMGET,   OS_NOSTACK)
#  pragma linkage(FLMLOC,   OS_NOSTACK)
#  pragma linkage(FLMOPN,   OS_NOSTACK)
#  pragma linkage(FLMOPD,   OS_NOSTACK)
#  pragma linkage(FLMOPF,   OS_NOSTACK)
#  pragma linkage(FLMGHD,   OS_NOSTACK)
#  pragma linkage(FLMPHD,   OS_NOSTACK)
#  pragma linkage(FLMGSH,   OS_NOSTACK)
#  pragma linkage(FLMPSH,   OS_NOSTACK)
#  pragma linkage(FLMGUH,   OS_NOSTACK)
#  pragma linkage(FLMPUH,   OS_NOSTACK)
#  pragma linkage(FLMPWD,   OS_NOSTACK)
#  pragma linkage(FLMPOS,   OS_NOSTACK)
#  pragma linkage(FLMPUT,   OS_NOSTACK)
#  pragma linkage(FLMQRY,   OS_NOSTACK)
#  pragma linkage(FLMSET,   OS_NOSTACK)
#  pragma linkage(FLMQSH,   OS_NOSTACK)

#  define _flmkme    _flmkme_h
#  define flmkme     _flmkme
#  define flmcls     FLMCLS
#  define flmflu     FLMFLU
#  define flmeme     FLMEME
#  define flmdel     FLMDEL
#  define flmfky     FLMFKY
#  define flmfrn     FLMFRN
#  define flmgky     FLMGKY
#  define flmgrn     FLMGRN
#  define flmgtr     FLMGTR
#  define flmiky     FLMIKY
#  define flmlcr     FLMLCR
#  define flmpky     FLMPKY
#  define flmupd     FLMUPD
#  define flmget     FLMGET
#  define flmloc     FLMLOC
#  define flmopn     FLMOPN
#  define flmopd     FLMOPD
#  define flmopf     FLMOPF
#  define flmrdmod   FLMRDMOD
#  define flmrdblh   FLMRDBLH
#  define flmghd     FLMGHD
#  define flmphd     FLMPHD
#  define flmgsh     FLMGSH
#  define flmpsh     FLMPSH
#  define flmguh     FLMGUH
#  define flmpuh     FLMPUH
#  define flmpwd     FLMPWD
#  define flmpos     FLMPOS
#  define flmput     FLMPUT
#  define flmqry     FLMQRY
#  define flmset     FLMSET
#  define flmqsh     FLMQSH
#  define flmerr     FLMERR
#  define flgetmod   FLGETMOD
#  define flsetcmp   FLSETCMP
#  define flgetenc   FLGETENC
#  define flsetenc   FLSETENC
#  define flgetsmd   FLGETSMD
#  define flgetsnr   FLGETSNR
#  define flgetssz   FLGETSSZ
#  define flsetsmd   FLSETSMD
#  define flsetsnr   FLSETSNR
#  define flsetssz   FLSETSSZ
#  define flsetpsp   FLSETPSP
#  define flsetssp   FLSETSSP
#  define flsetvol   FLSETVOL
#  define flsetunt   FLSETUNT
#  define flsetdcl   FLSETDCL
#  define flsetscl   FLSETSCL
#  define flsetmcl   FLSETMCL
#  define flsetdst   FLSETDST
#  define flsetdnr   FLSETDNR
#  define flsetdab   FLSETDAB
#  define flsetsci   FLSETSCI

#else

#  define flmkme    _flmkme1
#  define flmcls    _flmcls1
#  define flmflu    _flmflu1
#  define flmget    _flmget1
#  define flmloc    _flmloc1
#  define flmopn    _flmopn1
#  define flmopd    _flmopd1
#  define flmopf    _flmopf1
#  define flmrdmod  _flmrdmod1
#  define flmrdblh  _flmrdblh1
#  define flmghd    _flmghd1
#  define flmphd    _flmphd1
#  define flmgsh    _flmgsh1
#  define flmpsh    _flmpsh1
#  define flmguh    _flmguh1
#  define flmpuh    _flmpuh1
#  define flmpwd    _flmpwd1
#  define flmpos    _flmpos1
#  define flmput    _flmput1
#  define flmqry    _flmqry1
#  define flmset    _flmset1
#  define flmqsh    _flmqsh1
#  define flmerr    _flmerr1
#  define flmdel    _flmdel1
#  define flmfky    _flmfky1
#  define flmfrn    _flmfrn1
#  define flmgky    _flmgky1
#  define flmgrn    _flmgrn1
#  define flmgtr    _flmgtr1
#  define flmiky    _flmiky1
#  define flmlcr    _flmlcr1
#  define flmpky    _flmpky1
#  define flmupd    _flmupd1
#  define flgetmod  _flgetmod1
#  define flgetcmp  _flgetcmp1
#  define flgetenc  _flgetenc1
#  define flsetenc  _flsetenc1
#  define flgetsmd  _flgetsmd1
#  define flgetsnr  _flgetsnr1
#  define flgetssz  _flgetssz1
#  define flsetsmd  _flsetsmd1
#  define flsetsnr  _flsetsnr1
#  define flsetssz  _flsetssz1
#  define flsetpsp  _flsetpsp1
#  define flsetssp  _flsetssp1
#  define flsetvol  _flsetvol1
#  define flsetunt  _flsetunt1
#  define flsetdcl  _flsetdcl1
#  define flsetscl  _flsetscl1
#  define flsetmcl  _flsetmcl1
#  define flsetdst  _flsetdst1
#  define flsetdnr  _flsetdnr1
#  define flsetdab  _flsetdab1
#  define flsetsci  _flsetsci1

#  define flmkme2   _flmkme2
#  define flmcls2   _flmcls2
#  define flmflu2   _flmflu2
#  define flmget2   _flmget2
#  define flmloc2   _flmloc2
#  define flmopn2   _flmopn2
#  define flmopd2   _flmopd2
#  define flmopf2   _flmopf2
#  define flmrdmod2 _flmrdmod2
#  define flmrdblh2 _flmrdblh2
#  define flmghd2   _flmghd2
#  define flmphd2   _flmphd2
#  define flmgsh2   _flmgsh2
#  define flmpsh2   _flmpsh2
#  define flmguh2   _flmguh2
#  define flmpuh2   _flmpuh2
#  define flmpwd2   _flmpwd2
#  define flmpos2   _flmpos2
#  define flmput2   _flmput2
#  define flmqry2   _flmqry2
#  define flmset2   _flmset2
#  define flmqsh2   _flmqsh2
#  define flgetrn2  _flgetrn2
#  define flgetmod2 _flgetmod2
#  define flgetcmp2 _flgetcmp2
#  define flgetenc2 _flgetenc2
#  define flsetenc2 _flsetenc2
#  define flgetsmd2 _flgetsmd2
#  define flgetsnr2 _flgetsnr2
#  define flgetssz2 _flgetssz2
#  define flsetsmd2 _flsetsmd2
#  define flsetsnr2 _flsetsnr2
#  define flsetssz2 _flsetssz2
#  define flsetpsp2 _flsetpsp2
#  define flsetssp2 _flsetssp2
#  define flsetvol2 _flsetvol2
#  define flsetunt2 _flsetunt2
#  define flsetdcl2 _flsetdcl2
#  define flsetscl2 _flsetscl2
#  define flsetmcl2 _flsetmcl2
#  define flsetdst2 _flsetdst2
#  define flsetdnr2 _flsetdnr2
#  define flsetdab2 _flsetdab2
#  define flsetsci2 _flsetsci2
#  define flmerr2   _flmerr2

#endif

/*! @endcond */

/**********************************************************************/
/**
 * @defgroup TYPDEF Data types
 * @brief Definition of used data types for FLAM's APIs.
 * @{
 */

#ifndef INC_TYPDEF_H
   typedef char                     C08; /**< @brief 8 bit character        */
   typedef signed char              I08; /**< @brief signed 8 bit integer   */
   typedef unsigned char            U08; /**< @brief unsigned 8 bit integer */
   typedef signed short             I16; /**< @brief signed 16 bit integer  */
   typedef unsigned short           U16; /**< @brief unsigned 16 bit integer*/
   typedef signed int               I32; /**< @brief signed 32 bit integer  */
   typedef unsigned int             U32; /**< @brief unsigned 32 bit integer*/
   typedef signed long long int     I64; /**< @brief signed 64 bit integer  */
   typedef unsigned long long int   U64; /**< @brief signed 64 bit integer  */
#endif

/**********************************************************************/

/**
 * @brief The flmset_parameter enum defines constants for the #flmset() function.
 */
enum flmset_parameter {
   FLMSET_SPLITMODE            =   1, /**< @brief split mode 0: none, 1: serial, 2: parallel*/
   FLMSET_SPLITNUMBER          =   2, /**< @brief split number 2 - 4*/
   FLMSET_SPLITSIZE            =   3, /**< @brief split size in MiB 1 - 4095*/
   FLMSET_PRIMARY_SPACE        =   4, /**< @brief size of primary in MiB 1 - 4095*/
   FLMSET_SECONDARY_SPACE      =   5, /**< @brief size of secondary space in MiB 1 - 4095*/
   FLMSET_VOLUME               =   6, /**< @brief volume name 1-8 character*/
   FLMSET_UNIT                 =   7, /**< @brief unit name 1 - 8 character*/
   FLMSET_DATA_CLASS           =   8, /**< @brief data class name 1 - 8 character*/
   FLMSET_STORAGE_CLASS        =   9, /**< @brief storage class name 1 - 8 character*/
   FLMSET_MANAGEMENT_CLASS     =  10, /**< @brief management class name 1 - 8 character*/
   FLMSET_DISPOSTION_STATUS    =  11, /**< @brief disposition status 0: Default, 1: NEW, 2: OLD, 3: SHR, 4: MOD*/
   FLMSET_DISPOSITION_NORMAL   =  12, /**< @brief normal disposition 0: Default, 1: DELETE, 2: KEEP, 3: CATLG, 4: UNCATLG*/
   FLMSET_DISPOSITION_ABNORMAL =  13, /**< @brief abnormal disposition 0: Default, 1: DELETE, 2: KEEP, 3: CATLG, 4: UNCATLG*/
   FLMSET_CRYPTOMODE           =2001, /**< @brief mode of encryption 0: none, 1: FLAM, 2: AES*/
   FLMSET_SECUREINFO           =2002  /**< @brief secure info 0: no, 1: yes, 2: ignore, 3: member*/
};

/**
 * @brief The flmget_parameter enum defines constants for the #flmqry() function.
 */
enum flmget_parameter {
   FLMGET_SPLITMODE            =   1, /**< @brief split mode 0: none, 1: serial, 2: parallel*/
   FLMGET_SPLITNUMBER          =   2, /**< @brief split number 2 - 4*/
   FLMGET_SPLITSIZE            =   3, /**< @brief split size in MiB 1 - 4095*/
   FLMGET_CRYPTOMODE           =2001, /**< @brief mode of encryption 0: none, 1: FLAM, 2: AES*/
   FLMGET_SECUREINFO           =2002, /**< @brief secure info 0: no, 1: yes, 2: ignore, 3: member*/
   FLMGET_MODE                 =4001, /**< @brief general mode 0: deco/read 1: comp/write*/
   FLMGET_RLCOMPMODE           =6001  /**< @brief real compression mode 3: ADC 8: ZEDC*/
};

/******************************************************************************/

/**
 * @brief Defines a key element for index sequential access methods (VSAM-KSDS)
 */
typedef struct key_element {
   //!Key position
   /** Byte offset where the key begins (starting at 1, default 1)*/
   U32         KEYPOS;
   //!Length of the key in the record (minimum 1, default 8)
   U32         KEYLEN;
   //!Data type:
   /** <ul><li>0 = printable characters</li><li>1 = binary data</li></ul>*/
   U32         KEYTYP;
}FKE;

/**
 * @brief Key elements for index sequential data access
 *
 * Defines up to 8 key elements for index sequential data access.
 * Such access methods are only supported on mainframe systems (BSAM/VSAM).
 */
typedef struct key_description {
   //!Key flag
   /**Options:<ul><li>0 = No duplicate key (DEFAULT)</li><li>1 = Duplicate keys allowed</li></ul>*/
   U32         KEYFLG;
   //!Number of key elements
   /** The number of elements in key_description::KEYELM (normally 1 (VSAM), maximum 8 (BSAM))*/
   U32         KEYCNT;
   //!Array of key elements
   FKE         KEYELM[8];
}FKD;

/** @} */
/**********************************************************************/
/**
 * @defgroup FUNC Functions
 * @{
 */

/**
 * Adds version information to buffer
 * @param [in]    l  Level for indentation
 * @param [in]    s  Size of about buffer
 * @param [inout] b  Pointer to about buffer
 * @return Pointer to version buffer
 */
extern const char* pcFl4RecVersion(const int l, const int s, char* b);

/**
 * Adds about information to buffer
 * @param [in]    l  Level for indentation
 * @param [in]    s  Size of about buffer
 * @param [inout] b  Pointer to about buffer
 * @return Pointer to about buffer
 */
extern const char* pcFl4RecAbout(const int l, const int s, char* b);

/**
 * @brief Open a FLAMFILE
 *
 * The #flmopn() function opens a FLAMFILE. It can be followed by a #flmopd()
 * and/or #flmopf() call, in order to set or query the attributes of the
 * FLAMFILE or the FLAM settings.
 *
 * @param [out]   flmid    POINTER  The contents of flmid is a pointer to a character string.
 *                                  This argument identifies the FLAMFILE for which the function
 *                                  is being executed. It is set by the #flmopn() function and
 *                                  must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code (mainframe: 0=No error, 1=Error during memory request,
 *                                  10=File is not a FLAMFILE, 1=FLAMFILE format error, 12=Record length error,
 *                                  13=File length error, 14=Checksum error, 20=Invalid OPENMODE, 21=Invalid size of matrix buffer,
 *                                  22=Invalid compression mode, 23=Invalid code in FLAMFILE, 24=24 Invalid BLOCKMODE,
 *                                  25=Invalid record length, 30=FLAMFILE is empty, 37=Invalid key position (unequal 1),
 *                                  40=Module or table cannot be loaded, 41=Module cannot be called, 42=Module cannot be unloaded,
 *                                  43-49=Abort by user exit, 52=Invalid duplicate keys in the FLAMFILE, 57=Invalid partially compressed data length,
 *                                  x'F00000XX'=FLAM error code from FLAMFIO for FLAMFILE, x' 1F'=31 FLAMFILE no assigned, x' 20'=32 Invalid OPENMODE,
 *                                  x' 21'=33 Invalid file type, x' 22`=34 Invalid record format, x' 23'=35 Invalid record length, x' 24'=36 Invalid block length,
 *                                  x' 26'=38 Invalid key length, x' 27'=39 Invalid file name, x' 28'=40 I/O-module not loaded (e.g. missing STEPLIB in JCL),
 *                                  x'FFXXXXXX'=DMS error code from FLAMFIO for FLAMFILE
 * @param [in]    lstpar   INTEGER  Set to a non-zero value if you will call #flmopd() and/or #flmopf() afterwards
 * @param [in]    opmode   INTEGER  0=INPUT(read), 1=OUTPUT(write), 2=INOUT(read/write, Host-only)
 * @param [in]    ddname   STRING   Zero-terminated filename of file to open (or DD name (STRING8) on mainframes)
 * @param [in]    statis   INTEGER  Indicates whether to collect statistical data that is returned on #flmcls() or #flmflu() (0=disable, other=enable)
 */
extern void flmopn(
   C08**       flmid,
   I32*        rc,
   I32*        lstpar,
   I32*        opmode,
   C08*        ddname,
   I32*        statis);

/**
 * @brief Set/Get FLAMFILE organisation attributes
 *
 * #flmopd() allows to set and/or get file organistation attributes of the FLAMFILE. Use of #flmopd() is optional but has to be done
 * after #flmopn() and before #flmopf(). To create a VSAM-KSDS as FLAMFILE FLAM needs the key position and key length of the original
 * VSAM dataset, to build it own key position and key length. If you access an existing FLAM-VSAM-FILE then the key description
 * structure contains the calculated key length and key position of the FLAMFILE.
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code (mainframe: 0= no error, -1=invalid identification or invalid call (e.g. LASTPAR=0 for FLMOPN), etc.)
 * @param [in]    lstpar   INTEGER  Set to a non-zero value if you will call #flmopf() afterwards
 * @param [inout] namelen  INTEGER  Pass the length of the @p filename buffer; contains the filename length after this call (max. 54 Bytes on mainframe)
 * @param [inout] dsname   String   Buffer used to output the filename of the file to be opened (on mainframes the file name (max. 54 Bytes) allocated to the DD name)
 * @param [inout] org      INTEGER  organisation of FLAMFILE (0,8,16=sequential(PS,ESDS) 1,9,17=index-sequential(IS,KSDS) 2,10=RRDS 3,11=LDS)
 * @param [inout] recf     INTEGER  Record format for FLAMFILE (0,8,16=variable 1,9,17=fixed(default) 2,3,10,18=undefined
 *                                  (on mainframe: 0=V,8=VB,16=VBS 1=F,9=FB,17=FBS 2,10,18=undefined)
 * @param [inout] recs     INTEGER  maximum record length for FLAMFILE 80 - 32760, 512=default (for CX7 the maximum is 4095)
 * @param [inout] recdel   STRING4  Record delimiter for FLAMFILE records (only for CX7 on WIN/UNIX). On mainframe not supported.
 * @param [inout] keydesc  POINTER  Pointer to key description (32 bytes) for the original records at write and from the FLAMFILE at read see #FKD (mainframe only)
 * @param [inout] blks     INTEGER  Blocksize for the FLAMFILE (only for mainframes) 0=unblocked or 80-32760
 * @param [inout] cldisp   INTEGER  Close disposition (only for mainframes) 0=rewind(default) 1=unload 2=leave/retain
 * @param [inout] dev      INTEGER  Device type 0=disc(default) 7=user defined I/O functions are used
 *                                 (for mainframes: 0,8,16=disc or unkown(default) 1,9,17=tape 2,10,18=floppy 3,11,19=streamer 7,15,23=user defined I/O functions are used)
 */
extern void flmopd(
   C08**       flmid,
   I32*        rc,
   I32*        lstpar,
   I32*        namelen,
   C08*        dsname,
   I32*        org,
   I32*        recf,
   I32*        recs,
   U08*        recdel,
   FKD*        keydesc,
   I32*        blks,
   I32*        cldisp,
   I32*        dev);

/**
 * @brief Set/Get FLAMFILE attributes
 *
 * Can be used to define (when compressing) or retrieve (when decompressing)
 * the attributes of the compressed file. #flmopf() can be called as second
 * function after #flmopn(), when #flmopd() is not used, or as third function after #flmopd().
 * For encrypted FLAMFILES on mainframes the function FLMSET() must be used, other platforms
 * use bit 4 and 5 of the @p modus parameter to specify the encryption method: FLAM and AES
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code (mainframe: 0= no error, -1=invalid identification,
 *                                  40=Load of user exit failed, 43-49=abort by user exit, etc.)
 * @param [inout] version  INTEGER  of FLAMFILE: always 2  (UNIX only)
 *                                  (on mainframe: 100= Version 1/6020, 101=Version 1/6035, 200=Version 2, 300=Version 3, 400=Version 4)
 * @param [out]   flcode   INTEGER  During compression, specifies the character set to use to
 *                                  write to the FLAMFILE. This information is returned during the
 *                                  decompression procedure. 0=EBCDIC, 1=ASCII(default)
 * @param [inout] modus    INTEGER  compression method: 0=CX8 1=CX7 2=VR8 3=ADC 5=NDC
 * @param [inout] maxbuf   INTEGER  size of matrix buffer in bytes or kbytes, possible values 1 - 2.621.440, Implicit value (at compression): 32 Kbytes
 *                                  (mainframe: Size of matrix buffer in BYTES)
 * @param [inout] header   INTEGER  option flag for header generation/existence: 0=no 1=yes
 * @param [in]    maxrec   INTEGER  maximum number of records in matrix: limits are 255 for CX8,CX7,VR8  and 4095 for ADC
 * @param [inout] keydesc  POINTER  pointer to key description (32 bytes) for the original records see #FKD (mainframe only)
 * @param [in]    blkmode           method of matrix storage: 0=unblocked (one compressed record from one matrix)
 *                                                            1=blocked (default, data from more than 1 matrix might be in 1 block)
 * @param [in]    exk20    STRING8  name of user exit (8 bytes) for output of compressed data (unused / z/OS only)
 * @param [inout] exd20    STRING8  name of user exit (8 bytes) for input of compressed data  (unused / z/OS only)
 */
extern void flmopf(
   C08**       flmid,
   I32*        rc,
   I32*        version,
   I32*        flcode,
   I32*        modus,
   I32*        maxbuf,
   I32*        header,
   I32*        maxrec,
   FKD*        keydesc,
   I32*        blkmode,
   U08*        exk20,
   U08*        exd20);

/**
 * @brief Flush FLAMFILE
 *
 * #flmflu() finishes the current FLAM matrix and finalizes the
 * compression procedure for a file.
 * The remaining records in the block are compressed and the last FLAM
 * record is padded where necessary. The compressed file is not closed
 * after #flmflu() and the statistics counters are not reset, i.e. another
 * piece of compressed data can be appended. With Secure FLAMFILEs, a
 * member trailer is appended.
 *
 * Statistical information is returned if it has been requested at the
 * corresponding #flmopn() call (statis != 0).
 *
 * When compressing Secure FLAMFILEs, #flmflu() is permitted only after
 * #flmpuh() or #flmput(). When decompressing Secure FLAMFILEs, #flmflu()
 * must be preceded by either #flmget(), #flmghd(), or #flmguh().
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code (mainframe: 0= no error, -1=invalid identification,
 *                                  43-49=abort by user exit, x'FFXXXXXX'=DMS error code)
 * @param [out]   cputime  INTEGER  Consumed CPU time in units of time as returned by clock()
 *                                  (UNIX in seconds, MAINFRAME: used CPU in milliseconds)
 * @param [out]   recin    INTEGER  If #flmopn() was called with @p statis != 0, this argument
 *                                  returns the number of decompressed records which have been processed
 *                                  by #flmput() or #flmget(). The accumulated values of this counter
 *                                  are only significant if complete files are processed.
 * @param [out]   bytin    INTEGER  If #flmopn() was called with @p statis != 0, this argument
 *                                  returns the number of bytes of the decompressed records which
 *                                  have been transferred with #flmput() or #flmget(). The accumulated
 *                                  value of this counter is only significant if complete files are
 *                                  processed.
 * @param [out]   bytoflin INTEGER  UNIX: If the accumulated value of the @p bytin argument exceeds
 *                                  2,000,000,000, this counter is used for multiples of 2,000,000,000.
 *                                  MAINFRAME: Overflow counter for original bytes. With extremely big
 *                                  compressed files (greater 4 gigabytes) one word byte counter are
 *                                  not sufficient. For this purpose the overflow counters are provided.
 *                                  They allow to extend the counter to a double word.
 * @param [out]   recout   INTEGER  If #flmopn() was called with @p statis != 0, this argument
 *                                  returns the number of compressed records which were created during
 *                                  the compression procedure or read during the decompression procedure.
 *                                  This value is only significant if complete files are processed
 *                                  (MAINFRAME: Number of compressed records).
 * @param [out]   bytout   INTEGER  If #flmopn() was called with @p statis != 0, this argument
 *                                  returns the number of bytes which were created during the
 *                                  compression procedure or read during the decompression procedure.
 *                                  This value is only significant if complete files are processed
 *                                  (MAINFRAME: Number of compressed bytes).
 * @param [out]   bytoflout INTEGER UNIX: If the accumulated value of the @p bytout argument exceeds
 *                                  2,000,000,000, this counter is used for multiples of 2,000,000,000.
 *                                  MAINFRAME: Overflow counter for compressed bytes. With extremely big
 *                                  compressed files (greater 4 gigabytes) one word byte counter are
 *                                  not sufficient. For this purpose the overflow counters are provided.
 *                                  They allow to extend the counter to a double word.
 */
extern void flmflu(
   C08**       flmid,
   I32*        rc,
   U32*        cputime,
   U32*        recin,
   U32*        bytin,
   U32*        bytoflin,
   U32*        recout,
   U32*        bytout,
   U32*        bytoflout);

/**
 * @brief End member in a FLAMFILE (only z/OS)
 *
 * The function FLMEME finishes the current data as member of a
 * Group-FLAMFILE (end member). During compression, the content of
 * the matrix is compressed and written immediately, enlarged with
 * some security information (e.g. byte- and record counter), if
 * required (SECUREINFO=YES); during decompression, the next
 * matrix is decompressed. On AES encryption, a member MAC is
 * created and written into the end member. The MAC is returned.
 * On AES decryption, the member MAC is returned. Statistical values
 * are returned. To end only a matrix and not the entire member,
 * function * #flmflu() is provided.
 *
 * @param [in]    flmid     POINTER Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc        INTEGER Return code (mainframe: 0=no error, -1=invalid identification,
 *                                  43-49=abort by user exit, x'FFXXXXXX'=DMS error code)
 * @param [out]   cputime   INTEGER Consumed CPU time in units of time as returned by clock()
 *                                  in milliseconds.
 * @param [out]   recin     INTEGER Number of original records
 * @param [out]   bytin     INTEGER Number of original bytes
 * @param [out]   bytoflin  INTEGER Overflow counter for original bytes. With extremely big
 *                                  compressed files (greater 4 gigabytes) one word byte counters are
 *                                  not sufficient. For this purpose the overflow counters are provided.
 *                                  They allow to extend the counter to a double word.)
 * @param [out]   recout    INTEGER Number of compressed records
 * @param [out]   bytout    INTEGER Number of compressed bytesrecords
 * @param [out]   bytoflout INTEGER Overflow counter for compressed bytes. With extremely
 *                                  big compressed files (greater 4 gigabytes) one word byte counters
 *                                  are not sufficient. For this purpose the overflow counters are
 *                                  provided. They allow to extend the counter to a double word.
 * @param [out]   membermac STRING8 pointer to a 8 byte string field where the member mac is returned.
 */
extern void flmeme(
   C08**       flmid,
   I32*        rc,
   U32*        cputime,
   U32*        recin,
   U32*        bytin,
   U32*        bytoflin,
   U32*        recout,
   U32*        bytout,
   U32*        bytoflout,
   U08*        membermac);

/**
 * @brief Delete last record (only z/OS)
 *
 * With function FLMDEL it is possible to delete the last
 * read original record from an index sequential FLAMFILE.
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (Mainframe: 0=no error, -1=invalid identification
 *                                  for function invalid, 5=no active record found,
 *                                  43-49=abort by user exit, x'FFXXXXXX'= DMS)
 */
extern void flmdel(
   C08**       flmid,
   I32*        rc);

/**
 * @brief Find record using a key (only z/OS)
 *
 * The function FLMFKY (Find Key) can be used to search in
 * an index sequential FLAMFILE for a record of the original
 * file, whose key is equal to or greater than a specified key
 * value. The specified value can be generic, i.e. not all of
 * the positions of the key value have to be specified
 * uniquely. The record found is the next record to be
 * processed. If FLMFKY does not find a record, the old
 * position is retained.
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (Mainframe: 0=no error, -1=invalid identification
 *                                  or function, 5=Key not found, otherwise=see
 *                                  function FLMGET)
 * @param [in]    keylen   INTEGER  Key length: This contains the number of significant bytes in the
 *                                  specified key value. It can be less than the key length.
 *                                  In this case, only the length passed here is taken into
 *                                  account in the logical relation specified in the argument
 *                                  checkmod.
 * @param [in]    record   POINTER  Record buffer with search key
 * @param [in]    checkmod INTEGER  Type of relation (0 - equal, 1 - greater than or equal, 2 - greater than)
 */
extern void flmfky(
   C08**       flmid,
   I32*        rc,
   I32*        keylen,
   U08*        record,
   I32*        checkmod);

/**
 * @brief Find record number (only z/OS)
 *
 * The function FLMFRN (Find Record Number) positions
 * the record pointer to a record with a specified number
 * in an index sequential FLAMFILE. This number corresponds
 * to the record number of the sequential or relative original
 * file. The record is the next record to be processed.
 * Specifying checkmod=1 or 2 allows gaps and empty records
 * to be skipped. If FLMFRN does not find a record, the old
 * position isretained.
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (0=no error, -1=invalid identification
 *                                  or function, 5=invalid position, otherwise=see
 *                                  function FLMGET)
 * @param [inout] recno    INTEGER  Record number (1 = File start. With checkmod=1,2 the true record number is returned)
 * @param [out]   checkmod INTEGER  Type of relation (0 - Record with specified number, 1 - Record with specified number, skip gaps and empty records, 2 - Record with next number, skip gaps and empty records)
 */
extern void flmfrn(
   C08**       flmid,
   I32*        rc,
   I32*        recno,
   I32*        checkmod);

/**
 * @brief Get record addressed by key (only z/OS).
 *
 * The user can obtain an original record from an index
 * sequential FLAMFILE via a key by using the function
 * FLMGKY. The search key must be placed at the key
 * position within the record area.
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (0=no error, -1=invalid identification
 *                                  or function, 5=Key not found, otherwise=see
 *                                  function FLMGET)
 * @param [out]   reclen   INTEGER  Length of passed record in bytes
 * @param [out]   record   STRING   Original record (Data with key)
 * @param [in]    buflen   INTEGER  Length of available record buffer in byte
 */
extern void flmgky(
   C08**       flmid,
   I32*        rc,
   I32*        reclen,
   U08*        record,
   I32*        buflen);

/**
 * @brief Get record by number (only z/OS)
 *
 * The function FLMGRN (Get Record Number) reads the original
 * record of a sequential or relative file from an index sequential
 * FLAMFILE as specified by the record number. If FLMGRN does not
 * find a valid record, the new position moved to is the next record
 * or the end of the file.
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (0=no error, -1=invalid identification
 *                                  or function, 1=Record was truncated because original record
 *                                  was larger than BUFLEN, 2=END-OF-FILE found, 3=Gap in relative
 *                                  file found, 5=Invalid record number (0 or negative), 6=New
 *                                  file starts, eventually the new file header can be read,
 *                                  otherwise=see function FLMGET)
 * @param [out]   reclen   INTEGER  Record length in bytes of the passed record
 * @param [out]   record   STRING   Original record (data)
 * @param [in]    buflen   INTEGER  Length of available record buffer in bytes
 * @param [in]    recno    INTEGER  Record number (1 = file start)
 *
 * With return codes 2, 6 and 7 no record is passed.
 * With return code 3 a record of length =0 is passed.
 * *
 */
extern void flmgrn(
   C08**       flmid,
   I32*        rc,
   I32*        reclen,
   U08*        record,
   I32*        buflen,
   I32*        recno);

/**
 * @brief Get previous record (only z/OS)
 *
 * With function FLMGTR (Get reverse) the previous original
 * record is read in sequential order. It is possible to position
 * to a certain record in the compressed file using FLMGKY or FLMPOS
 * and then to read backward sequentially. Data is transferred from
 * the record buffer to the calling program (MOVE mode).
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (0=no error, -1=invalid identification
 *                                  or function, 1=Record was truncated because original record
 *                                  was larger than BUFLEN, 2=END-OF-FILE found, 3=Gap in relative
 *                                  file found, 6=New file starts, eventually the new file header
 *                                  can be read, otherwise=see function FLMGET).
 * @param [out]   reclen   INTEGER  Record length in bytes of the passed record.
 * @param [out]   record   STRING   Original record (data).
 * @param [in]    buflen   INTEGER  Length of available record buffer in bytes.
 *
 * With return codes 2 and 6 no record is passed.
 * With return code 3 a record of length 0 is passed.
 */
extern void flmgtr(
   C08**       flmid,
   I32*        rc,
   I32*        reclen,
   U08*        record,
   I32*        buflen);

/**
 * @brief Insert record with key (only z/OS)
 *
 * The function FLMIKY allows to insert records with a key to
 * an index sequential FLAMFILE (VSAM-KSDS).
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (0=no error, -1=invalid identification
 *                                  or function, 5=Key exists already, 15=Original record
 *                                  is larger than 32763 bytes, 16=Original record is larger
 *                                  than matrix - 4, 43-49=Abort by user exit, 52=Too many)
 *                                  or invalid duplicate keys, x'FFXXXXXX'=DMS error code)
 * @param [in]    reclen   INTEGER  Record length (data length) in bytes without record length field
 * @param [in]    record   STRING   Original record (data with key)
 */
extern void flmiky(
   C08**       flmid,
   I32*        rc,
   I32*        reclen,
   U08*        record);

/**
 * @brief Locate previous record (only z/OS)
 *
 * The function FLMLCR is equivalent to FLMGTR (Get reverse).
 * The data will not be transmitted but only a pointer on
 * the record is provided (locate Mode).
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (0=no error, -1=invalid identification
 *                                  or function, 2=Beginning of file found, otherwise=see
 *                                  FLMGET)
 * @param [out]   reclen   INTEGER  Record length in bytes of the passed record
 * @param [out]   recptr   POINTER  Record address (data address)
 *
 * With return codes 2 and 6 no record address is passed.
 * With return code 3 the length 0 is passed.
 */
extern void flmlcr(
   C08**       flmid,
   I32*        rc,
   I32*        reclen,
   U08**       recptr);

/**
 * @brief Put record by key (only z/OS)
 *
 * The function FLMPKY allows to insert records into an
 * index sequential FLAMFILE or to update records within
 * such a file via a key.
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (0=no error, -1=invalid identification
 *                                  or function, 5=Key not allowed, 15=Original record
 *                                  greater than 32763 bytes, 16=Original record
 *                                  greater than matrix - 4, 43=Abort by user exit,
 *                                  x'FFXXXXXX'= DMS error code)
 * @param [in]    reclen   INTEGER  Record length (data length) in bytes without record length field (exclusive length)
 * @param [in]    record   STRING   Original record (Data with key)
 */
extern void flmpky(
   C08**       flmid,
   I32*        rc,
   I32*        reclen,
   U08*        record);

/**
 * @brief Update record (only z/OS)
 *
 * The function FLMUPD updates the original record last
 * read from a VSAM-KSDS FLAMFILE.
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (0=no error, -1=invalid identification
 *                                  or function, 5=No current record, 15=Original record
 *                                  greater than 32764 bytes, 16=Original record
 *                                  greater than matrix - 4, 43=Abort by user exit,
 *                                  x'FFXXXXXX'= DMS error code).
 * @param [in]    reclen   INTEGER  Record length (data length) in bytes without record lengthfield.
 * @param [in]    record   STRING   Original record (data).
 */
extern void flmupd(
   C08**       flmid,
   I32*        rc,
   I32*        reclen,
   U08*        record);

/**
 * @brief Close FLAMFILE
 *
 * The #flmcls() function finalizes the record interface.
 *
 * If compression is closed, the last matrix is compressed and the
 * compressed data is written to the FLAMFILE. Additional information
 * (byte-, record counter, MACs) are stored as an 'ending record', if
 * required (SECUREINFO=YES). Then the FLAMFILE is closed.
 *
 * When decompression is closed, only the FLAMFILE is closed. Additional
 * records not yet read from the FLAMFILE are discarded.
 *
 * Statistical information are returned if it has been requested at the
 * corresponding #flmopn() call (statis != 0).
 * Mainframe: The parameters cputime until bytoflout are only used if the
 * statistics are switched on in FLMOPN.
 *
 * With Secure FLAMFILEs, #flmcls() may only be invoked immediately after
 * #flmflu() or #flmpos().
 * @param [inout] flmid    POINTER  The contents of flmid is a pointer to a character string.
 *                                  This argument identifies the FLAMFILE for which the function
 *                                  is being executed. It is set by the #flmopn() function and
 *                                  must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (mainframe: 0=no error, -1=Invalid identification (e.g. FLMCLS
 *                                  already done ?), 43-49=Abort by user exit, x'FFXXXXXX'=DMS- error code)
 * @param [out]   cputime  INTEGER  Consumed CPU time in units of time as returned by clock()
 *                                  (Mainframe: CPU time in milliseconds, UNIX: in seconds).
 * @param [out]   recin    INTEGER  If #flmopn() was called with @p statis != 0, this argument
 *                                  returns the number of original records which have been
 *                                  processed by #flmput() or #flmget(). The accumulated values of
 *                                  this counter are only significant if complete files are processed.
 * @param [out]   bytin    INTEGER  If #flmopn() was called with @p statis != 0, this argument
 *                                  returns the number of bytes of the original records which
 *                                  have been transferred with #flmput() or #flmget(). The accumulated
 *                                  value of this counter is only significant if complete files are
 *                                  processed.
 * @param [out]   bytoflin INTEGER  UNIX: If the accumulated value of the @p bytin argument exceeds
 *                                  2,000,000,000, this counter is used for multiples of 2,000,000,000.
 *                                  MAINFRAME: Overflow counter for original bytes. With extremely big
 *                                  compressed files (greater 4 gigabytes) one word byte counters are
 *                                  not sufficient. For this purpose the overflow counters are provided.
 *                                  They allow to extend the counter to a double word.
 * @param [out]   recout   INTEGER  If #flmopn() was called with @p statis != 0, this argument
 *                                  returns the number of compressed records which were created during
 *                                  the compression procedure or read during the decompression procedure.
 *                                  This value is only significant if complete files are processed.
 * @param [out]   bytout   INTEGER  If #flmopn() was called with @p statis != 0, this argument
 *                                  returns the number of bytes which were created during the
 *                                  compression procedure or read during the decompression procedure.
 *                                  This value is only significant if complete files are processed.
 * @param [out]   bytoflout INTEGER UNIX: If the accumulated value of the @p bytout argument exceeds
 *                                  2,000,000,000, this counter is used for multiples of 2,000,000,000.
 *                                  MAINFRAME: Overflow counter for compressed bytes. With extremely big
 *                                  compressed files (greater 4 gigabytes) one word byte counter are
 *                                  not sufficient. For this purpose the overflow counters are provided.
 *                                  They allow to extend the counter to a double word.
 */
extern void flmcls(
   C08**       flmid,
   I32*        rc,
   U32*        cputime,
   U32*        recin,
   U32*        bytin,
   U32*        bytoflin,
   U32*        recout,
   U32*        bytout,
   U32*        bytoflout);

/**
 * @brief Get file header
 *
 * #flmghd() allows retrieving the file attributes of the
 * original file during decompression if they were stored in the
 * FLAMFILE during compression. If the FLAMFILE contains several file
 * headers (see #flmphd()), the last file header found by FLAM is returned.
 * It is possible to request the file header information with function#
 * FLMGHD at any time between FLAM-OPEN (FLMOPN, FLMOPD, FLMOPF) and
 * FLAM-CLOSE (FLMCLS).
 *
 * The first file header is usually available immediately after #flmopn()
 * (see #flmopf() header=1). When FLAM recognizes additional file headers,
 * it will inform the user via the return code (RETCO=6) of #flmget() or
 * #flmloc().
 * @param [in]    flmid    POINTER  Pointer to a character string of 8 bytes. Identifies the FLAMFILE. It is set by the
 *                                  #flmopn() function and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (mainframe: 0=no error, -1=Invalid identification or function)
 * @param [inout] namelen  INTEGER  Pass the length of the @p filename buffer in which the name
 *                                  of the original file will be returned. Is set to the actual
 *                                  length when function returns
 *                                  (Mainframe: 0=File name not known).
 * @param [inout] filename STRING   Buffer area in which to store the original filename.
 *                                  If the buffer is too small, the filename will be truncated to
 *                                  the length of the buffer.
 * @param [inout] org      INTEGER  returns a value for the organization of the original file.
 *                                  Possible values (not all are supported on Unix): 0=sequential,
 *                                  1=index-sequential, 2=relative, 3=random/direct access, 4=no record
 *                                  structure, 5=library 6=physical
 * @param [out]   recf     INTEGER  returns a value for the record format of the original file.
 *                                  Possible values (not all are supported on Unix):
 *                                  0/8/16/24 = variable / blocked / blocked/spanned / VFC;
 *                                  1/9/17 = fix / blocked / blocked/Standard;
 *                                  2/10/18 = undefined (U)/ EAF;
 *                                  3/11/19 = stream (S)/ text delimiter / length fields
 * @param [out]   recs     INTEGER  This argument returns the record size of the original file.
 *                                  For variable record sizes and the stream record format, the value is 0
 *                                  (Mainframe= 0-32760).
 * @param [out]   recdel   STRING4  This argument specifies the record delimiter for the stream record format.
 * @param [out]   keydesc  POINTER  Key description structure, 32 bytes (mainframe only)
 * @param [out]   blks     INTEGER  Block length of original file (0=unblocked), Mainframe = 0-32760).
 * @param [out]   prnctr   INTEGER  Printer control characters (0=none, 1=ASA, 2=Machine specific)
 * @param [out]   system   STRING2  This argument consists of two bytes and is used to return a
 *                                  code for the operating system in which the FLAMFILE was created:
 *                                  = x'0000' unknown
 *                                  = x'0080' MS-DOS
 *                                  = x'0101' IBM MVS, z/OS
 *                                  = x'0102' IBM VSE/SP, zVSE
 *                                  = x'0103' IBM VM/SP VM/XA
 *                                  = x'0104' IBM DPPX/8100
 *                                  = x'0105' IBM DPPX/370
 *                                  = x'02XX' UNISYS
 *                                  = x'0301' DEC VMS
 *                                  = x'0302' DEC ULTRIX
 *                                  = x'0401' SIEMENS BS2000
 *                                  = x'0402' SIEMENS SINIX
 *                                  = x'0403' SIEMENS SYSTEM V
 *                                  = x'0501' NIXDORF 886X
 *                                  = x'0502' NIXDORF TARGON
 *                                  = x'06XX' WANG
 *                                  = x'07XX' PHILLIPS
 *                                  = x'08XX' OLIVETTI
 *                                  = x'11XX' INTEL 80286
 *                                  = x'12XX' INTEL 80386
 *                                  = x'13XX' INTEL 80486
 */
extern void flmghd(
   C08**       flmid,
   I32*        rc,
   I32*        namelen,
   C08*        filename,
   I32*        org,
   I32*        recf,
   I32*        recs,
   U08*        recdel,
   FKD*        keydesc,
   I32*        blks,
   I32*        prnctr,
   C08*        system);

/**
 * @brief Put file  header
 *
 * The #flmphd() function is only allowed during
 * compression and if header=1 was set with #flmopf(). It generates a
 * common file header, which describes the file format of the original
 * records that are transferred subsequently. If several different files
 * are compressed into a single FLAMFILE, a separate file header can be
 * generated for each file with the #flmphd() function. FLAM returns this
 * file header information during the decompression procedure if it has
 * been requested to do so (#flmghd()).
 *
 * Calls to #flmphd() with @p continue_param!=0 or after #flmpwd() must be
 * followed immediately by #flmpuh().
 *
 * Using SECUREINFO=YES, function #flmphd() is mandatory!
 *
 * Note: The parameters in #flmphd() also control the construction of an
 * index-sequential FLAMFILE. On DSORG=0 (sequential data), a record
 * number is created and used as a record key; on DSORG=1 (index-sequential)
 * the original key is used.
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (mainframe: 0=no error, -1=Invalid identification or function)
 * @param [in]    namelen  INTEGER  Length of the @p filename
 *                                  (mainframe: 0 = no use of filename)
 * @param [in]    filename STRING   Buffer containing the original filename
 * @param [in]    org      INTEGER  Code for the organization of the original file. For permissible values, see the #flmghd() function.
 * @param [in]    recf     INTEGER  Code for the record format of the original file. For permissible values, see the #flmghd() function.
 * @param [in]    recs     INTEGER  The maximum record size of the original file (mainframe: 0-32760)
 * @param [in]    recdel   STRING4  Record delimiter
 * @param [in]    keydesc  POINTER  Key description structure, 32 bytes  (for mainframes only)
 * @param [in]    blks     INTEGER  Block length of original file (UNIX: 0=unblocked, 0-32767, MAINFRAME: 0-32760)
 * @param [in]    prnctr   INTEGER  Printer control characters for mainframe only (0=none, 1=ASA, 2=Machine specific)
 * @param [in]    system   STRING2  This argument consists of two bytes and is used to return a code
 *                                  for the operating system in which the FLAMFILE was created. For a list of valid values, see #flmghd().
 * @param [in]    cont     INTEGER  Indicates whether a call to #flmpuh() will follow (0=no more parameter, otherwise=a user header is to be transferred with FLMPUH)
 */
extern void flmphd(
   C08**       flmid,
   I32*        rc,
   I32*        namelen,
   C08*        filename,
   I32*        org,
   I32*        recf,
   I32*        recs,
   U08*        recdel,
   FKD*        keydesc,
   I32*        blks,
   I32*        prnctr,
   C08*        system,
   I32*        cont);

/**
 * @brief Get user header
 *
 * Retrieves the data from the user-specific FLAM file header. Calling
 * this function is only allowed during decompression and immediately
 * following an #flmghd() call.
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is executed. It is set by the #flmopn() function
 *                                  and must not be changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (mainframe: 0=no error, -1=Invalid identification or function) *
 * @param [inout] hdrlen   INTEGER  Pass the length of the buffer in which the user-specific
 *                                  file header will be returned. Is set to the actual length when function returns.
 *                                  (Mainframe: 0=no data, 1-3500=8-bit compressed data for CX8 or VR8,
 *                                  -1750=7-bit compressed data for CX7)
 * @param [out]   header   STRING   Buffer containing user header with user data.
 *                                  The user data is reproduced exactly as it is written, i.e.
 *                                  converting the code of a file transfer has no effect here.
 */
extern void flmguh(
   C08**       flmid,
   I32*        rc,
   I32*        hdrlen,
   C08*        header);

/**
 * @brief Put user header
 *
 * The flmpuh() function adds a user-specific header with
 * information of arbitrary structure to the FLAMFILE. This information
 * is added in binary form and can be retrieved during decompression with
 * #flmguh() (the complementary function).
 *
 * Calling this function is only allowed during compression and immediately
 * following an #flmphd() call.
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is
 *                                  executed. It is set by the #flmopn() function and must not be
 *                                  changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (mainframe: 0=no error, -1=Invalid identification or function)
 * @param [in]    hdrlen   INTEGER  max. 1750 (Host, 7-bit, CX7), 32732 bytes (other))
 * @param [in]    header   STRING   User-specific header data
 *                                  In CX7, this data is converted in such a way that the
 *                                  integrity of the FLAMFILE is not corrupted.
 *                                  The user data itself remains in its original code, even during code
 *                                  conversions using heterogeneous data exchange.
 */
extern void flmpuh(
   C08**       flmid,
   I32*        rc,
   I32*        hdrlen,
   C08*        header);

/**
 * @brief Sets a password for encryption/decryption while compressing/decompressing
 *
 * It is the first call after the last FLMOPx function during encryption.
 *
 * The encryption mode is set by the function #flmset(). On decryption,
 * the information is read from the FLAMFILE and can be obtained by calling #flmqry().
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is
 *                                  executed. It is set by the #flmopn() function and must not be
 *                                  changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (mainframe: 0=no error, -1=Password function invalid, e.g. for
 *                                  MODE=CX8, VR8, CX7, renewed call up)
 * @param [in]    pwdlen   INTEGER  The password's length in characters  (max. 64)
 * @param [in]    passwd   STRING   The password string
 */
extern void flmpwd(
   C08**       flmid,
   I32*        rc,
   U32*        pwdlen,
   C08*        passwd);


/**
 * @brief Load and use FKME
 *
 * Works like SETPWD but use FKME parameters. It dynamically loads the
 * FKME module, runs the function code INFO, if @p inflen provided and
 * execute function code COMP or DECO with the provided values.
 *
 * @param [inout] flmid    POINTER  Identifies the FLAMFILE for which the function is
 *                                  executed. It is set by the #flmopn() function and must not be
 *                                  changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 * @param [inout] kmclen            length of key management context (user header)
 * @param [inout] kmc               pointer to key mangement context (user header)
 * @param [in]    liblen            length of the library name (not relevant on z/OS)
 * @param [in]    lib               pointer to the library name
 * @param [in]    fuclen            length of the function name
 * @param [in]    fuc               pointer to the function name (for dynamic load)
 * @param [in]    parlen            length of the parameter string
 * @param [in]    par               pointer to the paramter string
 * @param [inout] msglen            size/length of return message
 * @param [out]   msg               point to the return message
 * @param [inout] inflen            size/length of return info string (could be 0 to prevent call of function code INFO)
 * @param [out]   inf               point to the info string
 */
extern void flmkme(
   C08**       flmid,
   I32*        rc,
   U32*        kmclen,
   U08*        kmc,
   const U32*  liblen,
   const C08*  lib,
   const U32*  fuclen,
   const C08*  fuc,
   const U32*  parlen,
   const C08*  par,
   U32*        msglen,
   C08*        msg,
   U32*        inflen,
   C08*        inf);
/*! @cond PRIVATE */
extern void _flmkme(
   C08**       flmid,
   I32*        rc,
   U32*        kmclen,
   U08*        kmc,
   const U32*  liblen,
   const C08*  lib,
   const U32*  fuclen,
   const C08*  fuc,
   const U32*  parlen,
   const C08*  par,
   U32*        msglen,
   C08*        msg,
   U32*        inflen,
   C08*        inf);
/*! @endcond */

/**
 * @brief Set read position
 *
 * FLMPOS (Position) allows to position the record pointer within
 * compressed files.
 *
 * With OPEN=INPUT and INOUT or OUTIN the pointer can positioned
 * anywhere, irrespective of whether the original file is index
 * sequential or sequential.
 * With OPEN = OUTPUT it is possible to create gaps in relative
 * files by advancing the write pointer by N records.
 *
 * FLMPOS (Position) is used for relative positioning in any FLAMFILE and
 * for creating gaps when writing relative files.
 *
 * The @p pos parameter is used as follows:
 *
 * On mainframes:
 *        -MAXINT -> Start of file
 *        +MAXINT -> End of file
 *        -99999999 -> Start of file for Cobol
 *        +99999999 -> End of file for Cobol
 *        -99999998 -> Start of previous file in a group file
 *        +99999998 -> Start of next file in a group file
 *        -N        -> N records backward
 *        +N        -> N records forward
 *        -99999998 -> Back to the start of the current file
 *                     or to the start of the previous file
 *                     in a group file
 *        +99999998 -> Start of next file in a group file
 *
 * ON UNIX: only one relative position is supported:
 *        +99999998 -> Start of next file in a group file
 *
 * @param [in]   flmid    POINTER  Identifies the FLAMFILE for which the function is
 *                                 executed. It is set by the #flmopn() function and must not be
 *                                 changed until calling #flmcls().
 * @param [out]  rc       INTEGER  Return code
 *                                 (mainframe: 0=no error, -1=Invalid identification or function,
 *                                 5=Invalid position, 40-78=see function FLMGET, x'FFXXXXXX'=DMS error code)
 * @param [in]   pos      INTEGER  new position to use on get next read (see above).
 */
extern void flmpos(
    C08**      flmid,
    I32*       rc,
    I32*       pos);

/**
 * @brief Get next record
 *
 * #flmget() reads the next original record sequentially. The
 * data is transferred to the supplied @p record buffer. A special return
 * code indicates when a new file header is encountered.
 *
 * It is possible to position to a certain record in the compressed file
 * using #flmgky() or #flmpos() and then to continue with sequential reading.
 *
 * #flmget() may only be used at decompression. With encrypted FLAMFILEs,
 * a password must be provided via #flmpwd() before the first invocation
 * of #flmget().
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is
 *                                  executed. It is set by the #flmopn() function and must not be
 *                                  changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (mainframe: 0=no error, -1=Invalid identification or function,
 *                                  1=Record was truncated because original record was larger than BUFLEN,
 *                                  2=END-OF-FILE found, 3=Gap in relative file found, 6=New file starts,
 *                                  eventually the new file header can be read, 7=Password required. Pass it
 *                                  via FLMPWD, 11=FLAMFILE format error, 12=Record length error, 13=File length error,
 *                                  14=Checksum error, 29=Illegal password, 43-49=Abort by user exit,
 *                                  52=Too many or invalid duplicate keys, x'FFXXXXXX'=Data management error code,
 *                                  etc.
 * @param [out]   reclength INTEGER Returns the length in bytes of the @p record which has been read
 * @param [out]   record    STRING  Record buffer used to put record data into
 * @param [in]    buflength INTEGER Length of the @p record buffer in bytes
 *
 * With return codes 2 , 6 and 7 no record is passed.
 * With return code 3 a record of length 0 is passed.
 *
 */
extern void flmget(
   C08**       flmid,
   I32*        rc,
   I32*        reclength,
   U08*        record,
   I32*        buflength);

/**
 * @brief Locate record
 *
 * The function #flmloc() is equivalent to #flmget(), except that it does
 * not put a read record into a supplied buffer. Instead, a pointer to
 * the record is returned (LOCATE mode).
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is
 *                                  executed. It is set by the #flmopn() function and must not be
 *                                  changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (mainframe: 0=no error, -1=Invalid identification or function,
 *                                  1=Record was truncated because original record was)
 * @param [out]   reclength INTEGER Length of the record pointed to by @p record
 * @param [out]   record    POINTER Contains pointer to the read record after call
 *
 * With return codes 2 , 6 and 7 no record is passed.
 * With return code 3 a record of length 0 is passed.
 */
extern void flmloc(
   C08**       flmid,
   I32*        rc,
   I32*        reclength,
   U08**       record);

/**
 * @brief Put record
 *
 * The flmput function compresses one original record at a time.
 *
 * @param [in]    flmid    POINTER  Identifies the FLAMFILE for which the function is
 *                                  executed. It is set by the #flmopn() function and must not be
 *                                  changed until calling #flmcls().
 * @param [out]   rc       INTEGER  Return code
 *                                  (mainframe: 0=no error, -1=Invalid identification or function,
 *                                  2=END-OF-FILE found, 3=Gap in relative file found, 6=New file starts,
 *                                  eventually the new file header can be read, etc.
 * @param [in]    reclength INTEGER Record length in bytes
 * @param [in]    record    STRING  Buffer containing the buffer with record/data address
 */
extern void flmput(
   C08**       flmid,
   I32*        rc,
   I32*        reclength,
   U08*        record );

/**
 * @brief Provides an error message
 *
 * With #flmerr() a return code can be translated into a talking error message.
 *
 * @param [inout] rc       INTEGER  Return code
 * @param         msglen            at input space for the error message, at output length of the error message
 * @param         errmsg            pointer to the error message buffer
 */
extern void flmerr(
   I32*        rc,
   I32*        msglen,
   const C08** errmsg);

/**
 * @brief Query extended FLAMFILE attributes
 *
 * With #flmqry() parameters can be obtained during decompression.
 * It may be called at any time after #flmopn(), but the results depend
 * on the moment it is called. E.g. SPLIT.. are first known after #flmopd(),
 * CRYPTOMODE after #flmopf().
 *
 * Note: In opposite to the other function calls the return code
 * @p rc was expanded into two words (2 x 4 byte). The
 * first word is still the return code, the second word is the
 * info code. The info code is the parameter in error on return.
 * If the parameter ID unknown the info code 91# will be set.
 *
 * Besides #FLMGET_CRYPTOMODE and #FLMGET_SECUREINFO extended attributes
 * are only meaningful on the mainframe.
 *
 * @see #flmget_parameter and #flmset
 *
 * @param [in]    flmid       POINTER   Identifies the FLAMFILE for which the function is
 *                                      executed. It is set by the #flmopn() function and must not be
 *                                      changed until calling #flmcls().
 * @param [out]   rc          INTARY2   Return code and info code
 * @param [in]    parameter   INTEGER   Identifies the #flmget_parameter
 * @param [out]   value       POINTER   Parameter value read
 *
 * Note:
 *  Only on z/OS multiple parameter/value pairs can be get
 *  in one call. It is necessary to mark the end of the
 *  parameter list! Most compilers do it automatically, but
 *  in Assembler the last parameter address has to be
 *  flagged: A(X'80000000')+VALUEn).
 *
 *  It's recommended to make only one call for one parameter
 *  to keep the code usable for all platforms.
 */
extern void flmqry(
   C08**       flmid,
   I32*        rc,
   I32*        parameter,
   void*       value);

/**
 * @brief Set extended FLAMFILE attributes
 *
 * #flmset() sets parameter that open functions do not support.
 * It must be called before #flmopd() and/or #flmopf(). A later call will
 * fail with return code 90.
 *
 * Note: In opposite to the other function calls the return code
 * @p rc was expanded into two words (2 x 4 byte). The
 * first word is still the return code, the second word is the
 * info code. The info code is the parameter in error on return.
 * If the parameter ID unknown the info code 91# will be set.
 *
 * Besides #FLMSET_CRYPTOMODE and #FLMSET_SECUREINFO extended attributes
 * are only meaningful on the mainframe.
 *
 * @see #flmset_parameter and #flmqry()
 *
 * @param [in]    flmid       POINTER   Identifies the FLAMFILE for which the function is
 *                                      executed. It is set by the #flmopn() function and must not be
 *                                      changed until calling #flmcls().
 * @param [out]   rc          INTARY2   Return code and info code
 * @param [in]    parameter   INTEGER   Identifies the #flmset_parameter
 * @param [in]    value       POINTER   Will be used to set the specified @p parameter
 *
 * Note:
 *  Only on z/OS multiple parameter/value pairs can be set
 *  in one call. It is necessary to mark the end of the
 *  parameter list! Most compilers do it automatically, but
 *  in Assembler the last parameter address has to be
 *  flagged: A(X'80000000')+VALUEn).
 *
 *  It's recommended to make only one call for one parameter.
 *  to keep the code usable for all platforms.
 */
extern void flmset(
   C08**       flmid,
   I32*        rc,
   I32*        parameter,
   void*       value);

/** @} */
/**********************************************************************/

/*! @cond PRIVATE */

extern void flmrdmod(C08** flmid,I32* rc,I32* modus);
extern void flmrdblh(C08** flmid,I32* rc,I32* hdrtyp,I32* modus);
extern void flmgsh(C08** flmid,I32* rc,I32* hdrlen,C08* header);
extern void flmpsh(C08** flmid,I32* rc,I32* hdrlen,C08* header,I32* cont);
extern void flmqsh(C08** flmid,C08* system,C08* header,I32* filtyp,I64* filsiz,I32* dirblk);
extern void flgetmod(C08** flmid,I32* rc,I32* mode);
extern void flgetenc(C08** flmid,I32* rc,I32* cmpmod,I32* encmod);
extern void flgetcmp(C08** flmid,I32* rc,I32* cmpmod);
extern void flsetenc(C08** flmid,I32* rc,I32* cmpmod,I32* encmod);
extern void flgetsmd(C08** flmid,I32* rc,I32* splmod);
extern void flgetsnr(C08** flmid,I32* rc,I32* splnbr);
extern void flgetssz(C08** flmid,I32* rc,I32* splsiz);
extern void flsetsmd(C08** flmid,I32* rc,I32* splmod);
extern void flsetsnr(C08** flmid,I32* rc,I32* splnbr);
extern void flsetssz(C08** flmid,I32* rc,I32* splsiz);
extern void flsetpsp(C08** flmid,I32* rc,I32* prispc);
extern void flsetssp(C08** flmid,I32* rc,I32* secspc);
extern void flsetvol(C08** flmid,I32* rc,C08* volser);
extern void flsetunt(C08** flmid,I32* rc,C08* unit);
extern void flsetdcl(C08** flmid,I32* rc,C08* datcls);
extern void flsetscl(C08** flmid,I32* rc,C08* srgcls);
extern void flsetmcl(C08** flmid,I32* rc,C08* mgmcls);
extern void flsetdst(C08** flmid,I32* rc,I32* dspsta);
extern void flsetdnr(C08** flmid,I32* rc,I32* dspnrm);
extern void flsetdab(C08** flmid,I32* rc,I32* dspabo);
extern void flsetsci(C08** flmid,I32* rc,I32* secinf);

/**********************************************************************/

#ifdef FL4REC_VERSION2

extern void flmopn2(
   void      **hdl,
   I32        *rc,
   I32        *lstpar,
   I32        *opmode,
   C08        *filename,
   void       *connection,
   I32        *statis,
   void       *pvFlmLog,
   void       *pvFlmTrc);

extern void flmopd2(
   void      **hdl,
   I32        *rc,
   I32        *lstpar,
   I32        *namelen,
   C08        *filename,
   I32        *org,
   I32        *recf,
   I32        *recs,
   U08        *recdel,
   FKD        *keydesc,
   I32        *blks,
   I32        *cldisp,
   I32        *dev);

extern void flmopf2(
   void      **hdl,
   I32        *rc,
   I32        *version,
   I32        *flcode,
   I32        *modus,
   I32        *maxbuf,
   I32        *header,
   I32        *maxrec,
   FKD        *keydesc,
   I32        *blkmode,
   U08        *exk20,
   U08        *exd20);

extern void flmflu2(
   void      **hdl,
   I32        *rc,
   U32        *cputime,
   U32        *recin,
   U64        *piBytCnt,
   U32        *recout,
   U64        *piCmpByt);

extern void flmeme2(
   void      **hdl,
   I32        *rc,
   U32        *cputime,
   U32        *recin,
   U64        *piBytCnt,
   U32        *recout,
   U64        *piCmpByt);

extern void flmdel2(
   void**      hdl,
   I32*        rc);

extern void flmfky2(
   void**      hdl,
   I32*        rc,
   I32*        keylen,
   U08*        record,
   I32*        checkmod);

extern void flmfrn2(
   void**      hdl,
   I32*        rc,
   I32*        recno,
   I32*        checkmod);

extern void flmgky2(
   void**      hdl,
   I32*        rc,
   I32*        reclen,
   U08*        record,
   I32*        buflen);

extern void flmgrn2(
   void**      hdl,
   I32*        rc,
   I32*        reclen,
   U08*        record,
   I32*        buflen,
   I32*        recno);

extern void flmgtr2(
   void**      hdl,
   I32*        rc,
   I32*        reclen,
   U08*        record,
   I32*        buflen);

extern void flmiky2(
   void**      hdl,
   I32*        rc,
   I32*        reclen,
   U08*        record);

extern void flmlcr2(
   void**      hdl,
   I32*        rc,
   I32*        reclen,
   U08**       recptr);

extern void flmpky2(
   void**      hdl,
   I32*        rc,
   I32*        reclen,
   U08*        record);

extern void flmupd2(
   void**      hdl,
   I32*        rc,
   I32*        reclen,
   U08*        record);

extern void flmcls2(
   void      **hdl,
   I32        *rc,
   U32        *cputime,
   U32        *recin,
   U64*        piBytCnt,
   U32        *recout,
   U64*        piCmpByt,
   const U32   isWrite,
   const C08*  pcFilNam,
   const U32   isRemove,
   const U32   isFilDmy,
   const I64   siModTim,
   const I64   siAcsTim,
   const U32   isExtAtr,
   const U32   uiExtAtr);

extern void flmghd2(
   void      **hdl,
   I32        *rc,
   I32        *namelen,
   C08        *filename,
   I32        *org,
   I32        *recf,
   I32        *recs,
   U08        *recdel,
   FKD        *keydesc,
   I32        *blks,
   I32        *prnctr,
   C08        *system);

extern void flmphd2(
   void      **hdl,
   I32        *rc,
   I32        *namelen,
   C08        *filename,
   I32        *org,
   I32        *recf,
   I32        *recs,
   U08        *recdel,
   FKD        *keydesc,
   I32        *blks,
   I32        *prnctr,
   C08        *system,
   I32        *cont);

extern void flmguh2(
   void      **hdl,
   I32        *rc,
   I32        *hdrlen,
   C08        *header);

extern void flmpuh2(
   void      **hdl,
   I32        *rc,
   I32        *hdrlen,
   C08        *header);

extern void flmpwd2(
   void      **hdl,
   I32        *rc,
   U32        *pwdlen,
   C08        *passwd);

extern void flmkme2(
   void      **hdl,
   I32        *rc,
   U32        *kmclen,
   U08        *kmc,
   const U32  *liblen,
   const C08  *lib,
   const U32  *fuclen,
   const C08  *fuc,
   const U32  *parlen,
   const C08  *par,
   U32        *msglen,
   C08        *msg,
   U32        *inflen,
   C08        *inf);

extern void flmpos2(
   void      **hdl,
   I32        *rc,
   I32        *pos);

extern void flmget2(
   void      **hdl,
   I32        *rc,
   I32        *reclength,
   U08        *record,
   I32        *buflength);

extern void flmloc2(
   void      **hdl,
   I32        *rc,
   I32        *reclength,
   U08       **record);

extern void flmput2(
   void      **hdl,
   I32        *rc,
   I32        *reclength,
   U08        *record);

extern void flmrdmod2(
   void      **hdl,
   I32        *rc,
   I32        *modus);

extern void flmrdblh2(
   void      **hdl,
   I32        *rc,
   I32        *hdrtyp,
   I32        *modus);

extern void flmgsh2(
   void      **hdl,
   I32        *rc,
   I32        *hdrlen,
   C08        *header);

extern void flmpsh2(
   void      **hdl,
   I32        *rc,
   I32        *hdrlen,
   C08        *header,
   I32        *cont);

extern void flmqry2(
   void      **hdl,
   I32        *rc,
   I32        *parameter,
   void       *value);

extern void flmset2(
   void      **hdl,
   I32        *rc,
   I32        *parameter,
   void       *value);

extern void flmqsh2(
   void      **hdl,
   C08        *system,
   C08        *header,
   I32        *filtyp,
   I64        *filsiz,
   I32        *dirblk);

extern const char* flgetrn2(void **hdl);

extern void flgetmod2(
   void      **hdl,
   I32        *rc,
   I32        *mode);

extern void flgetenc2(
   void      **hdl,
   I32        *rc,
   I32        *cmpmod,
   I32        *encmod);

extern void flgetcmp2(
   void      **hdl,
   I32        *rc,
   I32        *cmpmod);

extern void flsetenc2(
   void      **hdl,
   I32        *rc,
   I32        *cmpmod,
   I32        *encmod);

extern void flsetsci2(
   void      **hdl,
   I32        *rc,
   I32        *secinf);

extern void flgetsmd2(
   void      **hdl,
   I32        *rc,
   I32        *splmod);

extern void flgetsnr2(
   void      **hdl,
   I32        *rc,
   I32        *splnbr);

extern void flgetssz2(
   void      **hdl,
   I32        *rc,
   I32        *splsiz);

extern void flsetsmd2(
   void      **hdl,
   I32        *rc,
   I32        *splmod);

extern void flsetsnr2(
   void      **hdl,
   I32        *rc,
   I32        *splnbr);

extern void flsetssz2(
   void      **hdl,
   I32        *rc,
   I32        *splsiz);

extern void flsetpsp2(
   void      **hdl,
   I32        *rc,
   I32        *prispc);

extern void flsetssp2(
   void      **hdl,
   I32        *rc,
   I32        *secspc);

extern void flsetvol2(
   void      **hdl,
   I32        *rc,
   C08        *volser);

extern void flsetunt2(
   void      **hdl,
   I32        *rc,
   C08        *unit);

extern void flsetdcl2(
   void      **hdl,
   I32        *rc,
   C08        *datcls);

extern void flsetscl2(
   void      **hdl,
   I32        *rc,
   C08        *srgcls);

extern void flsetmcl2(
   void      **hdl,
   I32        *rc,
   C08        *mgmcls);

extern void flsetdst2(
   void      **hdl,
   I32        *rc,
   I32        *dspsta);

extern void flsetdnr2(
   void      **hdl,
   I32        *rc,
   I32        *dspnrm);

extern void flsetdab2(
   void      **hdl,
   I32        *rc,
   I32        *dspabo);

extern void* flgetfil2(void** hdl);

extern C08* flprncon2(void** hdl, const U32 uiSize, C08* pcBuffer);

extern void flmerr2(
   void      **hdl,
   I32        *rc,
   I32        *msglen,
   const C08 **errmsg);

#ifdef __DEBUG__
extern int flchkopncls2(void);
#endif

#endif /*FL4REC_VERSION2*/
/**********************************************************************/

#endif /* INC_FL4REC_H */

#ifdef __cplusplus
   }
#endif
 /*! @endcond */

/**********************************************************************/
