/**
 * @file   FLCRECLB.h
 * @brief  Specification for the FLUC record interface
 * @author limes datentechnik gmbh
 * @date   02.03.2016
 * @copyright limes datentechnik (R) gmbh
 *
 * @mainpage FLUC Record Interface
 *
 * This interface provides record- or element-oriented sequential read
 * and write access to original files. Original files can be binary, text
 * or XML data sets as well as GZIP-, BZIP2-, XZ-, PGP-, ZIP, FLAM4 files
 * or any other kind of original local or remote data set format supported
 * by FLAM. It includes all conversion and formatting capabilities of the
 * Frankenstein Limes Universal Converter (FLUC). These conversion
 * capabilities are also available as an in-memory variant (FCRCONV/RUNV/FINV)
 * without file I/O. The COBOL sample 'SOFCRIPS' shows how it can be used
 * to convert an XML transaction to a copy book (second FCRCONP call) for
 * SEPA instant payments.
 *
 * The interface provides functions similar to the record-oriented file
 * I/O functions used with COBOL or PL/1 on mainframes. Only the function for
 * opening files differs in that it takes a file, a format and a state string.
 * You can specify them using the syntax of our command line (FLCL). The FLAM
 * return code (rtc) can be mapped to a message with #FCRMSG() and the complete
 * FLAM error trace can be fetched with #FCRTRC(). Additionally, this interface
 * provides functions for getting help and syntax information for the file
 * and format string parameters.
 *
 * There is also a logging facility which causes log messages to be
 * collected in memory. These log messages can be queried when desired.
 *
 * Additionally, a set of conversion functions is available, which can be used
 * when accessing elements (format.element()), for example to parse XML documents
 * in COBOL or PL/I. An example can be found in @ref XMLEXMPL "a section below".
 *
 * There are also function for hash, MAC and HMAC calculations, base encoding
 * and decoding and a few other help function for example to determine the
 * amount of processed bytes or units (records or blocks).
 *
 * @section MFEDZ Micro Focus EDZ support
 * The interface does support Micro Focus Enterprise Server for SystemZ (MF-EDZ).
 * It is usable on Linux and Windows, 32 and 64 bit systems with Cobol and
 * PL1.
 *
 * There are some special functions implemented, mainly to provide a
 * possibility for a workaround concerning the native pointer handling bug
 * if the AMODE directive is required. In this case (e.g AMODE=31), the native
 * pointer provided by the locate functions (#FCRLOC(), #FCRCONP(), ...) is not
 * usable with the ADDRESS OF statement (invalid pointer value). The pointer
 * is mapped with the corresponding MF-EDZ routine, but the pointer is still in
 * native format. For this case, the function #FCRCPY() is provided to implement
 * a transparent workaround.
 *
 * In the opposite direction, i.e. when writing, #FCRPTR() converts a local
 * AMODE=31 pointer to a native pointer to allow, for example, structures
 * with length and pointer for variable length formats in table support.
 *
 * Often to AMODE=31 is only required to determine job or system names
 * from control blocks. In this case #FCRSYM() can be used for it.
 *
 * 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>
 * <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>
 * <dl>
 * <dt>FLAM4MF_STATIC_SYSVAR=unset</dt><dd>
 *      No static system variables are read into the environment.</dd>
 * <dt>FLAM4MF_STATIC_SYSVAR=filename</dt><dd>
 *      Static system variables are read from <code>filename</code> into the environment (for #FCRSYM()).</dd>
 * </dl>
 * <dl>
 * <dt>FLAM4MF_DYNAMIC_SYSVAR=unset</dt><dd>
 *      No dynamic system variables are read into the environment.</dd>
 * <dt>FLAM4MF_DYNAMIC_SYSVAR=filename</dt><dd>
 *      Dynamic system variables are read from <code>filename</code> into the environment (for #FCRSYM()).<br>
 *      The second file name can be used in conjunction with the JCL User Exit to provide the dynamic system variables for #FCRSYM().<br>
 *      The implementation can be done with this interface using #FCROPN(fomat.record() write.text(file=filename ccsid=local))</dd>
 * </dl>
 *
 * @section ITFSTD Interface standards
 * Each function is provided as a separate load module. All parameters
 * are call-by-reference and function do not have a return value, except
 * few help functions like hash calculation, etc. All parameters must be
 * specified. There is no support to determine a variable amount of
 * parameter. There are mainly 4 types of parameters:
 *
 * <pre>
 * POINTER:   pointer to an address (usually 32 (PIC S9(9) COMP or BIN FIXED(31,0)) or 64 bit)
 * INTEGER:   pointer to a 32 bit number in two's complement (PIC S9(9) COMP or BIN FIXED(31,0))
 * STRING[x]: pointer to a byte (8 bit) array of length x (PIC X(x) or CHAR(x))
 * STRING:    pointer to a variable length byte (8 bit) array (PIC X(n) CHAR(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. Only the function #FCRCNT()
 * returns a 64 bit integer value for the amount of processed data.
 *
 * Input strings may be null-terminated in which case the corresponding
 * length pointer may be NULL. If a length value is provided, the string
 * may not be null-terminated. All output strings are null-terminated.
 * The output length is set only if the pointer is not NULL. This is only
 * valid for printable string output. Binary byte arrays are not null-terminated.
 * The return code parameter can be a NULL pointer in which case no return
 * value is set.
 *
 * @section FILDEF File definition and format strings
 * When reading: Through the file definition string, you specify how the
 * read operation interprets and transforms your original data to produce
 * an internal neutral FLAM5 element list from it. The format string
 * describes how this element list will then be formatted into a sequence
 * of records. You also have the option of getting the raw elements
 * by specifying element formatting in the format string
 * (<code>format.element()</code>). An optional state string is returned
 * when opening a file for reading which contains some metadata about
 * the contents.
 *
 * When writing: The format string defines how the provided records or
 * elements will be formatted into a neutral FLAM5 element list. The file
 * definition string describes how this element list will be written to
 * a file. The state string can be used to set additional metadata that
 * provides FLUC with additional information about the data. The
 * converted data can be written to multiple targets in parallel by
 * specifying multiple I/Os through the OUTPUT object. It is possible to
 * specify multiple WRITE overlays or OUTPUT objects to write the same
 * data in different formats to different files, reading the input only
 * once.
 *
 * @section MBRWRT Write of multiple members to the same open file
 * To write more than one member to a ZIP archive or FLAMFILE the function
 * #FCRNEWM() can be used. This function does a reopen of the open file
 * to add a new member. This is a lot faster than to close the file and
 * open it again with the append switch for the next member.
 *
 * This will work for all kind of files (not only archives) and could
 * result in a concatenation or a bouquet of further files depending on
 * the input-output name mapping specified in the write string.
 *
 * The #FCROPN() describes the first member and for all other members of
 * this file you must call #FCRNEWM(). This functions allows you to
 * provide a new format and state string. If the new member is formated like
 * the old member, the format string can be NULL. In this case the current
 * formatting will be reused. Additionally you have the possibility to receive
 * the interim statistics buffer.
 *
 * Here is the typical program sequence in pseudo code:
 * <pre>
 *    FCROPN(&hdl,"write.text(... archive.zip(member='[name]'))","format.text()","state(orgf='first.member.txt')");
 *    if (hdl==NULL) exit(1);
 *    FCRPUT(&hdl,...);
 *    ...
 *    FCRPUT(&hdl,...);
 *
 *    FCRNEWM(&hdl,"format.record()","state(orgf='second.member.txt')");
 *    if (hdl==NULL) exit(2);
 *    FCRPUT(&hdl,...);
 *    ...
 *    FCRPUT(&hdl,...);
 *
 *    FCRNEWM(&hdl,NULL,"state(orgf='third.member.txt')");
 *    if (hdl==NULL) exit(3);
 *    ...
 *    ...
 *    ...
 *    FCRCLS(&hdl);
 * </pre>
 *
 * The member definition for the archive should contain an input output
 * name mapping, because the state string for each new member provides the
 * original file name (ORGF), which is mapped into the member name of the
 * archive.
 *
 * @section FORMAT Formatting
 * When reading or writing, you can define how to format the data (binary,
 * character, text, xml, ...), use different conversions (Base64, OpenPGP,
 * GZIP, CHRSET, ...) executed sequentially and different kinds of I/O
 * methods (block, record, text, FLAM4, ...). This means that you can read
 * and write compressed, encrypted and encoded files, where you can change
 * the character set and other things as part of the write and read operation.
 *
 * Through the format string, you specify how the data is transformed into
 * a sequential list of records or elements. For example, if the data
 * contains text, you can specify which character set the output should
 * be in and so on. Please use the interactive help function #FCRHLP()
 * for more information.
 *
 * Beside record (default) and element formatting, you can also choose
 * binary, character, text and XML formatting. An #FCRGET() call returns
 * the formatted content of one element. For example, a text record with
 * delimiter or a binary block. Please be aware, that such a block could
 * potentially contain up to 1 GB of data.
 *
 * For read operations, you can use the auto detection capabilities of
 * FLUC.
 *
 * <pre>
 * FCROPN("read.file='filename'","format.record()")
 * </pre>
 *
 * This results in any kind of file (encoded, encrypted and/or
 * compressed) being converted to records. If the content is XML, then
 * the XML data is pretty printed into records. If it is text, then the
 * data is parsed based on the containing delimiters. If it is binary
 * and record lengths are detected, then the records are provided one by
 * one. If it is binary and no record lengths are known or detected, then
 * the data is wrapped into records.
 *
 * @subsection FMTREC Record formatting
 * Record formatting is the default format. If the format string does not
 * start with <code>format</code>, the format string is expected to be
 * the inner portion of <code>format.record()</code>. So, the format
 * string <code>reclen=80</code> is equivalent to
 * <code>format.record(reclen=80)</code>. Record formatting will result
 * in the expected results for a record-oriented I/O interface.
 *
 * @subsection FMTELM Element formatting
 * FLAM5 elements are parsed data elements with a type, a length, a value
 * and more. If the element data contains printable characters, then
 * these characters are encoded in UTF-8 by default, but can also be
 * converted as needed.
 *
 * With element formatting, you can read and write a serialized form of
 * FLAM5 elements. For example, it can be used to tokenize an XML document
 * and read these tokens (elements) for further processing. The
 * serialized element format (version 0) is described by the structure
 * #FlmElmRec0. It basically consists of a set of 32 bit integers
 * followed by element data and metadata.
 *
 * @subsection FMTOTH Other formatting modes
 * The formatting modes binary, character, text or XML can also be used.
 * The converted element data field is returned as a record, which could
 * be a line of a text with a delimiter or the whole chunk of binary data
 * as a block. These formatting modes are designed to be used via the byte
 * interface, but available on the record interface as well. Be careful
 * when using these modes as results could be not as expected.
 *
 * @section ELMCNV Element conversion
 * When using element formatting, you can use several individual element
 * data conversion modules for per-element data conversion. If no converter
 * is used, the element data is simply copied into application memory to
 * build the element structure (#FlmElmRec0). A set of functions with 'v'
 * at the end of the function name can be used to set a custom element data
 * converter. A converter must be opened before using it, which can done by
 * calling #FCROPNV with a corresponding conversion string. The conversion
 * string describes how the data is converted from the neutral format of a
 * FLAM5 element to the representation in the application memory (when
 * reading) or how the application memory must be interpreted to form the
 * corresponding neutral FLAM5 element data type (when writing). The functions
 * #FCRGETV, #FCRLOCV and #FCRPUTV accept an additional conversion handle as
 * parameter which is obtained from #FCROPNV() to replace the default/standard
 * conversion. The #FCRGETV, #FCRLOCV and #FCRPUTV functions require to know the
 * data format that will be read in advance, which is not always the case.
 * Instead, you can also use the regular #FCRGET, #FCRLOC and #FCRPUT functions
 * and use the function #FCRCONV to convert the data, if needed. In fact,
 * this function works on arbitrary data and may also be used independently.
 *
 * There is no limit on the amount of element converters that can be
 * opened. The output length of most converts can be controlled in two
 * ways: By passing appropriate length values in the conversion string or
 * or by passing a buffer of appropriate length at call time.
 *
 * The converter handle must be closed with #FCRCLSV to release all
 * associated resources.
 *
 * Some usage scenarios for element converters:
 * * Selective character conversion
 * * Number conversion from/to BCD/binary integer
 * * Removal of whitespace
 *
 * @section FMTTAB Table support
 * With version 5.1.16 of FLAM the table support was introduced. For the
 * record interface you can activate an end of table support if you read
 * from a file (file string). If you activate ENDOFT in the format string
 * at write and use #FCRSTN() in conjunction with an output file name containing
 * [table], then you can split the data in different files. But at read you
 * must now handle the FLMRTC_EOT error like an FLMRTC_EOF. If you don't get
 * data the reason could be EOF or EOT. With EOT the next read gives the
 * records conform to the new table.
 * At EOF you get still no data and still EOF. If you activate ENDOFT at read
 * you can use the new function #FCRGTN() to get the name of the current
 * table after #FCROPN() or after an EOT was signalled. This can be used
 * to interpret the data correctly if more than one table is in a file.
 * If you want to write more than one table to a file, you can work with the
 * table format detection, but normally it is better to define the
 * table format with the new function #FCRSTN(), before you provide the
 * data. If you set the table name the data must match this table format
 * (row specification). The table format detection is disabled if #FCRSTN()
 * is used. You can reactivate the automatic table detection at write by
 * calling #FCRGTN().
 *
 * @section ENVVAR Environment variables
 * For all default character conversions, it is useful to set the environment
 * variable LANG. Other used environment variables of FLAM can be found
 * in the FLCL manual. With version 5.1.19 a new function was introduced
 * (#FCRENV()) to load the FLAM environment . This function can be used
 * before the first API call to establish the same environment used by
 * FLAM utilities, subsystems and so on. This give the application
 * developer the possibility to adjust the environment before the first
 * real call is done. Until version 5.1.18, each opening function has
 * read the system variables on z/OS. This is now part of the #FCRENV()
 * function to give complete control about the environment to users of
 * the API. To fetch a symbol from the environment, the function
 * #FCRSYM() can be used.
 *
 * @section CODPGE Special EBCDIC code page support
 * On system using EBCDIC a special support for critical punctuation
 * characters was implemented (see FLCL manual). This support converts
 * the several punctuation character from a certain EBCDIC code page
 * to the local character set defined over the LANG variable (if LANG
 * not defined the default is 1047). Below you can find the list of
 * character with different code points in the different supported EBCDIC
 * code pages, which are part of the first 128 Unicode code points.
 *
 * <pre>
 *    CRITICAL PUNCTUATION CHARACTERS:
 *       ! $ # @ [ \\ ] ^ ` { | } ~
 *    SUPPORTED EBCDIC CODE PAGES FOR COMMAND ENTRY:
 *       "IBM-1140","IBM-1141","IBM-1142","IBM-1143",
 *       "IBM-1144","IBM-1145","IBM-1146","IBM-1147",
 *       "IBM-1148","IBM-1149","IBM-1153","IBM-1154",
 *       "IBM-1156","IBM-1122","IBM-1047","IBM-924",
 *       "IBM-500","IBM-273","IBM-037","IBM-875","IBM-424",
 *       "IBM-277","IBM-278","IBM-280","IBM-284","IBM-285",
 *       "IBM-297","IBM-871","IBM-870","IBM-1025","IBM-1112",
 *       "IBM-1157"
 * </pre>
 *
 * This conversion is required to interpret the command syntax correctly.
 * These CLP strings are the major part used by this interface. To work
 * with this API the user must build such CLP string. For this often
 * literals are used. On EBCDIC systems you can define in which CCSID
 * (code page) the literals are provided by the compiler. For example,
 * in COBOL the default, if the CODEPAGE parameter not defined, is 1140.
 *
 * Your application could get variables from outside (e.g. file names)
 * in the local character set (e.g. 1141). Your literals are in 1140 and
 * you must build a CLP string with literals and variables. To support
 * this kind of inconsistent code pages (since version 5.1.19 of FLAM)
 * escape sequences (\&xxx;) the CCSID areas (\&nnnn;...\&nnnn;) are supported
 * (see FLCL manual). Below you can find an examples for a CLP command
 * string how to use it.
 *
 * <pre>
 *     WORKING-STORAGE SECTION.
 *     01  C2-DATA                    PIC X(200)
 *            VALUE 'CONV.MEMORY(READ.CHAR(TABLE='\&TLD;.PAIN008.XMLTAB')
 *    \-            'WRITE.RECORD(TABLE='\&TLD;.PAIN008.FIXTAB'))'.
 * or
 *     WORKING-STORAGE SECTION.
 *     01  C2-DATA                    PIC X(200)
 *            VALUE '\&1140;CONV.MEMORY(READ.CHAR(TABLE='~.PAIN008.XMLTAB')
 *    \-            'WRITE.RECORD(TABLE='~.PAIN008.FIXTAB'))'.
 * </pre>
 *
 * An unsupported CCSID (e.g. 0) can be used to define the local character
 * set as code page (default case). To get an area for the literal code
 * page you must add a CCSID escape sequence (&1140;). If you have a
 * variable part, you must switch to the local character set (&0000;) or
 * the correct CCSID for this variable and if the literal continued
 * switch back to the literal CCSID (&1140;). If you need such moving
 * characters in your literals you can use the corresponding escape
 * sequence for it. Below you can find all escape sequences for the
 * critical punctuation characters.
 *
 * <pre>
 *    ! = \&EXC;   - Exclamation mark
 *    $ = \&DLR;   - Dollar sign
 *    # = \&HSH;   - Hashtag (number sign)
 *    @ = \&ATS;   - At sign
 *    [ = \&SBO;   - Square bracket open
 *    \\ = \&BSL;   - Backslash
 *    ] = \&SBC;   - Square bracket close
 *    ^ = \&CRT;   - Caret (circumflex)
 *    ` = \&GRV;   - Grave accent
 *    { = \&CBO;   - Curly bracket open
 *    | = \&VBR;   - Vertical bar
 *    } = \&CBC;   - Curly bracket close
 *    ~ = \&TLD;   - Tilde
 * </pre>
 *
 * This two features provide the possibility to build CLP strings
 * dependency on the EBCDIC code page used for literals and as local
 * or system character set.
 *
 * @section INFCMD Info command
 * The interface also provides access to the info command. #FCRINF() can
 * be used, for example, to get information about files and supported
 * CCSIDs.
 *
 * @section HASHMAC Hash, HMAC and MAC calculations with clear keys
 * The interface also provides a set of functions to calculate hash, MAC
 * and HMAC values. #FCRHASH() does everything in one call and is useful
 * for transaction processing. #FCRHINI(), #FCRHADD() and #FCRHFIN() can
 * be used to calculate the checksum over several pieces of data. A
 * sample program in Cobol using the hash function can be found in the
 * library SRCLIB(SOFCRHSH).
 *
 * @section BASEENCDEC Base encoding decoding
 * Mainly for the hash function above the interface provides a set of
 * function to encode and decode binary data. #FCRBASE() does anything
 * in one call and is useful for transaction processing. #FCRBINI(),
 * #FCRBRUN() and #FCRBFIN() can be used over several pieces of the data.
 *
 * @section CMPLNK Compile and Link
 * @subsection HOST On mainframes (z/OS, ...)
 * The interface is provided as DLL and each function of the DLL is also
 * available as separate load module.
 *
 * For dynamic linking of the load module (fetch) the hlq.FLAM.LOAD
 * library must be part of the STEPLIB concatenation. A static link in
 * COBOL or PL1 works as well with the separate load modules.
 *
 * If you link one of the load modules statically to your application
 * (each load module contains all required entries of the interface),
 * you must include the DLL import files below to resolve the missing
 * external references and set the binder option DYNAM(DLL):
 *
 * <pre>
 * hlq.FLAM.IMPORT(FLCBYT)
 * hlq.FLAM.IMPORT(FL5CORE)
 * </pre>
 *
 * To link dynamically against the DLL you must include the import DLL
 * file form the IMPORT library below:
 *
 * <pre>
 * hlq.FLAM.IMPORT(FLCRECLB)
 * </pre>
 *
 * Assembler programs need to activate the LE runtime system (PIPI) before
 * any call. The calling convention is standard OS (save area and R1
 * points to the flagged parameter list (each parameter call be
 * reference, R15 is not used (no return code))).
 *
 * We recommend to use application-specific runtime option defaults with
 * the CEEUOPT assembler language source program to establish application
 * default options. You can find the recommended runtime options as member
 * CEEUOPTx (x=3 for 31 bit and x=6 for 64 bit applications) in the
 * hlq.FLAM.SRCLIB partitioned dataset.
 *
 * @subsection OTHER On other platforms (Unix, Windows, ...)
 * The interface is only available as dynamic link library (DLL) or
 * shared object (SO). You can link it dynamically, statically or load
 * the library at runtime (dlopen(), LoadLibrary()) with the common
 * DLL/SO mechanism of your operating system.
 *
 * @section SAMPLE Sample programs
 * A sample program in C with name SCFCRCPY can be found as part of the
 * installation package for mainframe systems in the library SRCLIBC(SCFCRCPY),
 * with the corresponding compile and link step in JOBLIB(SBUILD).
 * For other platforms (Windows, UNIX) the sample program source of SCFCRCPY
 * is located in the <code>sample</code> directory and the compile and link
 * procedures can be found in the Makefile of the same directory.
 *
 * Additionally, COBOL samples with name SOFCRGET (uses FCRGET to read any
 * kind of supported file format and writes the EBCDIC records to a host dataset),
 * SOFCRXML (reads a clear or encoded XML file and writes the content as dump),
 * SOFCREXV (parses an XML file based on several element converters and does
 * operations with it) and SOFCRINT/FLT (reads records from a dataset, converts
 * the strings to several different integer/floats values and calculates the sum)
 * can be found in SRCLIB(SOFCRGET/SOFCRXML/SOFCREXV/SOFCRINT). How to call our
 * LE requiring entries in a LE-less assembler program using CEEPIPI the sample
 * SAFCRGET is provided. The corresponding compile and link procedures are also
 * located as separate steps in JOBLIB(SBUILD). SOFCRGET/INT uses record formatting
 * and SOFCRXML/EXV uses element formatting. SPxxxxxx are the corresponding samples
 * in PL1.
 *
 * @section XMLEXMPL Example for reading XML files with COBOL
 * This simple XML document contains some strings and integer numbers within
 * some nested XML tags:
 *
 * <pre>
 * \<foo>
 *    \<address>
 *       \<name>  Max Herre        \</name>
 *       \<number>    13           \</number>
 *    \</address>
 * \</foo>
 * </pre>
 *
 * The file (FCROPN) can be opened with the file and format strings below.
 * In this example, we use a static allocation.
 * <pre>
 * FILE-STRING:        "read.xml(file='DD:INPUT' nocmnt)"
 * FORMAT-STRING:      "format.element()"
 * </pre>
 * If the file is compressed/encrypted/encoded in a supported format, it
 * is decoded first. Character set conversion takes place automatically,
 * if necessary. The internal neutral representation of XML elements is
 * always a UTF-8 string. The nocmnt flag suppresses XML comments from
 * the document while reading.
 *
 * We need a couple of converters which are created with FCROPNV and an
 * appropriate conversions string:
 *
 * <pre>
 * CONVERSION-STRING1: "write.string(chrset(ccsid=DEFAULT))"
 * CONVERSION-STRING2: "write.string(chrset(ccsid=DEFAULT whitespace=collapse) padding=right)"
 * CONVERSION-STRING3: "conv.integer(from(format.str()) to(format.bin(signed)))"
 * </pre>
 *
 * The first converter converts an element to a string with the system's
 * default character set. This is used to convert the XML tag names in
 * order to be able to compare them in our code.
 *
 * The second converter also converts an element to a string with default
 * CCSID, but additionally removes leading, trailing and duplicate
 * successive whitespace and pads the string on the right to fill our
 * output buffer that we pass to the interface functions. This is used to
 * convert the "name" field of the document and store it in a fixed-length
 * data structure.
 *
 * The last converter is used to convert the string representation of a
 * number to a signed number in two's complement format in system
 * endianness. The output buffer passed must be 1, 2, 4 or 8 bytes long
 * as these are the supported binary integer lengths.
 *
 * Now that everything is setup, we can start reading XML elements with
 * FCRLOC. If we encounter the start of an XML tag, we use the first
 * converter to retrieve the tag name in our local charset and do a
 * string compare. For the string data in the "name" tag, we use the
 * second converter to store it in a COBOL data structure (COPYBOOK).
 * If the element contains a number, we use the number converter to
 * store the number as 32 bit signed bianry integer as "PIC 9(8) COMP".
 *
 * Here is the example for reading the above XML file in a kind of
 * simplified pseudo code:
 *
 * <pre>
 * pvFil=FCROPN("read.xml(file='DD:INPUT' nocmnt)","format.element()")
 * pvKyw=FCROPNV("write.string(chrset(ccsid=DEFAULT))")
 * pvStr=FCROPNV("write.string(chrset(ccsid=DEFAULT whitespace=collapse) padding=right)")
 * pvInt=FCROPNV("conv.integer(from(format.str(marker=period)) to(format.bin(signed)))")
 * uiTyp=FCRLOCV(pvFil,acKyw,pvKyw)
 * if (uiTyp=STARTELM && acKyw=="foo") then begin
 *    uiTyp=FCRLOC(pvFil)
 *    if (uiTyp==ENDSTARTELM) then begin
 *       uiTyp=FCRLOCV(pvFil,acKyw,pvKyw)
 *       if (uiTyp=STARTELM && acKyw=="address") then begin
 *          uiTyp=FCRLOC(pvFil)
 *          if (uiTyp==ENDSTARTELM) then begin
 *             if (uiTyp=STARTELM && acKyw=="name") then begin
 *                uiTyp=FCRLOC(pvFil)
 *                if (uiTyp==ENDSTARTELM) then begin
 *                   uiTyp=FCRLOC(pvFil,acDat)
 *                   if (uiTyp=DATA) then begin
 *                      FCRCONV(pvStr,acDat,32,CB.NAME)
 *                      uiTyp=FCRLOCV(pvFil,acKyw,pvKyw)
 *                      if (uiTyp!="ENDELM" && acKyw!="name")
 *                         ERROR
 *                      end
 *                   end
 *                end
 *             end
 *             uiTyp=FCRLOCV(pvFil,acKyw,pvKyw)
 *             if (uiTyp=STARTELM && acKyw=="number") then begin
 *                uiTyp=FCRLOC(pvFil)
 *                if (uiTyp==ENDSTARTELM) then begin
 *                   uiTyp=FCRLOC(pvFil,acDat)
 *                   if (uiTyp=DATA) then begin
 *                      FCRCONV(pvInt,acDat,4,CB.NUMBER)
 *                      uiTyp=FCRLOCV(pvFil,acKyw,pvKyw)
 *                      if (uiTyp!="ENDELM" && acKyw!="name")
 *                         ERROR
 *                      end
 *                   end
 *                end
 *             end
 *          end
 *       end
 *    end
 * end
 * FCRCLSV(pvInt)
 * FCRCLSV(pvStr)
 * FCRCLSV(pvKyw)
 * FCRCLS(pvFil)
 * </pre>
 *
 * FCRLOC returns a pointer to the neutral FL5 element. Alternatively,
 * FCRGET can be used to retrieve a copy of the element data written to
 * an application-provided buffer. The corresponding functions with a 'V'
 * at the end (FCRLOCV/GETV) provide FCRLOC/FCRGET functionality, but
 * with implicit data conversion by passing an open converter handle
 * (created with FCROPENV). If the type of data is unknown in advance,
 * the data can also be read with FCRLOC/FCRGET first, and then converted
 * explicitly with FCRCONV. This function performs explicit conversions
 * on arbitrary buffers. Therefore, it is not limited to data processed by
 * the record interface.
 **********************************************************************/

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

#ifndef INC_FLCRECLB_H
#define INC_FLCRECLB_H
 /*! @endcond */

#include "FLMRTC.h"
#include "FLMDEF.h"

 /*********************************************************************/
 /*! @cond PRIVATE */

#ifndef MF_SUPPORT
#  define FCR_READ_FILE               FLC_READ_FILE
#  define FCR_READ_FORMAT             FLC_READ_FORMAT
#  define FCR_WRITE_FILE              FLC_WRITE_FILE
#  define FCR_WRITE_FORMAT            FLC_WRITE_FORMAT
#  define FCR_CONV_READ               FLC_CONV_READ
#  define FCR_CONV_WRITE              FLC_CONV_WRITE
#  define FCR_INPUT_FILE              FLC_INPUT_FILE
#  define FCR_OUTPUT_FILE             FLC_OUTPUT_FILE
#  define FCR_INFO                    FLC_INFO
#  define FCR_STATE                   FLC_STATE
#  define FCR_LOG                     FLC_LOG
#endif

#ifdef MF_SUPPORT
#  define PFIX(n) _mf_ ## n
#  define FCRVSN  PFIX(FCRVSN)
#  define FCRABO  PFIX(FCRABO)
#  define FCRLIC  PFIX(FCRLIC)
#  define FCRHLP  PFIX(FCRHLP)
#  define FCRSYN  PFIX(FCRSYN)
#  define FCRMSG  PFIX(FCRMSG)
#  define FCRTRC  PFIX(FCRTRC)
#  define FCRINF  PFIX(FCRINF)
#  define FCROPN  PFIX(FCROPN)
#  define FCRNEWM PFIX(FCRNEWM)
#  define FCROPNV PFIX(FCROPNV)
#  define FCRPUT  PFIX(FCRPUT)
#  define FCRPUTV PFIX(FCRPUTV)
#  define FCRCNT  PFIX(FCRCNT)
#  define FCRFLU  PFIX(FCRFLU)
#  define FCRGET  PFIX(FCRGET)
#  define FCRGETV PFIX(FCRGETV)
#  define FCRLOC  PFIX(FCRLOC)
#  define FCRLOCV PFIX(FCRLOCV)
#  define FCRPRV  PFIX(FCRPRV)
#  define FCRCONV PFIX(FCRCONV)
#  define FCRRUNV PFIX(FCRRUNV)
#  define FCRFINV PFIX(FCRFINV)
#  define FCRCONP PFIX(FCRCONP)
#  define FCRRUNP PFIX(FCRRUNP)
#  define FCRFINP PFIX(FCRFINP)
#  define FCRCLS  PFIX(FCRCLS)
#  define FCRCLSV PFIX(FCRCLSV)
#  define FCRCLR  PFIX(FCRCLR)
#  define FCRGFN  PFIX(FCRGFN)
#  define FCRGTN  PFIX(FCRGTN)
#  define FCRSTN  PFIX(FCRSTN)
#  define FCRENV  PFIX(FCRENV)
#  define FCRSYM  PFIX(FCRSYM)
#  define FCROPNL PFIX(FCROPNL)
#  define FCRGETL PFIX(FCRGETL)
#  define FCRCPYL PFIX(FCRCPYL)
#  define FCRCLRL PFIX(FCRCLRL)
#  define FCRCLSL PFIX(FCRCLSL)
#  define FCRCPY  PFIX(FCRCPY)
#  define FCRPTR  PFIX(FCRPTR)
#  define FCRHASH PFIX(FCRHASH)
#  define FCRHINI PFIX(FCRHINI)
#  define FCRHADD PFIX(FCRHADD)
#  define FCRHFIN PFIX(FCRHFIN)
#  define FCRBASE PFIX(FCRBASE)
#  define FCRBINI PFIX(FCRBINI)
#  define FCRBRUN PFIX(FCRBRUN)
#  define FCRBFIN PFIX(FCRBFIN)
#endif
#ifdef USE_MF_SUPPORT
#  define FCRVSN  fcrvsn
#  define FCRABO  fcrabo
#  define FCRLIC  fcrlic
#  define FCRHLP  fcrhlp
#  define FCRSYN  fcrsyn
#  define FCRMSG  fcrmsg
#  define FCRTRC  fcrtrc
#  define FCRINF  fcrinf
#  define FCROPN  fcropn
#  define FCRNEWM fcrnewm
#  define FCROPNV fcropnv
#  define FCRPUT  fcrput
#  define FCRPUTV fcrputv
#  define FCRFLU  fcrflu
#  define FCRCNT  fcrcnt
#  define FCRGET  fcrget
#  define FCRGETV fcrgetv
#  define FCRLOC  fcrloc
#  define FCRLOCV fcrlocv
#  define FCRPRV  fcrprv
#  define FCRCONV fcrconv
#  define FCRRUNV fcrrunv
#  define FCRFINV fcrfinv
#  define FCRCONP fcrconp
#  define FCRRUNP fcrrunp
#  define FCRFINP fcrfinp
#  define FCRCLS  fcrcls
#  define FCRCLSV fcrclsv
#  define FCRCLR  fcrclr
#  define FCRGFN  fcrgfn
#  define FCRGTN  fcrgtn
#  define FCRSTN  fcrstn
#  define FCRENV  fcrenv
#  define FCRSYM  fcrsym
#  define FCROPNL fcropnl
#  define FCRGETL fcrgetl
#  define FCRCPYL fcrcpyl
#  define FCRCLRL fcrclrl
#  define FCRCLSL fcrclsl
#  define FCRCPY  fcrcpy
#  define FCRPTR  fcrptr
#  define FCRHASH fcrhash
#  define FCRHINI fcrhini
#  define FCRHADD fcrhadd
#  define FCRHFIN fcrhfin
#  define FCRBASE fcrbase
#  define FCRBINI fcrbini
#  define FCRBRUN fcrbrun
#  define FCRBFIN fcrbfin
#endif
 /*! @endcond */
/**********************************************************************/
 /**
  * @defgroup FUNC Functions
  * @{
  */
/**
 * @brief Retrieves the version string
 *
 * This function writes a string containing version information for
 * every used component into the @p vsn parameter. This should be used
 * in a support case.
 *
 * @param [out]     rtc    INTEGER Return code
 * @param [inout]   vsnLen INTEGER Size/length of version string (16KiB required)
 * @param [out]     vsn    STRING  Version string (is null-terminated)
 */
extern void FCRVSN(
   int*                 rtc,
   int*                 vsnLen,
   char*                vsn);

/**
 * @brief Retrieves the about string
 *
 * This function writes a string with about information for this
 * library on multiple lines and license information for used
 * external libraries into the @p abo parameter.
 *
 * @param [out]     rtc    INTEGER Return code
 * @param [inout]   aboLen INTEGER Size/length of about string (16KiB required)
 * @param [out]     abo    STRING  About string (is null-terminated)
 */
extern void FCRABO(
   int*                 rtc,
   int*                 aboLen,
   char*                abo);

/**
 * @brief Gets the license text
 *
 * This function can be used to get the current license text on multiple
 * lines. The license text defines the permissible use of this library.
 *
 * @param [out]     rtc    INTEGER Return code
 * @param [inout]   licLen INTEGER Size/length of license string
 * @param [out]     lic    STRING  Current license text (is null-terminated)
 */
extern void FCRLIC(
   int*                 rtc,
   int*                 licLen,
   char*                lic);

/**
 * @brief Returns help information about the file, format, state and info strings
 *
 * This function can be used to get all help messages or man pages for
 * each parameter in the file, format, state and info strings.
 *
 * To select the parameter string for which to request help information,
 * the parameter @p what must be set to one of the following values:
 *
 * * 1 - to get information about the READ FILE STRING
 * * 2 - to get information about the READ FORMAT STRING
 * * 3 - to get information about the WRITE FILE STRING
 * * 4 - to get information about the WRITE FORMAT STRING
 * * 5 - to get information about the READ CONVERSION STRING
 * * 6 - to get information about the WRITE CONVERSION STRING
 * * 8 - to get information about the INPUT FILE STRING
 * * 9 - to get information about the OUTPUT FILE STRING
 * * 10 - to get information about the INFO STRING
 * * 11 - to get information about the STATE STRING
 *
 * The output of this function is identical to the content of the FLCL
 * user manual section for the respective parameter string.
 *
 * @param [out]     rtc     INTEGER Return code
 * @param [in]      what    INTEGER Constant number for the corresponding parameter string
 * @param [in]      depth   INTEGER Number of levels to display (0-Man page, 1-One Level, 2-Two Level, ..., \<9-All)
 * @param [in]      pathLen INTEGER Length of path string (0 to start at root)
 * @param [in]      path    STRING  Path (e.g. conv.read.text.ccsid) to limit help to the (sub)tree of a certain object
 * @param [inout]   outLen  INTEGER Size/length of output buffer
 * @param [out]     out     STRING  Buffer for help information (is null-terminated)
 */
extern void FCRHLP(
   int*                 rtc,
   const int*           what,
   const int*           depth,
   const int*           pathLen,
   const char*          path,
   int*                 outLen,
   char*                out);

/**
 * @brief Returns syntax information about the file, format, state and info strings
 *
 * This function can be used to determine the complete syntax of the
 * file, format, state and info strings.
 *
 * To select the parameter string for which to request syntax information,
 * the parameter @p what must be set to one of the following values:
 *
 * * 1 - to get information about the READ FILE STRING
 * * 2 - to get information about the READ FORMAT STRING
 * * 3 - to get information about the WRITE FILE STRING
 * * 4 - to get information about the WRITE FORMAT STRING
 * * 5 - to get information about the READ CONVERSION STRING
 * * 6 - to get information about the WRITE CONVERSION STRING
 * * 8 - to get information about the INPUT FILE STRING
 * * 9 - to get information about the OUTPUT FILE STRING
 * * 10 - to get information about the INFO STRING
 * * 11 - to get information about the STATE STRING
 *
 * The output of this function is identical to the content of the FLCL
 * user manual section for the respective parameter string.
 *
 * @param [out]     rtc     INTEGER Return code
 * @param [in]      what    INTEGER Constant number for the corresponding parameter string
 * @param [in]      depth   INTEGER Number of levels to display (0-Man page, 1-One Level, 2-Two Level, ..., \<9-All)
 * @param [in]      pathLen INTEGER Length of path string (0 to start at root)
 * @param [in]      path    STRING  Path (e.g. conv.read.text.ccsid) to limit syntax to the (sub)tree of a certain object
 * @param [inout]   outLen  INTEGER Size/length of output buffer
 * @param [out]     out     STRING  Buffer for syntax information (is null-terminated)
 */
extern void FCRSYN(
   int*                 rtc,
   const int*           what,
   const int*           depth,
   const int*           pathLen,
   const char*          path,
   int*                 outLen,
   char*                out);

/**
 * @brief Retrieves an error message
 *
 * This function can be used to retrieve a human-readable error message
 * using the return code.
 * Sample call in COBOL:
 * <pre>
 *     02  MSGRC     PIC S9(8) COMP.
 *     02  MSGLEN    PIC S9(8) COMP VALUE 800.
 *     02  MSGBUFF   PIC X(800) VALUE SPACES.
 *     02  F-RETCO  PIC S9(8)  COMP.
 *         88 FLUC-OK           VALUE  0.
 *         88 FLUC-EOF          VALUE  43.
 * CALL 'FCRMSG' USING MSGRC, F-RETCO, MSGLEN, MSGBUFF.
 * </pre>
 * Sample call in PL1:
 * <pre>
 * DCL FCRMSG ENTRY EXTERNAL OPTIONS (ASM, FETCHABLE);
 *     2   MSGRC           BIN FIXED(31,0) INIT (0),
 *     2   MSGLEN          BIN FIXED(31,0) INIT (800),
 *     2   MSGBUFF         CHAR(800)       INIT ('40'X),
 *     2   F_RETCO         BIN FIXED(31,0) INIT (0)  ALIGNED,
 * CALL FCRMSG ( MSGRC,
 *               F_RETCO,
 *               MSGLEN,
 *               MSGBUFF );
 * </pre>
 * @param [out]     rtc     INTEGER Return code for this function
 * @param [in]      code    INTEGER A valid error code from another call
 * @param [inout]   msgLen  INTEGER Size/length of message buffer
 * @param [out]     msg     STRING  Buffer for error message (is null-terminated)
 */
extern void FCRMSG(
   int*                 rtc,
   const int*           code,
   int*                 msgLen,
   char*                msg);

/**
 * @brief Error trace
 *
 * This function can be used to get an error trace after a call to
 * #FCRINF, #FCROPN, #FCRGET, #FCRPUT, #FCRFLU, #FCRPRV, #FCRCLS, #FCRHLP or #FCRSYN.
 * The error trace contains the FLAM error stack. If parsing the file or
 * format string failed, the error trace also contains the complete error
 * stack of the Command-Line-Parser (FLAMCLP).
 *
 * @param [out]     rtc     INTEGER Return code for this function
 * @param [in]      code    INTEGER reserved (not used yet)
 * @param [inout]   trcLen  INTEGER Size/length of trace buffer
 * @param [out]     trc     STRING  Buffer for error trace (is null-terminated)
 */
extern void FCRTRC(
   int*                 rtc,
   const int*           code,
   int*                 trcLen,
   char*                trc);

/**
 * @brief Clear error information
 *
 * This function clears all error information (global errno and trace as
 * well as if a handle provided the reason codes in the handle). This is
 * useful before an open or an atomic function to not get the error trace
 * of the previous call.
 *
 * @param [in]      hdl     POINTER File handle from #FCROPN() or NULL
 */
extern void FCRCLR(void** hdl);

/**
 * @brief Load the FLAM environment
 *
 * This function loads the FLAM system variables (only on z/OS or in EDZ
 * environment), the STDENV definitions ('DD:STDENV' or '\<SYSUID>.STDENV'
 * on z/OS or '.stdenv' file in working or home directory on other systems)
 * and a optional list of variables to the environment. This must be called
 * before any other FLAM API function to set the correct environment. This
 * function allows to work with the same environment used by FLAM utilities,
 * subsystems, etc.
 *
 * Sample call in COBOL:
 * <pre>
 * WORKING-STORAGE SECTION.
 * 01  F-RETCO         PIC S9(8) COMP VALUE 0.
 * 01  F-SYSENV        PIC S9(8) COMP VALUE 1.
 * 01  F-STDENV        PIC S9(8) COMP VALUE 1.
 * 01  F-ENVLEN        PIC S9(8) COMP VALUE 200.
 * 01  F-ENVAR         PIC X(200)
 *     VALUE 'KEYWORD1=VALUE1;KEYWORD2=VALUE2'
 * 01  F-ENVCNT        PIC S9(8) COMP VALUE 0.
 * PROCEDURE DIVISION.
 * CALL  'FCRENV' USING F-RETCO,F-SYSENV,F-STDENV,
 *                      F-ENVLEN,F-ENVAR,F-ENVCNT.
 * </pre>
 *
 * @param [out] rtc     INTEGER Return code
 * @param [in]  sys     INTEGER Non-zero value to load system variables, 0 otherwise
 * @param [in]  std     INTEGER Non-zero value to load standard environment, 0 otherwise
 * @param [in]  envLen  INTEGER Length of the optional environment string (NULL if not provided or if the string is null-temrinated)
 * @param [in]  envStr  STRING  Optional list (can be NULL or empty) of environment variables (KEYWORD=VALUE) separated by new line ('\\n') or semicolon (';')
 * @param [out] cnt     INTEGER Number of environment variables set (optional, can be NULL)
 */
extern void FCRENV(int* rtc, const int* sys, const int* std, const int* envLen, const char* envStr, int* cnt);

/**
 * @brief Determines a symbol from environment
 *
 * The function can be used to fetch the value of an environment variable,
 * a JCL symbol (z/OS) or a system symbol (z/OS). If the replacement
 * string is not found (FLMRTC_FND), the symbol string is copied to the
 * output. The output string length is limited to 1024 bytes. The input
 * buffer can be the output buffer (replacement).
 *
 * @param [out]   rtc    INTEGER Return code
 * @param [in]    inpLen INTEGER Length of the symbol
 * @param [in]    inpStr STRING  Name of the symbol
 * @param [inout] outLen INTEGER At input the space for the output string,
 *                               on output the length of the output string
 * @param [out]   outStr STRING  Buffer for the output string
 */
extern void FCRSYM(int* rtc, const int* inpLen, const char* inpStr, int* outLen, char* outStr);

/**
 * @brief Open global facility for memory logging
 *
 * Enables in-memory logging. Messages that would normally printed to the console when using command
 * line tools like FLCL are collected in-memory and can be queried when needed.
 *
 * A CLP string can be passed to the function to control the identifier,
 * format and messages to log. If no log string is passed, the minimal format and minimal messages
 * are used by default. The logging facility is useful to catch warnings during operation.
 * The functions #FCRGETL(), #FCRCPYL() and #FCRCLRL() can be used to retrieve or clear the
 * current log buffer contents. The logging facility must be closed with #FCRCLSL().
 *
 * An example log string to log only warnings:
 * <pre>
 * "LOG(MESSAGE(WARN))"
 * </pre>
 *
 * Please use:
 * <pre>
 * 'FCRHLP(NULL,12,10,NULL,NULL,&buflen,buffer)'
 * 'FCRSYN(NULL,12,10,NULL,NULL,&buflen,buffer)'
 * </pre>
 * for more information.
 *
 *
 * @param [out]      rtc      INTEGER Return code
 * @param [in]       strLen   INTEGER Length of log string (optional, can be NULL)
 * @param [in]       logStr   STRING  Log string (optional, can be NULL))
 */
extern void FCROPNL(int* rtc,const int* strLen, const char* logStr);

/**
 * @brief Get log information
 *
 * Returns the maximum error code since the last call to #FCROPNL() or
 * #FCRCLRL(). Optionally, a read only buffer can be obtained by passing
 * memory for storing the buffer pointer. The returned buffer contains the
 * log messages separated by new line character and null-termination at
 * the end.
 *
 * @param [out]      maxCod   INTEGER Maximum error code since last initialization (optional, can be NULL)
 * @param [out]      bufLen   INTEGER Length of the string in the log buffer (optional, can be NULL)
 * @param [out]      buffer   POINTER Pointer to the log buffer (optional, can be NULL)
 */
extern void FCRGETL(int* maxCod, int* bufLen, const char** buffer);

/**
 * @brief Copies log information to a provided buffer
 *
 * Works like #FCRGETL() but instead of returning a pointer to the log,
 * the log is copied to the provided buffer. If the provided buffer is
 * too small, the output is truncated. The output is always
 * null-terminated. The parameter @p bufLen is set to the number of
 * bytes written to @p buffer, excluding the null-termination. Hence, on
 * truncation the returned length is one less than the buffer size.
 *
 * @param [out]      maxCod   INTEGER Maximum error code since last initialization (optional, can be NULL)
 * @param [inout]    bufLen   INTEGER Size of @p buffer (input), length of written log data (output)
 * @param [out]      buffer   STRING  Output buffer for log data
 */
extern void FCRCPYL(int* maxCod, int* bufLen, char* buffer);

/**
 * @brief Clear the log information
 *
 * Clears the log buffer and resets the maximum error code to 0.
 *
 * @param [out]      maxCod   INTEGER Returns maximum error code since last initialization (optional, can be NULL)
 */
extern void FCRCLRL(int* maxCod);

/**
 * @brief Close the global logging facility
 *
 * Closes the logging facility, frees all associated resources and
 * returns the maximum error code since the log was opened or cleared.
 *
 * @param [out]      maxCod   INTEGER Maximum error code since last initialization (optional, can be NULL)
 */
extern void FCRCLSL(int* maxCod);

/**
 * @brief Provides various information
 *
 * This function can be used to retrieve various information about
 * files, supported CCSIDs and other things. You must provide an info
 * string to define which information to request. You can define the
 * @p format in which the information will be output. The information is
 * written to an output buffer. If the buffer is too small, a FMLRTC_LEN
 * error is returned, the @p buflen is set to the required length and the
 * buffer is filled with the data up to the maximum.
 *
 * The @p format parameter can be set to one of the following output
 * formats:
 *
 * * 1 - Simple list of strings with each line separated by \\n and the whole text terminated by 0x00
 * * 2 - As XML string (in local charset) of strings with each line separated by \\n and the whole text terminated by 0x00
 *
 * The info definition string uses the same syntax as the GET method of
 * the FLCL INFO command. The complete syntax and help can be retrieved
 * with the corresponding functions below. The string must start with
 * <code>GET.</code> followed by the corresponding method (FILE/CCSIDS/...).
 * Leading whitespace is ignored.
 *
 * Examples:
 * <pre>
 * "GET.FILE='~.TEXT.TEST'"
 * "GET.CCSIDS"
 * </pre>
 *
 * Please use:
 * <pre>
 * 'FCRHLP(NULL,11,10,NULL,NULL,&buflen,buffer)'
 * 'FCRSYN(NULL,11,10,NULL,NULL,&buflen,buffer)'
 * </pre>
 * for more information.
 *
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      infoLen   INTEGER Length of info string
 * @param [in]      infoStr   STRING  Info string with GET instructions
 * @param [in]      format    INTEGER Format specification for the output buffer
 * @param [inout]   buflen    INTEGER Size/length of the output buffer
 * @param [out]     buffer    STRING  Output buffer (data format depends on format parameter)
 */
extern void FCRINF(
   int*                 rtc,
   const int*           infoLen,
   const char*          infoStr,
   const int*           format,
   int*                 buflen,
   char*                buffer);

/**
 * @brief Opens a file
 *
 * This function opens a normal file, a member in a FLAM4FILE, a PGP
 * file or a member in a concatenated GZIP-, BZIP- or XZ-File or some
 * other supported file format. It supports base encoding, encryption,
 * compression, character conversion and text, XML and table formatting,
 * among others.
 *
 * The file definition string uses the same syntax as the read or write
 * method of the FLCL CONV or the input and output specification of the
 * XCNV command. The complete syntax and help can be determined with the
 * corresponding functions below. The string must start with
 * <code>read.</code> or <code>write.</code> followed by the corresponding
 * method (binary/char/text/flam4/xml/...) or with <code>input()</code>
 * or <code>output()</code> object specifications (leading whitespace is
 * ignored).
 *
 * Examples:
 * <pre>
 * "read.text(file='test.txt')"
 * "write.binary(file='test.gz' comp.gzip(level=BEST))"
 * "input(sav.fil(fio.blk(name='~.GZ.TEST') cnv.zip() cnv.chr(from=latin1 to=ibm1141) fmt.txt()))"
 * "output(sav.fil(fmt.txt(method=host) fio.fl4(name='~.ADC.TEST')))"
 * "write[flam(file='flamfile.adc' ccsid=IBM1141),text(file='testfile.zip' method=windows ccsid=CP1252 archive.zip())]"
 * </pre>
 *
 * The last example above shows writing the output to two different
 * files in parallel: as FLAMFILE for IBM mainframes and as ZIP file for
 * a Windows system.
 *
 * Please use:
 * <pre>
 * 'FCRHLP/FCRSYN(NULL,1,10,NULL,NULL,buflen,buffer)'
 * 'FCRHLP/FCRSYN(NULL,3,10,NULL,NULL,buflen,buffer)'
 * 'FCRHLP/FCRSYN(NULL,8,10,NULL,NULL,buflen,buffer)'
 * 'FCRHLP/FCRSYN(NULL,9,10,NULL,NULL,buflen,buffer)'
 * </pre>
 * for more information.
 *
 * The format string uses the syntax of the <code>format.record()</code>
 * union which was specifically designed for the record interface to format
 * the data elements into records. The string can contain all parameters
 * supported by <code>format.record()</code>. Currently, the format parameter
 * can be used to specify the character conversion. If no format string is
 * passed, then the default CCSID is used to provide the records.
 *
 * If the format string starts with <code>format.</code> then one of the
 * corresponding objects (binary/char/text/record/element/...) can be used.
 * This is mainly useful to read FLAM5 elements as records. If you choose
 * one of the byte stream formatting methods (binary/char/text/xml) the
 * data element could be a whole block of data with (almost) arbitrary
 * length.
 *
 * Examples:
 * <pre>
 * "ccsid='UTF-8'"
 * "format.record(ccsid='UTF-8'")
 * "format.element(ccsid='IBM1141' attributes)"
 * </pre>
 *
 * Please use:
 * <pre>
 * 'FCRHLP/FCRSYN(NULL,2,10,NULL,NULL,buflen,buffer)'
 * 'FCRHLP/FCRSYN(NULL,4,10,NULL,NULL,buflen,buffer)'
 * </pre>
 * for more information.
 *
 * With element formatting, you can read and write a serialized form of
 * FLAM5 elements. For example, it can be used to tokenize an XML document
 * and read these tokens (elements) for further processing. The
 * serialized element format (version 0) is described by the structure
 * #FlmElmRec0 in the FLMDEF.h header. For COBOL, a corresponding copy
 * book (SOFLMDEF) can be found in the SRCLIB folder.
 *
 * The state string uses the syntax of the <code>state()</code> object
 * which was specifically designed for the byte and record interface to
 * manage the internal state information of FLAM. This object contains
 * the current state of the data and is useful to transfer it from an
 * FCROPN call for reading to an FCBOPN call for writing or to set a
 * custom state when writing. The object contains metadata like file
 * attributes, data types and character set. These values are, among
 * others, important to fill header information of archives like GZIP
 * header or FLAM member headers. If you provide a NULL pinter or zero
 * length for the state at read, no state is given. If a length for space
 * and pointer to the buffers provided, then a length error is returned
 * if the buffer too small. In this case the length field contains the
 * required size. We recommend to use at least 1024 byte for the state
 * string.
 *
 * Examples: "state(member='MY.ORIGINAL.DATASET',RECF=FBA,RECL=120 CCSID=1141)"
 *
 * Please use:
 * <pre>
 * 'FCRHLP(NULL,11,10,NULL,buflen,buffer)'
 * 'FCRSYN(NULL,11,10,NULL,buflen,buffer)'
 * </pre>
 * for more information.
 *
 * The file string defines how the FLAM elements are read from or written
 * to the file. The format string defines how the FLAM elements are converted
 * into records. When opening a file for reading, the state string is
 * returned via the @p stateStr parameter. When opening for writing, it
 * is an input parameter that contains the state information for the data.
 *
 * Sample call in COBOL:
 * <pre>
 * 01  FLUC-PARAMETER.
 *     02 F-ID     PIC S9(8)  COMP.
 *     02 F-RETCO  PIC S9(8)  COMP.
 *        88 FLUC-OK           VALUE  0.
 *        88 FLUC-EOF          VALUE  43.
 *     02  F-FILELEN  PIC S9(8)  COMP VALUE 60.
 *     02  F-FILE     PIC X(60)  VALUE
 *         'READ.TEXT(FILE=''DD:INPUT'' RECLEN=2040)'.
 *     02  F-FORMLEN  PIC S9(8)  COMP SYNC VALUE 20.
 *     02  F-FORM     PIC X(20)  VALUE
 *         'CCSID=''1141'''.
 *     02  F-STATLEN  PIC S9(8)  COMP SYNC VALUE 512.
 *     02  F-STAT     PIC X(512) VALUE ' '.
 * CALL  'FCROPN' USING F-ID, F-RETCO,
 *                      F-FILELEN, F-FILE,
 *                      F-FORMLEN, F-FORM,
 *                      F-STATLEN, F-STAT.
 * </pre>
 *
 * Sample call in PL1:
 * <pre>
 * DCL FCROPN ENTRY EXTERNAL OPTIONS (ASM, FETCHABLE);
 * 2 F_ID       BIN FIXED(31,0) INIT (0)  ALIGNED,
 * 2 F_RETCO    BIN FIXED(31,0) INIT (0)  ALIGNED,
 * 2 F_FILELEN  BIN FIXED(31,0) INIT (60) ALIGNED,
 * 2 F_FILE     CHAR(60)        INIT ('READ.TEXT(FILE=''DD:INPUT'' RECLEN=2040)'),
 * 2 F_FORMLEN  BIN FIXED(31,0) INIT (20) ALIGNED,
 * 2 F_FORM     CHAR(20)        INIT ('CCSID=''1141'''),
 * 2 F_STATLEN  BIN FIXED(31,0) INIT (512) ALIGNED,
 * 2 F_STAT     CHAR(512)       INIT ('40'X),
  * CALL FCROPN (F_ID,      F_RETCO,
 *               F_FILELEN, F_FILE,
 *               F_FORMLEN, F_FORM,
 *               F_STATLEN, F_STAT );
 * </pre>
 *
 * @param [out]     hdl       POINTER File handle
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      fileLen   INTEGER Length of file string (must be provided)
 * @param [in]      fileStr   STRING  File string with READ/WRITE instructions
 * @param [in]      formatLen INTEGER Length of format string (0 to use defaults)
 * @param [in]      formatStr STRING  Format string or NULL
 * @param [inout]   stateLen  INTEGER Length of state string (NULL or 0 no state, minimum 1024)
 * @param [inout]   stateStr  STRING  State string (output at read, input for write)
 */
extern void FCROPN(
   void**               hdl,
   int*                 rtc,
   const int*           fileLen,
   const char*          fileStr,
   const int*           formatLen,
   const char*          formatStr,
   int*                 stateLen,
   char*                stateStr);

/**
 * @brief Opens a converter
 *
 * This function opens an element data conversion module for read or write
 * operations if <code>format.element()</code> is used. All functions ending
 * with 'V' accept an additional conversion handle, which is only relevant
 * if <code>format.element()</code> is done. With this set of 'V' functions,
 * it is possible to define how the element data is converted from
 * application memory to a neutral FLAM5 element or vice versa.
 *
 * The read type specification defines how the data type is read from application
 * memory and converted in the neutral data type at a write operation. The write
 * type specification defines how a neutral data type is written to the
 * application memory at a read operation.
 *
 * To use the converter in write operations the read type specification is
 * required. If the converter is used for read operation a write type
 * specification must be defined. The conversion string uses the syntax of
 * the 'type' union designed for element conversion. The string must start
 * with 'read.' or 'write.' followed by the corresponding data type
 * specification (binary/string/integer/float/...). Leading whitespace is
 * ignored.
 *
 * You can also use a read conversion in a read operation. It makes sense,
 * for example, to convert a string of an XML element containing a decimal
 * number at read to the neutral form of a number (64 bit integer) in FLAM.
 * In this case the 8 byte (64 bit) integer value is given as element data,
 * instead of the string with the decimal number.
 *
 * The function optionally accepts a file or memory conversion handle. You
 * can provide the file handle for which the converter will be used, so that
 * the system knows e.g. the CCSID of the data. Otherwise, UTF-8 is assumed
 * as neutral character encoding, but with the INPUT() object it is possible
 * to use another internal character set. By providing the file or memory
 * conversion handle it can be made sure that the correct internal
 * representation of the data is known and the converter is opened in the
 * right manner for that file.
 *
 * You can also use a conversion string (<code>CONV.type(from() to())</code>)
 * which describe a complete external representation to external representation
 * conversion. This form can be used with the functions #FCRCONV / #FCRCONP for an independent
 * memory to memory conversion. One use case woud be for an XML element, which
 * contains a decimal number as UTF-8 string to build an integer in two's complement
 * representation or to produce a PGP file which contains a CSV table
 * or some other complex in-memory conversions.
 *
 * Examples:
 * <pre>
 * "read.string(chrset(ccsid=default))"
 * "write.string(chrset(ccsid=default whitespace=collapse))"
 * "write.string(chrset(ccsid=default whitespace=number) number(format='%3.2f'))"
 * "conv.integer(from.string() to.bin())"
 * </pre>
 *
 * Please use:
 * <pre>
 * 'FCRHLP/FCRSYN(NULL,5,10,NULL,NULL,buflen,buffer)'
 * 'FCRHLP/FCRSYN(NULL,6,10,NULL,NULL,buflen,buffer)'
 * 'FCRHLP/FCRSYN(NULL,7,10,NULL,NULL,buflen,buffer)'
 * </pre>
 * for more information.
 *
 *
 * Sample call in COBOL:
 * <pre>
 * CALL  'FCROPNV' USING F-ID, F-CNV, F-RETCO,
 *                       F-CONVLEN, F-CONV.
 * </pre>
 *
 * @param [in]      hdl       POINTER File or memory conversion handle from #FCROPN or #FCROPNV (optional)
 * @param [out]     cnv       POINTER Conversion handle
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      convLen   INTEGER Length of conversion string (must be provided)
 * @param [in]      convStr   STRING  Conversion string with READ/WRITE instructions
 */
extern void FCROPNV(
   void**               hdl,
   void**               cnv,
   int*                 rtc,
   const int*           convLen,
   const char*          convStr);

/**
 * @brief Start with a new member in an open file
 *
 * The function implements a re-open of the current file handle to start
 * with a new member. You must provide a valid handle from #FCROPN() for
 * write operation and you can provide a new format string and/or state
 * string. If no format string (NULL) is given, the format of the
 * previous member is used. If no state (NULL) is provided, then the
 * default values are used. Additionally you have the ability to get
 * statistical information, since open or last re-open. This works
 * like #FCRCLS().
 *
 * Sample call in COBOL:
 * <pre>
 * CALL  'FCRNEWM' USING N-ID, N-RETCO,
 *                       N-FORMATLEN, N-FORMAT,
 *                       N-STATELEN, N-STATE,
 *                       N-STATISTICFMT, N-BUFLEN, N-BUFFER.
 * </pre>
 *
 * @param [inout]   hdl       POINTER File handle
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      formatLen INTEGER Length of format string (0 to use defaults)
 * @param [in]      formatStr STRING  Format string or NULL (to use previous formatting)
 * @param [in]      stateLen  INTEGER Length of state string (NULL or 0 no state, minimum 1024)
 * @param [in]      stateStr  STRING  State string
 * @param [in]      format    INTEGER Format specification for the output buffer
 * @param [inout]   buflen    INTEGER Size/length of the output buffer (0 = no statistics)
 * @param [out]     buffer    STRING  Output buffer (data format depends on the @p format parameter)
 */
extern void FCRNEWM(
   void**               hdl,
   int*                 rtc,
   const int*           formatLen,
   const char*          formatStr,
   const int*           stateLen,
   const char*          stateStr,
   const int*           format,
   int*                 buflen,
   char*                buffer);


/**
 * @brief Writes one record or element
 *
 * This function writes records to the output stream. The behavior
 * depends on the formatting that has been selected when opening the file.
 *
 * @par format.record()
 * Depending on the record formatting method, the length of the data is
 * either recorded, discarded or replaced by a delimiter or length field.
 *
 * @par
 * Each call to FCRPUT is transformed into one record. Only one record
 * can be written per call when using record I/O. The record length is not
 * limited when formatting the elements in memory. However, when writing
 * records to a dataset or a FLAMFILE, respective limits apply. Therefore,
 * in the file string, you can specify how longer records are handled (cut,
 * wrap or error).
 *
 * @par format.element()
 * To write elements, the buffer pointed to by <code>rec</code> must
 * contain one of the serialized element structures defined in FLMDEF.h
 * (e.g. #FlmElmRec0). The structure is expected to start at offset 0
 * in the buffer. All members of the structure must be set to valid
 * values. The length in bytes of the serialized element structure
 * must be passed via parameter <code>recLen</code>. The length of an
 * element is calculated as sum of all length fields in the structure +
 * the length of the structure itself without the last field (i.e.
 * buffer). You can use macros like #FLMELMREC0_LENGTH(element) to
 * conveniently calculate the correct length of the structure in C.
 *
 * @par
 * All elements written to one file handle must have the same
 * matrix type. If an element of an element type is written which contains
 * text data, the data field must be provided in UTF-8 unless character
 * conversion was activated by setting the <code>ccsid</code> in the
 * <code>format.element()</code> clause to the character set of your data.
 * If the matrix and/or element type requires attributes, then the
 * attribute length and values must be set as described by the element
 * type.
 *
 * Depending on the file and format strings passed to #FCROPN(), you can,
 * for example, write EBCDIC records in IBM1141 and the result will be
 * an ASCII-armored, compressed and encrypted PGP file in CP1252 where
 * each record is delimited with 0x0D0A for a Windows system.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRPUT' USING F-ID, F-RETCO,
 *                     F-RECLEN, F-RECORD.
 * </pre>
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      recLen    INTEGER Length of the record
 * @param [in]      rec       STRING  Record (binary data)
 */
extern void FCRPUT(
   void**               hdl,
   int*                 rtc,
   const int*           recLen,
   const char*          rec);

/**
 * @brief Writes one element with conversion
 *
 * This function works like #FCRPUT but accepts one additional parameter
 * <code>cnv</code> which point to a conversion handle. This parameter
 * is only relevant with <code>format.element()</code> and can be used to
 * overwrite the element data conversion. You can open such a handle by
 * calling #FCROPNV and request an individual conversion for that element.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRPUTV' USING F-ID, F-RETCO,
 *                      F-RECLEN, F-RECORD,
 *                      F-CNV.
 * </pre>
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      recLen    INTEGER Length of the record
 * @param [in]      rec       STRING  Record (binary data)
 * @param [in]      cnv       POINTER Conversion handle from #FCROPNV()
 */
extern void FCRPUTV(
   void**               hdl,
   int*                 rtc,
   const int*           recLen,
   const char*          rec,
   void**               cnv);

/**
 * @brief Get table name
 *
 * If you use the table support at read with end of table handling (ENDOFT)
 * then you can determine the current table name (logical name defined in
 * the row specification) after open and EOT using this function.
 *
 * The function truncates the table name if the provided buffer is too small.
 * Using such a shorted table name in FCRSTN will cause a "table name
 * does not fit" error.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRGTN' USING F-ID, F-RETCO, F-LENGTH, F-NAME.
 * </pre>
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 * @param [inout]   length    INTEGER Buffer size for @p name (input), Length of the table name (output)
 * @param [out]     name      STRING  Buffer that the table name is written to (ATTENTION: truncated if provided buffer too small)
 */
extern void FCRGTN(
   void**               hdl,
   int*                 rtc,
   int*                 length,
   char*                name);

/**
 * @brief Get file name
 *
 * If you open a file for write operation and use input output name mapping
 * running or random numbers, dates and times, this function is useful to
 * determine the current file name. To analyze the data read from memory at
 * write, the real open is delayed. To ensure to get the file name you must
 * call this function after a #FCRFLU() in front of #FCRCLS(). At read the
 * original file name read will be returned and the index ignored.
 *
 * The function truncates the file name if the provided buffer is too small.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRGFN' USING F-ID, F-RETCO, F-INDEX, F-LENGTH, F-NAME.
 * </pre>
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      ind       INTEGER Index if multiple writes defined else set to 0
 * @param [inout]   length    INTEGER Buffer size for @p name (input), Length of the file name (output)
 * @param [out]     name      STRING  Buffer that the file name is written to (ATTENTION: truncated if provided buffer too small)
 */
extern void FCRGFN(
   void**               hdl,
   int*                 rtc,
   const int            ind,
   int*                 length,
   char*                name);

/**
 * @brief Set table name
 *
 * If you write more than one table to a file, the current table format can
 * be set with this function. The function only succeeds at the end of a
 * complete row. It fails if there is a remainder in the buffer. The
 * automatic detection of the table format is deactivated. The provided
 * data must match with the defined row specification. Auto detection of
 * the table format can be reactivated with a call to #FCRGTN(). A call to
 * #FCRSTN() will start a new table of the same or another format. If ENDOFT
 * is activated in the format string while writing, then FLMRTC_EOT is handled
 * internally and the file handle will be re-opened. By using the [table] in
 * your output file name, you can split the data and write it to different files.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRSTN' USING F-ID, F-RETCO, F-LENGTH, F-NAME.
 * </pre>
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      length    INTEGER Length of the table name
 * @param [in]      name      STRING  Table name in provide length
 */
extern void FCRSTN(
   void**               hdl,
   int*                 rtc,
   const int*           length,
   const char*          name);

/**
 * @brief Flush internal buffers
 *
 * Flushes all internal buffers, i.e. writes all data that still resides
 * in memory to the file denoted by the handle. (This function also ensures
 * that the real open are done.)
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRFLU' USING F-ID, F-RETCO.
 * </pre>
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 */
extern void FCRFLU(
   void**               hdl,
   int*                 rtc);

/**
 * @brief Reads one record or element
 *
 * Reads one record per function call from the input file. The behavior
 * depends on the formatting that has been selected when opening the file.
 *
 * @par format.record()
 * In record formatting mode, set @p recLen to the maximum expected length
 * of the record, to obtain the number of bytes. If the record attempted
 * to read is longer than @p recLen, the function will fail with the
 * return code @p rtc set to #FLMRTC_LEN. In this case, you can allocate
 * more space and try to read the same record again. The required space
 * is returned in @p reclen. There is no limit on record length, but the
 * record length may be limited by the underlying data management system
 * (DMS). Most record-oriented DMS are limited to a maximum record length
 * of 32760 bytes. The record I/O of FLAM has currently a limit of 1 MiB
 * for the maximum record length.
 *
 * @note
 * If record I/O is used, then the returned number of bytes
 * can be zero because records can contain zero-length data.
 *
 * @par format.element()
 * This formatting method provides access to the raw elements in a
 * serialized form that all data is split into internally when reading
 * any data. Each call to this functions returns at most one serialized
 * element. The record buffer pointed to by <code>rec</code> contains an
 * element matching the structure #FlmElmRec0. Anything else works like
 * record I/O.
 *
 * @par
 * Each element has a @ref MATTYP "matrix type", which indicates the
 * type of data, and an @ref ELMTYP "element type" which defines the kind
 * of content. The set of element types depends on the matrix type.
 *
 * @par
 * Besides the element data, each element can contain hash values
 * (checksums) and additional attributes. The presence of both depends
 * on the element type.
 *
 * @par
 * With element formatting, the function reads one element at a time and
 * writes it into the supplied record buffer of length @p recLen. If the
 * buffer is too small, the return code @p rtc is set to #FLMRTC_LEN. If
 * the buffer is at least <code>sizeof(#FlmElmRec0)</code> bytes long,
 * all fields of the structure will have been written to the buffer
 * except for the actual data (FlmElmRec0::buffer). You can use this
 * information to reallocate your buffer to the required size. The
 * required buffer size is the size of the structure (e.g. #FlmElmRec0)
 * plus the sum of all length fields of the structure. There is a
 * convenient C macro for every supported structure, which calculates the
 * correct length, e.g. #FLMELMREC0_LENGTH.
 *
 * @note
 * You should always check the version field (first 32 bits, currently
 * always 0) to determine the structure of the element. A version of 0
 * indicates that, #FlmElmRec0 is the structure of the data. In future
 * versions, additional structures might be added. Checking the version
 * field avoids misinterpreting the data by using the wrong structure.
 *
 * @par format.binary/char/text/xml()
 * In this case @p reclen bytes are read and copy to @p rec.
 *
 * Sample call in COBOL:
 * <pre>
 * 01  FLUC-PARAMETER.
 *     02 F-ID     PIC S9(8)  COMP.
 *     02 F-RETCO  PIC S9(8)  COMP.
 *        88 FLUC-OK           VALUE  0.
 *        88 FLUC-EOF          VALUE  43.
 *     02  F-INLEN   PIC S9(8) COMP.
 * 01  OUTDAT-RECORD.
 *     02 FILLER   PIC X(2040).
 * CALL 'FCRGET' USING F-ID, F-RETCO,
 *                     F-INLEN, OUTDAT-RECORD
 * </pre>
 * Sample call in PL1:
 * <pre>
 * DCL FCRGET ENTRY EXTERNAL OPTIONS (ASM, FETCHABLE);
 * 2 F_ID       BIN FIXED(31,0) INIT (0)  ALIGNED,
 * 2 F_RETCO    BIN FIXED(31,0) INIT (0)  ALIGNED,
 * 2 F_INLEN    BIN FIXED(31,0),
 * DCL  1  OUTREC   CHAR(2040);
 * CALL FCRGET ( F_ID,
 *               F_RETCO,
 *               F_INLEN,
 *               OUTREC  );
 * </pre>
 *
 * The function sets the return code to #FLMRTC_EOF (43) if the end of file
 * is encountered. To read a whole file you have to call #FCRGET() in a
 * loop until the return code is 43.
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 * @param [inout]   recLen    INTEGER Size/length of the record buffer
 * @param [out]     rec       STRING  Record buffer (binary data)
 */
extern void FCRGET(
   void**               hdl,
   int*                 rtc,
   int*                 recLen,
   char*                rec);

/**
 * @brief Reads one element with conversion
 *
 * This function works like #FCRGET but accepts two additional parameter
 * @p cnv which point to a conversion handle and @p skip is a element type
 * which will be ignored at this read request. These parameters are only
 * relevant with <code>format.element()</code> and can be used to
 * overwrite the element data conversion and skip an unexpected element
 * type. You can open such an handle by calling #FCROPNV and request a
 * individual conversion for that element.
 *
 * In XML data between a #FLMELM_TYPXML_ENDSTRTELM and the next #FLMELM_TYPXML_STARTELM
 * data elements (#FLMELM_TYPXML_DATA) could be exist and the parameter @p skip can be
 * used for example to ignore these data elements. With #FLMELM_NOSKIP the next element
 * is given.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRGETV' USING F-ID, F-RETCO,
 *                      F-RECLEN, F-RECORD,
 *                      F-CNV F-SKIP.
 * </pre>
 *
 * The function sets the return code to #FLMRTC_EOF (43) if the end of file
 * is encountered. To read a whole file you have to call #FCRGET() in a
 * loop until the return code is 43.
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 * @param [inout]   recLen    INTEGER Size/length of the record buffer
 * @param [out]     rec       STRING Record buffer (binary data)
 * @param [in]      cnv       POINTER Conversion handle from #FCROPNV()
 * @param [in]      skip      INTEGER Skip this element type (NULL no skip)
 */
extern void FCRGETV(
   void**               hdl,
   int*                 rtc,
   int*                 recLen,
   char*                rec,
   void**               cnv,
   int*                 skip);

/**
 * @brief Locates one record or element (without own buffer)
 *
 * The function works like #FCRGET(), but it returns a memory address to
 * a buffer containing the record instead of copying the data into the
 * memory provided by the caller. (no length error can occur)
 *
 * If you use #FCRLOC() for record I/O, @p recLen is an output parameter
 * that contains the length of the record. The pointer to the record buffer
 * @p rec is only valid up to the next function call on this handle.
 *
 * Be careful with the returned record pointer because it breaks the
 * isolation and if you manipulate the data area behind this pointer,
 * you can destroy internal structures.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRLOC' USING F-ID, F-RETCO,
 *                     F-RECLEN, P-RECORD.
 * </pre>
 *
 * The function sets the return code to #FLMRTC_EOF (43) if the end of file
 * is encountered. To read a whole file you have to call #FCRLOC() in a
 * loop until the return code is 43.
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 * @param [out]     recLen    INTEGER Length of the record buffer
 * @param [out]     rec       POINTER Pointer to the record buffer
 */
extern void FCRLOC(
   void**               hdl,
   int*                 rtc,
   int*                 recLen,
   char**               rec);

/**
 * @brief Reads one element with conversion (without own buffer)
 *
 * This function works like #FCRLOC but accepts two additional parameter
 * @p cnv which point to a conversion handle and @p skip is a element type
 * which will be ignored at this read request. These parameters are only
 * relevant with <code>format.element()</code> and can be used to
 * overwrite the element data conversion and skip an unexpected element
 * type. You can open such an handle by calling #FCROPNV and request a
 * individual conversion for that element.
 *
 * In XML data between a #FLMELM_TYPXML_ENDSTRTELM and the next #FLMELM_TYPXML_STARTELM
 * data elements (#FLMELM_TYPXML_DATA) could be exist and the parameter @p skip can be
 * used for example to ignore these data elements. With #FLMELM_NOSKIP the next element
 * is given.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRLOCV' USING F-ID, F-RETCO,
 *                      F-RECLEN, P-RECORD,
 *                      F-CNV F-SKIP.
 * </pre>
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 * @param [out]     recLen    INTEGER Length of the record buffer
 * @param [out]     rec       POINTER Pointer to the record buffer
 * @param [in]      cnv       POINTER Conversion handle from #FCROPNV()
 * @param [in]      skip      INTEGER Skip this element type (NULL no skip)
 */
extern void FCRLOCV(
   void**               hdl,
   int*                 rtc,
   int*                 recLen,
   char**               rec,
   void**               cnv,
   int*                 skip);

/**
 * @brief Sets the read position to the previous record or element
 *
 * If the file handle has been opened for reading with element
 * formatting (<code>format.element()</code>) or record formatting
 * <code>format.record()</code>, the internal position is set to the
 * previously read element or record. I.e. the next call to #FCRGET()
 * will return the same element or record as the last one.
 *
 * The function is guaranteed to decrement the file position at least
 * once after #FCRGET() has been called. Multiple successive calls to
 * this function may or not be successful.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRPRV' USING F-ID, F-RETCO.
 * </pre>
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 */
extern void FCRPRV(
   void**               hdl,
   int*                 rtc);


/**
 * @brief Converts element data (with copy)
 *
 * The function converts data between formats as specified by the conversion
 * string passed to #FCROPNV().
 *
 * It provides memory to memory conversion between external data representations
 * of different data types using a conversion handle from function #FCROPNV()
 * which was called with a conversion string of the form from-to or read-write.
 *
 * Please note that this function always converts the whole input data
 * independent of previous calls. This implies that data elements must
 * be passed as a whole. For example, passing a block of UTF-8 text as input
 * where the data in the input buffer ends in the middle of a multi-byte
 * character, will result in an error or unexpected output. To convert
 * multiple buffers of dependent data (e.g. whole files), use the functions
 * #FCRRUNV() and #FCRFINV().
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRCONV' USING C-ID, C-RETCO.
 *                      C-INPLEN, C-INP,
 *                      C-OUTLEN, C-OUT.
 * </pre>
 *
 * The return code FLMRTC_LEN tells that the output buffer is too small.
 * In this case, the function must be called again with the same input
 * buffer and an output buffer of the size returned by the <code>outLen</code>
 * parameter (or larger).
 *
 * If EOT (end of table) handling is activated, the return code FLMRTC_EOT
 * can occur if the input buffer contains the data for more than one
 * table or if the order of tables in the input buffer does not match the
 * order of the row specifications. Only one table can be written to the
 * output buffer per call of this function. Hence, it must be called
 * repeatedly with the same input buffer as long as FLMRTC_EOT is returned.
 * Note that if the data in the input buffer does not match the first row
 * specification, FLMRTC_EOT is returned without writing any data to the
 * output buffer. Please be aware that FLMRTC_LEN may also be returned
 * for any of your repeated calls if the output buffer is not large enough
 * for the currently processed table.
 *
 * Below is an example on handling the return codes if EOT handling is
 * activated and length errors are expected:
 *
 * <pre>
 * FCROPNV(hdl,rtc,"...");
 * if (rtc) then return(rtc);
 * do {
 *    do {
 *       FCRGTN(hdl,...);
 *       outlen=0; // ensure a length error
 *       FCRCONV(hdl,rtc,inplen,input,outlen,output);
 *       if (rtc==FLMRTC_LEN) then {
 *          output=realloc(output,outlen);
 *          FCRCONV(hdl,rtc,inplen,input,outlen,output);
 *       }
 *       if (rtc && rtc!=FLMRTC_EOT) then {
 *          FCRCLSV(hdl,NULL);
 *          return(rtc);
 *       }
 *       if (outlen>0) then {
 *         // process output
 *       }
 *    } while(rtc==FLMRTC_EOT);
 *    input+=inplen; // goto next input
 * } while (input<end && rtc==FLMRTC_OK);
 * FCRCLSV(hdl,NULL);
 * return(rtc);
 * </pre>
 *
 * To simplify the EOT handling and to increase performance, you can use the
 * corresponding p(ointer) function (#FCRCONP()) which returns a pointer to
 * the data, where no length error can occur.
 *
 * @param [in]      cnv       POINTER Conversion handle from #FCROPNV()
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      inpLen    INTEGER Length of the input buffer
 * @param [in]      inp       POINTER  Pointer to the input buffer
 * @param [inout]   outLen    INTEGER On input: Available space for the output buffer
 *                                    At output: If return code 0: length of the output buffer
 *                                               If return code FLMRTC_LEN: required minimum length for @p out
 * @param [out]     out       POINTER Pointer to the output buffer
 */
extern void FCRCONV(
   void**               cnv,
   int*                 rtc,
   const int*           inpLen,
   const char*          inp,
   int*                 outLen,
   char*                out);

/**
 * @brief Converts element data (with locate)
 *
 * This function is identical to #FCRCONV(), except that the output buffer
 * is not user-provided. When the function returns, the buffer pointer
 * pointed to by the @p out parameter is set to a buffer that is large enough
 * to store the output data. As a result, the return code can never be FLMRTC_LEN.
 *
 * @param [in]      cnv       POINTER Conversion handle from #FCROPNV()
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      inpLen    INTEGER Length of the input buffer
 * @param [in]      inp       POINTER Pointer to the input buffer
 * @param [out]     outLen    INTEGER Length of the output buffer
 * @param [out]     out       POINTER Pointer to the output buffer pointer
 */
extern void FCRCONP(
   void**               cnv,
   int*                 rtc,
   const int*           inpLen,
   const char*          inp,
   int*                 outLen,
   char**               out);

/**
 * @brief Converts dependent data blocks (with copy)
 *
 * The function converts data between formats as specified by the conversion
 * string passed to #FCROPNV().
 *
 * It provides memory to memory conversion between external data representations
 * of different data types using a conversion handle from function #FCROPNV()
 * which was called with a conversion string of the form from-to or read-write.
 *
 * This function must be used instead of #FCRCONV() if processing consecutive
 * blocks of data, e.g. whole files. If no sufficient amount of input data
 * is available, the output length (outLen) might be shorter than the input
 * or even zero. When the last input block is processed, the function #FCRFINV()
 * must be called to force any pending data to be processed and written to the
 * output buffer. Failing to call #FCRFINV() might result truncated output!
 *
 * The return code FLMRTC_LEN tells that the output buffer is too small.
 * In this case, you can provide a larger buffer to get the conversion done.
 * The required length for the output buffer is provided in the <code>outLen</code>
 * parameter.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRRUNV' USING C-ID, C-RETCO.
 *                      C-INPLEN, C-INP,
 *                      C-OUTLEN, C-OUT.
 * </pre>
 *
 * @param [in]      cnv       POINTER Conversion handle from #FCROPNV()
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      inpLen    INTEGER Length of the input buffer
 * @param [in]      inp       POINTER Pointer to the input buffer
 * @param [inout]   outLen    INTEGER On input: Available space for the output buffer
 *                                    At output: If return code 0: length of the output buffer
 *                                               If return code FLMRTC_LEN: required minimum length for @p out
 * @param [out]     out       POINTER Pointer to the output buffer
 */
extern void FCRRUNV(
   void**               cnv,
   int*                 rtc,
   const int*           inpLen,
   const char*          inp,
   int*                 outLen,
   char*                out);

/**
 * @brief Converts dependent data blocks (with locate)
 *
 * This function is identical to #FCRRUNV(), except that the output buffer
 * is not user-provided. When the function returns, the buffer pointer
 * pointed to by the @p out parameter is set to a buffer that is large enough
 * to store the output data. As a result, the return code can never be FLMRTC_LEN.
 *
 * @param [in]      cnv       POINTER Conversion handle from #FCROPNV()
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      inpLen    INTEGER Length of the input buffer
 * @param [in]      inp       POINTER Pointer to the input buffer
 * @param [out]     outLen    INTEGER Length of the output buffer
 * @param [out]     out       POINTER Pointer to the output buffer pointer
 */
extern void FCRRUNP(
   void**               cnv,
   int*                 rtc,
   const int*           inpLen,
   const char*          inp,
   int*                 outLen,
   char**               out);

/**
 * @brief Finish conversion of dependent data blocks (with copy)
 *
 * This function must be called to finish data conversion when #FCRRUNV() is used.
 * It forces all internally buffered, but unprocessed data to be converted and
 * written to the output buffer.
 *
 * A final block of input data may be passed. Calling with a zero length is also valid.
 *
 * The return code FLMRTC_LEN tells that the output buffer is too small.
 * In this case, you can provide a larger buffer to get the conversion done.
 * The required length for the output buffer is provided in the <code>outLen</code>
 * parameter.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRFINV' USING C-ID, C-RETCO.
 *                      C-INPLEN, C-INP,
 *                      C-OUTLEN, C-OUT.
 * </pre>
 *
 * @param [in]      cnv       POINTER Conversion handle from #FCROPNV()
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      inpLen    INTEGER Length of the input buffer
 * @param [in]      inp       POINTER Pointer to the input buffer
 * @param [inout]   outLen    INTEGER On input: Available space for the output buffer
 *                                    At output: If return code 0: length of the output buffer
 *                                               If return code FLMRTC_LEN: required minimum length for @p out
 * @param [out]     out       POINTER Pointer to the output buffer
 */
extern void FCRFINV(
   void**               cnv,
   int*                 rtc,
   const int*           inpLen,
   const char*          inp,
   int*                 outLen,
   char*                out);

/**
 * @brief Finish conversion of dependent data blocks (with locate)
 *
 * This function is identical to #FCRFINV(), except that the output buffer
 * is not user-provided. When the function returns, the buffer pointer
 * pointed to by the @p out parameter is set to a buffer that is large enough
 * to store the output data. As a result, the return code can never be FLMRTC_LEN.
 *
 * @param [in]      cnv       POINTER Conversion handle from #FCROPNV()
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      inpLen    INTEGER Length of the input buffer
 * @param [in]      inp       POINTER Pointer to the input buffer
 * @param [out]     outLen    INTEGER Length of the output buffer
 * @param [out]     out       POINTER Pointer to the output buffer pointer
 */
extern void FCRFINP(
   void**               cnv,
   int*                 rtc,
   const int*           inpLen,
   const char*          inp,
   int*                 outLen,
   char**               out);

/**
 * @brief Closes a file
 *
 * Opened files must be closed through this function after read or write
 * operations are completed. All internal buffers are flushed and all
 * allocated resources are released.
 *
 * The success flag, if set, allows the removal of the input file after closing
 * if the remove after close flag was set at read when opening the file. In
 * case of an error, it is usually not desirable to delete the original
 * file, but only if processing was successful. This flag tells the close
 * function whether processing was successful (success=1) or not (success=0).
 * At write the opposite behavior are implemented. If a write fails and the
 * remove switch is defined, then the file will be deleted.
 *
 * Statistics information can be requested by providing an output buffer.
 * The buffer is filled up to its maximum length. There is no second
 * chance to collect the missing statistics information if the buffer too
 * small. The @p format parameter specifies the output format and can be
 * set to one of the following output formats:
 *
 * * 1 - Simple list of strings with each line separated by \\n and the whole text terminated by 0x00
 * * 2 - As XML string (in local charset) of strings with each line separated by \\n and the whole text terminated by 0x00
 *
 * Sample call in COBOL:
 * <pre>
 * 01  FLUC-PARAMETER.
 *     02 F-ID     PIC S9(8)  COMP.
 *     02 F-RETCO  PIC S9(8)  COMP.
 *        88 FLUC-OK           VALUE  0.
 *        88 FLUC-EOF          VALUE  43.
 *     02  C-DELETE  PIC S9(8) COMP VALUE 0.
 *     02  C-STATFMT PIC S9(8) COMP VALUE 1.
 *     02  C-STATLEN PIC S9(8) COMP VALUE 4096.
 *     02  C-STATBUF PIC X(4096) VALUE SPACES.
 * CALL 'FCRCLS' USING F-ID, F-RETCO, C-DELETE
 *                     C-STATFMT, C-STATLEN, C-STATBUF.
 * </pre>
 * Sample call in PL1:
 * <pre>
 * DCL FCRCLS ENTRY EXTERNAL OPTIONS (ASM, FETCHABLE);
 * 2 F_ID       BIN FIXED(31,0) INIT (0)  ALIGNED,
 * 2 F_RETCO    BIN FIXED(31,0) INIT (0)  ALIGNED,
 * 2 C_DELETE   BIN FIXED(31,0) INIT (0)  ALIGNED,
 * 2 C_STATFMT  BIN FIXED(31,0) INIT (1)  ALIGNED,
 * 2 C_STATLEN  BIN FIXED(31,0) INIT (4096)
 *                                        ALIGNED,
 * 2  C_STATBUF CHAR(4096)      INIT ('40'X),
 * CALL FCRCLS ( F_ID,
 *               F_RETCO,
 *               C_DELETE,
 *               C_STATFMT,
 *               C_STATLEN,
 *               C_STATBUF );
 * </pre>
 *
 * @param [in]      hdl       POINTER File handle from #FCROPN()
 * @param [out]     rtc       INTEGER Return code
 * @param [in]      success   INTEGER True (not 0) if success else false (0) to manage remove of files if requested
 * @param [in]      format    INTEGER Format specification for the output buffer
 * @param [inout]   buflen    INTEGER Size/length of the output buffer (0 = no statistics)
 * @param [out]     buffer    STRING  Output buffer (data format depends on format parameter)
 */
extern void FCRCLS(
   void**               hdl,
   int*                 rtc,
   const int*           success,
   const int*           format,
   int*                 buflen,
   char*                buffer);

/**
 * @brief Closes a converter
 *
 * Opened conversion handles must be closed through this function after
 * read or write are completed. All allocated resources are released.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRCLSV' USING F-CNV, F-RETCO.
 * </pre>
 *
 * @param [in]      cnv       POINTER Conversion handle from #FCROPNV()
 * @param [out]     rtc       INTEGER Return code
 */
extern void FCRCLSV(
   void**               cnv,
   int*                 rtc);

/**
 * @brief Copy a memory area (MF-EDZ pointer handling workaround)
 *
 * The function #FCRCPY() was mainly implemented to copy memory pointed to by a
 * native pointer, which was provided by our locate functions, to local memory
 * of the using application as a workaround for the MF-EDZ pointer handling bug,
 * if AMODE=31 is used.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRCPY' USING
 *       BY REFERENCE F-LEN,
 *       BY VALUE     F-PTR,
 *       BY REFERENCE F-DAT.
 * </pre>
 *
 * @param [in]      len       INTEGER Length of the data
 * @param [in]      ptr       POINTER Data pointer from locate functions (#FCRLOC(), #FCRCONP(), ...)
 * @param [out]     dat       POINTER Pointer to local buffer with enough space to copy full length
 */
extern void FCRCPY(
   const int*           len,
   const char*          ptr,
   char*                dat);

/**
 * @brief Convert pointer to native format (MF-EDZ pointer handling workaround)
 *
 * The function below was mainly implemented to convert a local EDZ pointer
 * to a native pointer usable with external libraries as workaround for
 * the MF-EDZ pointer handling bug, if AMODE=31 is used.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL 'FCRPTR' USING
 *       BY REFERENCE F-DAT,
 *       BY REFERENCE F-PTR.
 * </pre>
 *
 * @param [in]      dat       POINTER Pointer to local data item
 * @param [out]     ptr       POINTER Pointer to native pointer value
 */
extern void FCRPTR(
   const char*          dat,
   const char**         ptr);

/**
 * @brief Determine current amount of processed data
 *
 * This function can be used to determine different statistical values
 * from a file or memory conversion handle. This can be used to control
 * the size of the output or how many records are read.
 *
 * The value returned is the current value from the corresponding component.
 * This value is normally calculated at the end of the processing of one
 * chunk of data. This means, that the data which is currently collected
 * to a chunk of data is not included. At write for example you can
 * control how many bytes are processed by the formatting component (XML
 * written). If a certain limit is achieved you can close the file or start
 * a new member, but the resulting size of the file or member will be
 * increased by the remaining rest of the data which are not yet processed
 * but collected in the buffers.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL  'FCRCNT' USING F-HDL, F-RTC, F-DIR, F-WHT, F-KND, F-VAL.
 * </pre>
 *
 * ATTENTION: The processed amount of data can be bigger than 4 GiB, the
 * value parameter is a 64 bit integer (must point to a 8 byte field).
 *
 * @param [in]   hdl POINTER File or memory conversion handle from #FCROPN() or #FCROPNV()
 * @param [out]  rtc INTEGER Return code
 * @param [in]   dir INTEGER Input (1) or output (2), if NULL then output
 * @param [in]   wht INTEGER File I/O (1) or Formating (2), if NULL the formatting
 * @param [in]   knd INTEGER Bytes (1) or Units (2), if NULL then bytes
 * @param [out]  val INTEGER The requested amount in 64 Bit (8 Byte)
 */
extern void FCRCNT(
   void**               hdl,
   int*                 rtc,
   const int*           dir,
   const int*           wht,
   const int*           knd,
   long long int*       val);

/**
 * @brief Initialize base encoding or decoding
 *
 * If base encoding needs to be run over several scattered junks of data
 * it can be done with the following calling sequence:
 *
 * <pre>
 *    FCRBINI()
 *    FCRBRUN()
 *    FCRBRUN()
 *    ...
 *    FCRBFIN()
 * </pre>
 *
 * #FCRBINI() will return an initialized handle for use in #FCRBRUN()
 * and #FCRBFIN().
 *
 * Sample call in COBOL:
 * <pre>
 * CALL  'FCRBINI' USING F-HDL, F-MODE, F-BASE, F-CHRS
 *                 RETURNING INTO F-RES.
 * </pre>
 *
 * @param [out]     hdl      POINTER     Handle to this encoding
 * @param [in]      mode     INTEGER     Mode: 1 is Encode and 0 is Decode (if NULL it defaults to Encode)
 * @param [in]      base     INTEGER     Base: possible values 16, 32 or 64 (if NULL it defaults to 16)
 * @param [in]      chrs     INTEGER     Character set: 1 is ASCII and 2 is EBCDIC otherwise the system character set is used
 * @return                   INTEGER     0 if success else error
 */
extern int FCRBINI(
   void**               hdl,
   const unsigned int*  mode,
   const unsigned int*  base,
   const unsigned int*  chrs);

/**
 * @brief En- or Decode a junk of data
 *
 * #FCRBRUN() will process a piece of binary data. The @p hdl must be
 * initialized by #FCRBINI() first. The output buffer must be big enough to
 * write the encoding. If it is too small the areas behind it will be
 * overwritten.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL  'FCRBRUN' USING F-HDL, F-DATLEN, F-DAT, F-OUT
 *                 RETURNING INTO F-RES.
 * </pre>
 *
 * @param [in]    hdl      POINTER     Handle to this encoding initialized before with #FCRBINI()
 * @param [in]    datlen   INTEGER     Length of @p dat (if NULL it defaults to 0)
 * @param [in]    dat      STRING      Input data chunk for en- or decoding
 * @param [out]   out      STRING      Output data chunk
 * @return                 INTEGER     >=0 produced output length else error
 */
extern int FCRBRUN(
   void**               hdl,
   const unsigned int*  datlen,
   const unsigned char* dat,
   unsigned char*       out);

/**
 * @brief Finalize en- or decoding
 *
 * #FCRBFIN() will process the last piece of data and write all buffered
 * data to @p out. The @p hdl must be initialized by #FCRBINI() first and
 * is released afterwards. The output buffer must be big enough to write the
 * encoding. If it is too small the areas behind it will be overwritten.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL  'FCRBFIN' USING F-HDL, F-DATLEN, F-DAT, F-OUT
 *                 RETURNING INTO F-RES.
 * </pre>
 *
 * @param [inout] hdl      POINTER     Handle to this encoding initialized before with #FCRBINI()
 * @param [in]    datlen   INTEGER     Length of @p dat (if NULL it defaults to 0)
 * @param [in]    dat      STRING      Input data chunk for en- or decoding
 * @param [out]   out      STRING      Output data chunk
 * @return                 INTEGER     >=0 produced output length else error
 */
extern int FCRBFIN(
   void**               hdl,
   const unsigned int*  datlen,
   const unsigned char* dat,
   unsigned char*       out);

/**
 * @brief Base encoding or decoding for one message
 *
 * The #FCRBASE() function does the same as #FCRBINI() and #FCRBFIN()
 * It is a shortcut if the input data is not scattered.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL  'FCRBASE' USING F-MODE, F-BASE, F-CHRS,
 *                       F-DATLEN, F-DAT, F-OUT
 *                 RETURNING INTO F-RES.
 * </pre>
 *
 * @param [in]      mode     INTEGER     Mode: 1 is Encode and 0 is Decode (if NULL it defaults to Encode)
 * @param [in]      base     INTEGER     Base: possible values 16, 32 or 64 (if NULL it defaults to 16)
 * @param [in]      chrs     INTEGER     Character set: 1 is ASCII and 2 is EBCDIC otherwise the system character set is used
 * @param [in]      datlen   INTEGER     Length of @p dat (if NULL it defaults to 0)
 * @param [in]      dat      STRING      Input data for en- or decoding
 * @param [out]     out      STRING      Output data
 * @return                   INTEGER     >=0 produced output length else error
 */
extern int FCRBASE(
   const unsigned int*  mode,
   const unsigned int*  base,
   const unsigned int*  chrs,
   const unsigned int*  datlen,
   const unsigned char* dat,
   unsigned char*       out);

/**
 * @brief Initialize hash calculation
 *
 * If a hash needs to be calculated over several scattered junks of data
 * it can be done with the following calling sequence:
 *
 * <pre>
 *    FCRHINI()
 *    FCRHADD()
 *    FCRHADD()
 *    ...
 *    FCRHFIN()
 * </pre>
 *
 * #FCRHINI will initialize the @p hdl parameter for use in #FCRHADD()
 * and #FCRHFIN().
 *
 * Sample call in COBOL:
 * <pre>
 * CALL  'FCRHINI' USING F-HDL, F-HMTD, F-KMTD,
 *                      F-KEYLEN, F-KEY,
 *                      F-ICVLEN, F-ICV
 *                 RETURNING INTO F-RES.
 * </pre>
 *
 * @param [out]     hdl      POINTER     Handle to this hash
 * @param [in]      hmtd     INTEGER     Hash method to use, for example #FLCHSH_ALGO_SHA1 see header FLMDEF.h
 * @param [in]      kmtd     INTEGER     MAC method to use, for example #FLCMAC_ALGO_HMAC see header file FLMDEF.h
 * @param [in]      keylen   INTEGER     length of @p key
 * @param [in]      key      STRING      key to use in hash calculation
 * @param [in]      icvlen   INTEGER     Length of @p icv
 * @param [in]      icv      STRING      Initial chaining vector (only for certain MAC calculation)
 * @return                   INTEGER     0 if success else error
 */
extern int FCRHINI(
   void**               hdl,
   const unsigned int*  hmtd,
   const unsigned int*  kmtd,
   const unsigned int*  keylen,
   const unsigned char* key,
   const unsigned int*  icvlen,
   const unsigned char* icv);

/**
 * @brief Add a junk of data to the hash calculation buffer
 *
 * #FCRHADD() will add a piece of binary data to the hash calculation.
 * The @p hdl must be initialized by #FCRHINI() first.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL  'FCRHADD' USING F-HDL, F-DATLEN, F-DAT
 *                 RETURNING INTO F-RES.
 * </pre>
 *
 * @param [in]      hdl      POINTER     Handle to this hash initialized before with #FCRHINI()
 * @param [in]      datlen   INTEGER     length of @p dat
 * @param [in]      dat      STRING      input data chunk to add to hash calculation
 * @return                   INTEGER     0 if success else error
 */
extern int FCRHADD(
   void**               hdl,
   const unsigned int*  datlen,
   const unsigned char* dat);

/**
 * @brief Finalize hash calculation
 *
 * #FCRHFIN() will store the calculated hash to the @p hsh parameter.
 * The @p hdl must be initialized by #FCRHINI() first and is released
 * afterwards. The parameter @ hshlen must contain on input the size
 * of the hash buffer and will contain on output the length of the hash.
 * If the output buffer shorter then the hash length, the hash will be
 * truncated.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL  'FCRHFIN' USING F-HDL, F-HSHLEN, F-HSH
 *                 RETURNING INTO F-RES.
 * </pre>
 *
 * @param [inout]   hdl      POINTER     Handle to this hash initialized before with #FCRHINI()
 * @param [inout]   hshlen   INTEGER     On input size of @p hsh on output length of p@ hsh
 * @param [out]     hsh      STRING      Buffer where calculated hash is written to
 * @return                   INTEGER     0 if success else error
 */
extern int FCRHFIN(
   void**               hdl,
   unsigned int*        hshlen,
   unsigned char*       hsh);

/**
 * @brief Calculate hash for one message
 *
 * The #FCRHASH() function does the same as #FCRHINI(), #FCRHADD(), #FCRHFIN()
 * It is a shortcut if the input data is not scattered.
 *
 * Sample call in COBOL:
 * <pre>
 * CALL  'FCRHASH' USING F-HMTD, F-KMTD,
 *                      F-KEYLEN, F-KEY,
 *                      F-ICVLEN, F-ICV,
 *                      F-DATLEN, F-DAT,
 *                      F-HSHLEN, F-HSH
 *                 RETURNING INTO F-RES.
 * </pre>
 *
 * @param [in]      hmtd     INTEGER     Hash method to use, for example #FLCHSH_ALGO_SHA1 see header FLMDEF.h
 * @param [in]      kmtd     INTEGER     MAC method to use, for example #FLCMAC_ALGO_HMAC see header file FLMDEF.h
 * @param [in]      keylen   INTEGER     Length of @p key
 * @param [in]      key      STRING      Key to use in hash calculation
 * @param [in]      icvlen   INTEGER     Length of @p icv
 * @param [in]      icv      STRING      Initial chaining vector (only for certain MAC calculation)
 * @param [in]      datlen   INTEGER     Length of @p dat
 * @param [in]      dat      STRING      Input data chunk to add to hash calculation
 * @param [inout]   hshlen   INTEGER     On input size of @p hsh on output length of @p hsh
 * @param [out]     hsh      STRING      Buffer where calculated hash is written to
 * @return                   INTEGER     0 if success else error
 */
extern int FCRHASH(
   const unsigned int*  hmtd,
   const unsigned int*  kmtd,
   const unsigned int*  keylen,
   const unsigned char* key,
   const unsigned int*  icvlen,
   const unsigned char* icv,
   const unsigned int*  datlen,
   const unsigned char* dat,
   unsigned int*        hshlen,
   unsigned char*       hsh);

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

/*! @cond PRIVATE */
#endif /* INC_FLCRECLB_H */

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