ICOBOL USER LIBRARY 3.66 17-Jul-2008 A. Introduction The ICOBOL User Library (sometimes called icapi) allows users to write programs in other computer languages, usually C, to access COBOL indexed files (not sequential or relative, just indexed) through the ICOBOL interface. This interface allows the user programs to co-operate and share these files with ICOBOL processes. All the necessary calls to create, lock, open, read, rewrite, and write to the indexed files supported by ICOBOL are provided. To execute programs built using the Indexed Library, an ICOBOL API license with the IND_API option must be available from the license manager (ICPERMIT). The ICPERMIT_MACHINE environment variable can be used to direct licensing. In this section, the word scripts will be used to refer to Windows .BAT files and UNIX shell scripts. The user library API (Application Programmer Interface) was enhanced in revision 2.10 to return 32-bit status codes which includes the actual native operating system error number (if any) which caused the failure. *** NOTE *** The old interface is no longer supported The include file 'status.h' contains macro definitions for extracting the values of the various fields comprising a status code. The return type of all of the Indexed API routines is ic_api_status_t as defined in this include file. This file also defines the exit codes which are be returned by the 'ic_init_sys' function. The Indexed API file open functions 'ic_open_indexed' and 'ic_open_void_indexed' support all of the enhanced features of ICISAM indexed file support. The file specification structure includes an identifier entry which will be used to detect future upward compatible revisions of the specification structure. Under all UNIX platforms, the user library is packaged as a shared object, icuser.so, (.sl under HP-UX). The icuser.so shared object does have a dependency on the icsys.so. shared object (except on DG/UX 88K). When using shared objects you must ensure the objects can be found at runtime. The installic script in the examples subdirectory of the ICOBOL release can be used to install the icuser.so shared object. Under DG/UX 88K, icsys is inside of icuser.so. Under Windows, the user library is packaged as a .dll (icuser.dll provides a cdecl interface and icusers.dll provides a stdcall interface). When linking, the corresponding icuserv.lib or icusersv.lib import library should be used. The included sample program, indxsamp.exe, uses icusers.dll. To use either library, you must insure that the appropriate library is available at execution time, usually by copying the appropriate .dll to the system32 directory. *** NOTE *** The Watcom versions of the .lib files are still released, but no *** longer supported, only the Visual C versions are now supported. The .dll must be placed in the PATH used by your application. *** NOTE *** In addition, the PATH must include the location of the *** icsys.dll AND that icsys.dll must have the same revision as *** the icuser.dll or icusers.dll that your application is using. Your application files that use the user library should include the header files status.h, indexed.h, and system.h and they should define the symbol ICWIN32 before including these files. When using the indexed library, files can be opened via ICNETD by using an icnetd-type name as "@\\machine\dir\file". Where machine has an ICNETD running. 03/02/05 3.50 Added AIX, DG/UX 88K icuser.so support. 07/03/02 3.22 New calls ic_get_records_indexed and ic_get_delrecords_indexed added. Indsamp now uses the above calls. B. General Comments (1) All interfaces and type definitions used by the user library are contained in three header files: status.h - error handling macros and error definitions system.h - system runtime declarations indexed.h - indexed i/o declarations and definitions (2) All the ICOBOL User Library calls return a value of type status_t, indicating whether the call succeeded or failed. The return code will be moved into the Exception Status, and is defined as such: A zero return value means no error, A positive return value means an error occurred, and A negative return value means the operation was ok, but a status code is being returned to provide additional information. (3) To initialize the User Library the following calls must be made. These are: ic_init_sys (followed by) ic_init_indexed These "ic_init_" calls must be made before any of the indexed calls are attempted. These calls connect the process with the shared area set up by ICEXEC. Upon termination, corresponding calls must be made in the exact reverse order. These are: ic_term_indexed (followed by) ic_term_sys You should never terminate without making the appropriate "ic_term_" call for each of the "init_" calls that previously succeeded; otherwise, structures in memory could become corrupt, requiring that you shutdown and restart ICEXEC. (4) All the indexed calls correspond to their COBOL counterparts with the exception of ic_open_void_indexed and ic_update_indexed. The ic_open_void_indexed call allows the user program to open an indexed file that already exists without the user needing to know anything about the file other than its name. All the file's vital information is returned in the ic_indexed_file_spec_t structure. The ic_update_indexed call forces the file to be flushed to the operating system and the reliability bits cleared if the file had been modified. (5) Miscellaneous limits and options that the user program needs for the indexed files are defined in indexed.h that should be included in all sources that use the User Library. (6) The specification structure for an indexed file, ic_indexed_file_spec_t, is defined in indexed.h. It describes the file's vital information. The typedef, ic_indexed_key_spec_t, is a substructure that defines each key. The ic_indexed_file_spec_t must be provided to an ic_open_indexed to provide the specifications for the file. If the file already exists the specifications must match, with the exception of type and version fields which may be set to default (i.e., 0). If the ic_open_void_indexed call is used, none of the ic_indexed_file_spec_t structure is used but it is set to the file's vital information on the specified file. (7) Each call checks that the given parameters are valid for that particular call, if not, an error is returned. (8) The limit for the number of indexed files and the size of the buffers being used is determined by the current configuration used by ICEXEC. If ICEXEC is not running then 64 Indexed files and 256KB of buffers are used. C. Interface C.1. User Initialization ic_init_sys(proc_name) returns an int exit_code ic_term_sys() Where proc_name (char *) Specifies a character string specifying the name of the program that will be registered. The ic_init_sys call initializes the necessary information between the user program and the ICOBOL Indexed Library routines. Under UNIX and Windows NT/2000, this includes setting up the necessary information in the ICEXEC shared area. The ic_term_sys call must be called before terminating the program if a successful ic_init_sys had been executed. C.2. Indexed Initialization ic_init_indexed() ic_term_indexed() The ic_init_indexed call must be called before any other indexed calls can be made. The ic_term_indexed call must be called before terminating the program if a successful ic_init_indexed had been executed. It insures that all indexed files are closed and flushed. It should be called before ic_term_sys. C.3. Opening and Closing Files ic_close_indexed(handle) ic_open_indexed(filename_ptr, open_options, indexed_spec_ptr, handle_ptr) ic_open_void_indexed(filename_ptr, open_options, indexed_spec_ptr, handle_ptr) Where filename_ptr (char *) Specifies a pointer to a character string holding the name of the indexed file to open. The extensions `.xd' and `.nx' will be appended to this name when opening files. handle_ptr (ic_indexed_handle_t *) Specifies a pointer to a location where the file handle to be used on subsequent calls to refer to this open file for a successful open is stuffed. indexed_spec_ptr (ic_indexed_file_spec_t *) Specifies a pointer to a packet of information describing an indexed file. For ic_open_indexed this packet is passed in and if the file exists it must exactly match. For ic_open_void_indexed, upon a successful open, this packet is returned filled in with information from the specified indexed file that must already exist. open_options (short unsigned int) Specifies the type of open to perform using some combination of the IC_OPEN_.._INDEXED options. (IC_OPEN_INPUT_INDEXED, IC_OPEN_OUTPUT_INDEXED, IC_OPEN_CREATE_INDEXED, IC_OPEN_RECREATE_INDEXED, or IC_OPEN_EXCLUSIVE_INDEXED.) One of the open calls must be made for each file you wish to access in the program. An ic_close_indexed call must be called to close any indexed file that had been successfully opened with an open call. C.4. Reading ic_read_key_indexed(handle, key_number, key_ptr, key_length, record_ptr, record_length_ptr, read_options) ic_read_next_indexed(handle, record_ptr, record_length_ptr, read_options) ic_read_next_keyto_indexed(handle, record_ptr, record_length_ptr, read_options, keyto_ptr, keyto_length_ptr) ic_read_prev_indexed(handle, record_ptr, record_length_ptr, read_options) ic_read_prev_keyto_indexed(handle, record_ptr, record_length_ptr, read_options, keyto_ptr, keyto_length_ptr) Where handle (ic_indexed_handle_t) Specifies the file handle for the file that had previously been opened with an open call. keyto_length_ptr (short unsigned int *) Specifies a pointer to the size of the buffer pointed to by keyto_ptr. Its returned value is the actual number of bytes transferred to the buffer. keyto_ptr (char *) Specifies a pointer to a buffer to which the selected key value for the record is transferred. key_len (short unsigned int) Specifies the number of bytes from key_ptr to use in the lookup. key_number (short unsigned int) Specifies the number (0 for primary, 1 for first alternate, etc.) of the particular key to be looked up. key_ptr (char *) Specifies a pointer to the key string to be looked up for this particular key. read_options (short unsigned int) Specifies how the read should deal with record locking. Valid options are IC_NULL_OPTION_INDEXED or any or all of the IC_LOCK_ options except IC_LOCK_IGNORE_INDEXED cannot be set with either IC_LOCK_SET_INDEXED or IC_LOCK_CLEAR_INDEXED. Having both IC_LOCK_SET_INDEXED and IC_LOCK_CLEAR_INDEXED set allows for a program to read records locking one at a time while clearing the last lock before setting the next lock. record_length_ptr (short unsigned int *) Specifies a pointer to the size of the buffer pointed to by record_ptr. Its return value is the actual number of bytes transferred to the buffer. record_ptr (char *) Specifies a pointer to a buffer to which the record is to be placed. The "ic_read_" calls provide the mechanism to read records from files opened for input. The "ic_read_next_" calls will read the next sequential record in the file, the "ic_read_prev_" calls will read the previous record in the file as set by a previous read, start, or open. The ic_read_key_indexed call will allow the user to position to a particular record and read it. The "_keyto_" versions of these calls return the key value for the record that was read. C.5. Writing and Rewriting ic_rewrite_indexed(handle, record_ptr, record_length, rewrite_options) ic_write_indexed(handle, record_ptr, record_length, write_options) Where handle (ic_indexed_handle_t) Specifies the file handle for the file that had previously been opened with an open call. record_ptr (char *) Specifies a pointer to a buffer from which the record is to be written. record_length (short unsigned int) Specifies the number of bytes to be written. write_options (short unsigned int) Specifies how the write should deal with the record. Valid options are IC_UPDATE_FILE_INDEXED or IC_NULL_OPTION_INDEXED. rewrite_options (short unsigned int) Specifies how the rewrite should deal with the record. Valid options are IC_UPDATE_FILE_INDEXED or IC_NULL_OPTION_INDEXED. C.6. Miscellaneous Calls ic_delete_key_indexed(handle, key_ptr, key_length) ic_start_indexed(handle, start_options, key_number, key_ptr, key_length) ic_unlock_indexed(handle) ic_update_indexed(handle) ic_get_records_indexed(handle, record_cnt_ptr) ic_get_delrecords_indexed(handle, record_cnt_ptr) Where handle (ic_indexed_handle_t) Specifies the file handle for the file that had previously been opened with an open call. key_number (short unsigned int) Specifies the number of the particular key to be looked up. Valid numbers are 0 for the primary key, 1 for the first alternate, 2 for the second alternate, etc. This number cannot reference a key that does not exist. key_ptr (char *) Specifies a pointer to the key string to be looked up for this particular key. key_len (short unsigned int) Specifies the number of bytes from key_ptr to use in the lookup. It cannot be larger than the size of the key. start_options (short unsigned int) Specifies the kind of lookup to perform. Valid options are any one of the IC_START_options. (IC_START_EQL_INDEXED, IC_START_GEQ_INDEXED, IC_START_GTR_INDEXED, IC_START_LEQ_INDEXED, IC_START_LSS_INDEXED, IC_START_BEG_INDEXED, IC_START_END_INDEXED). record_cnt_ptr (long unsigned int *) Specifies a pointer to a long unsigned integer into which the number or records (ic_get_records_indexed) or the number of deleted/purged records (ic_get_delrecords_indexed) for the indicated file is returned. ICISAM rev 5 files will always return a 0 for the deleted count and currently network files (those open via ICNETD) will return 2**32 for the deleted count. The ic_delete_key_indexed call always works on the primary key. The ic_start_indexed positions to a particular position in the file based on the particular key value (key_ptr) looked up on a particular key (key_number) using a particular lookup (start_options). The length of the key_value may be smaller than the specified actual key size. The ic_unlock_indexed call clears all locks that have been placed on this file by this program on this handle. The ic_update_indexed call forces all modified data to the disk and clears the reliability bits. This can also be done as an option on the write and rewrite calls. D. Building an executable Under UNIX, the script 'ld_user.sh' describes how to link the application. Under Windows, the same script is 'ld_user.bat' or 'ld_users.bat'. E. Sample program (INDXSAMP.C) The included file, indxsamp.c, is a simple program that provides a few examples on how to connect, use, and disconnect from the ICOBOL User Library. Under UNIX, the script files cc.sh and ld_user.sh allow the sample program (indxsamp.c) to be compiled and linked to provide the executable, indxsamp. Under Windows, the script files cc.bat and ld_user.bat compile and link using the cdecl interface, while cc_std.bat and ld_users.bat compile and link using the stdcall interface. The sample program (indxsamp.c) can be compiled and linked with either method to provide the executable, indxsamp.exe. F. Miscellaneous Under UNIX, user written non-COBOL programs should be careful in how they open and use files (especially ICISAM files) that are in use by COBOL programs especially in posting UNIX locks on the files. ICOBOL uses UNIX locks to thread its way through files and any arbitrary use of these UNIX locks could cause ICOBOL processes to hang. End of readme