Chapter 3: User Exit Routines


About user exit routines

User exit routines allow a user to invoke a proprietary routine from within a map, providing a way for a user to perform additional functions called by mapping rules. The user exit routine behaves like a call-back mechanism in event-driven programs. The following files are provided to help the user create user exit routines.

The USEREX32.DLL file provided with the program contains one User Exit Function FCNV. The FCNV function will read a file that has lines terminated by CRLF or LF and write them out to another file with fixed line length specified by the cpRegBuf input parameter. To call the FCNV function, the User Exit CpuExitName must be equal to “FCNV”, and the cpRegBuf parameter should contain the new line length, the old file name and the new file name. These values should be separated by one space in the cpRegBuf input parameter. If the parameter CpuExitName does not equal “FCNV” then the supplied program will simply ring a bell and return.

To have the USEREX32.DLL file perform other functions, the user must write his or her own “user exit” routine and insert the code in the appropriate place in the USEREXIT.C file, which is supplied with ECRTP. The user then compiles the modified USEREXIT.C file to create a new USEREX32.DLL.

The USEREX32.LIB file allows the user to implicitly link to the DLL from a C program. The DEF file provides information. The C program is recompiled to create the DLL file after the user’s code has been inserted.

The USEREX32.DEF file is furnished for informational purposes only.

The annotated example provided with the installation is shown below. This example represents a very simple routine, which the user is expected to modify. The user’s code should be inserted where the code says “ring bell – user will add code here”.

/*----------------------------------------------------
* UserExit - Windows DLL and Unix shared library.
* This file and userdll.c and userexit.def are used for
* userexit.DLL.
* This file alone is used for UNIX shared library 
* userexit.sl
*-----------------------------------------------------
* USEREXIT function.
* Parameters:
* 	char cpuExitName - pointer to dynamically allocated * 			storage which contains the routine name. 
* 			This pointer should not be written to. 
*			This value can be used to determine what
* 			action should be done by USEREXIT() function.
* 	short sLanguage - will contain a 1 for Cobol or a 2
*			for 'C' language.
*	char *cpRegBuf - pointer to input buffer which 
* 			has been loaded with the value of a Memvar,
*			Record Field or Record Buffer.
* 			For 16 bit program the maximum record buffer 
* 			length is 3200 characters. For 32 bit program 
* 			the maximum record buffer length is 10000
*			characters.
*	char cpRetBuf - pointer to output buffer, where the 
* 			routine output of Memvar, Record Field or
*			Record Buffer should be placed.
*
*			Note cpRegBuf and cpRetBuf have been set to 
* 			point to the same large buffer. Empty input 
* 			cpRegBuf before writing to output cpRetBuf.
*
*
* 	char *cpStatus - pointer to dynamically allocated 
* 			storage which has been space filled and null 
* 			terminated to actual length of memvar of
*			status memvar. The user exit routine should
* 			be careful not to store more information 
* 			in the field than it can hold.
*
* parameter returns: cpRetbuf, and cpStatus.
* return value: none
*---------------------------------------------------*/
# ifndef NO_PROTO
  void fcnv(char *, char *);
#else
   void fcnv();
# endif



#ifndef
 UNIXextern "C" __declspec (dllexport)
void
WINAPI
USEREXIT(char *cpUExitName, short sLanguage, char *cpRegBuf,
   char *cpRetBuf, char *cpStatus)
#else
#if defined(__cplusplus)
extern "C"
#endif
void
# ifndef NO_PROT
OUSEREXIT(char *cpUExitName, short sLanguage, char *cpRegBuf,
   char *cpRetBuf, char *cpStatus)
# else
USEREXIT(cpUExitName, sLanguage, cpRegBuf,cpRetBuf, cpStatus)
char *cpUExitName;
short sLanguage;
char *cpRegBuf, *cpRetBuf, *cpStatus;
# endif
#endif
{
 	if(stricmp(cpUExitName, "FCNV") == 0)
   {
      fcnv(cpRegBuf, cpStatus);
   }
   else
   {
#ifndef UNIX
     MessageBeep(-1);   /* ring bell - user will add code here */
#else
    write(0,"\007", 1);   /* ring bell - user will add code here */
#endif
   }
}
/*********** File Conversion Program ******************
 ** UNWRAP.CPP - 11/11/98 													**
**--------------------------------------------------**
** THIS PROGRAM CONVERTS A SOURCE FILE OF VARIOUS LENGTH **
** RECORDS INTO THE USER'S DESIRED SIZE RECORDS. **
** PARAMETER 1 - USER'S DESIRED RECORDS SIZE.  	 **
** PARAMETER 2 - SOURCE FILE NAME 												 	**
** PARAMETER 3 - DESTINATION FILE NAME (CREATED BY PROGRAM)   **
**-------------------------------------------------**/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <io.h>
#include <process.h>
#include <windows.h>
#include <winbase.h>
#include <time.h>
#include <stddef.h>
#include <memory.h>



/*   ErrCondTYP  */
#define NoErrCOND 							1  /* normal completion, no
								 errors detected */
#define OpenErrCOND 							7  /* attempt opening an already
								 open file, */
#define FileMissingCOND    10 /*  operating system can't
									find file */
#define OtherCOND 							11 /*  other unspecified error
								 conditions    */
#ifndef NO_PROTO
lastchr(char *strng, int len);
#else
lastchr();
#endif



#ifndef NO_PROTO
void fcnv(char *xcmdline, char *cpStatus);
#else
void fcnv();
#endif
#define IMAX_BUF 1024
#ifndef NO_PROTO
void fcnv(char *xcmdline, char *cpStatus)
#else
void fcnv(xcmdline, cpStatus)
char *xcmdline, *cpStatus
;#endif
{
 	char *argvp[3];
 	unsigned char rdBfr[(IMAX_BUF + 2)];
   char arg1[302], arg2[302], arg3[302], buf[302];
   long rsize, lcnt, jcnt;



   FILE *srcfp, *dstfp;
   int at_eof, ich, k = 0, len, j, indx = -1;



   argvp[0] = arg1;
   argvp[1] = arg2;
   argvp[2] = arg3;
   memset(arg1, 302, '\0');
   memset(arg2, 302, '\0');
   memset(arg3, 302, '\0');
   len = lastchr(xcmdline, (int)strlen(xcmdline));
   if(len == 0)
   {
      sprintf(cpStatus, "%ld", OtherCOND);
      return;
   }
   while(k < len && indx < 2)
   {
      while (xcmdline[k] == ' ' && k < len)
         k += 1;
      j = 0;
      if(k < len)
      {
         indx += 1;
         /* Group single-quoted parameter as one argvp[] entry. */
         if (xcmdline[k] == '\'')
         {
            k += 1; /* skip first ' */
            while (xcmdline[k] != '\'' && j < 300 && k 
 				< len) buf[j++] = xcmdline[k++];
            k += 1; /* skip last ' */
         }
 		/* Group double-quoted parameter as one argvp[] entry. */
         else if (xcmdline[k] == '\"')
         {
            k += 1; /* skip first " */
            while (xcmdline[k] != '\"' && j < 300 && k < len)
               buf[j++] = xcmdline[k++];
            k += 1; /* skip last  " */
         }
         /* Normal argvp[] entry processing. */
         else while (xcmdline[k] != ' ' && j < 300 && k < len)
         {
            buf[j++] = xcmdline[k++];
         }
         buf[j] = '\0';
                  strcpy(argvp[indx], buf);
      }
   }
  /**------------------------------**
   ** Verify input parameter count **
   **------------------------------**/
   if(indx != 2)
   {
#ifdef UNIX
     printf("\nTHE FCNV UserExit REQUIRES THREE 
				PARAMETERS:\n");
     printf("PARAMETER 1 = NEW RECORD SIZE\n");
     printf("PARAMETER 2 = SOURCE FILE NAME\n");
     printf("PARAMETER 3 = DESTINATION FILE NAME\n");
#endif
     sprintf(cpStatus, "%ld", OtherCOND);
     return;
 } // END IF on number of parameters
  /**----------------------------------------**
   ** Convert the new record size to integer **
   **----------------------------------------**/
   rsize = atol(arg1);



 /**-----------------------**
   ** Open source file name **
   **-----------------------**/
   if ( (srcfp = fopen(arg2, "rb")) == (FILE *) NULL)
   {
#ifdef UNIX
       printf("ERROR OPENING FILE %s - Program Terminated\n", argv[2]);
#endif
       sprintf(cpStatus, "%ld", FileMissingCOND);
       return;
   }
  /**-------------------------**
   ** Create destination file **
   **-------------------------**/
   if( (dstfp = fopen(arg3, "wb")) == (FILE *) NULL)
 	{
#ifdef UNIX
      printf("ERROR CREATING DESTINATION FILE %s - 
				Program Terminated\n", arg3);
#endif
      sprintf(cpStatus, "%ld", OtherCOND);
      return;
   }
   at_eof = 0;
   /* lcnt is index into rdBfr */
   /* jcnt is index up to size of wrap and inserted CR LF */
   jcnt = lcnt = 0L;
	memset(rdBfr, 0, ( IMAX_BUF + 2) );



   while(at_eof == 0)
   {
 	/**------------------**
 	** Read source file **
 	**------------------**/
 	if( (ich = fgetc(srcfp)) == EOF && feof(srcfp))
      {
         at_eof = 1;
         continue;
      }
      if(ich == 10 || ich == 13)
      {
         continue;
      }
      rdBfr[lcnt++] = ich;
      jcnt += 1;
      if(jcnt >= rsize)
      {
#ifndef UNIX
         rdBfr[lcnt++] = 13;
#endif
         rdBfr[lcnt++] = 10;
         jcnt = 0;
      }



      if(lcnt >= IMAX_BUF)
      {
         if((fwrite(rdBfr, (size_t) lcnt, (size_t) 1, dstfp)) != 1)
         {
            fclose(srcfp);
            fclose(dstfp);
            unlink(arg3);
            sprintf(cpStatus, "%ld", OtherCOND);
            return;
         }
         lcnt = 0;
      }
   }
   if(jcnt != 0)  /* Need to pad out line */
   {
      while(jcnt < rsize)
      {
         rdBfr[lcnt++] = '\0';
         jcnt++;
         if(lcnt >= IMAX_BUF)
         {
            if((fwrite(rdBfr, (size_t) lcnt, (size_t) 1, dstfp)) != 1)
            {
               fclose(srcfp);
               fclose(dstfp);
               unlink(arg3);
               sprintf(cpStatus, "%ld", OtherCOND);
               return;
            }
            lcnt = 0;
         }
      }



#ifndef UNIX
      rdBfr[lcnt++] = 13;
#endif
      rdBfr[lcnt++] = 10;
   }
   if(lcnt > 0)
   {
     	if((fwrite(rdBfr, (size_t) lcnt, (size_t) 1, dstfp)) != 1)
      {
         fclose(srcfp);
         fclose(dstfp);
         unlink(arg3);
         sprintf(cpStatus, "%ld", OtherCOND);
         return;
      }
   }
   fclose(srcfp);
   fclose(dstfp);
   sprintf(cpStatus, "%ld", NoErrCOND);
   return;
}
 /* END main */
/*--------------------------------------------------*/
int
#ifndef NO_PROTO
lastchr(char *strng, int len)
#else
lastchr(strng, len)
char *strng;
int len;
#endif
{
   int i;
   char *ptr;



   if(len)
   {
      i = len -1;
      for(ptr = strng+i; ptr >= strng; ptr--)
      {
         if(*ptr != ' ' && *ptr != '\0') break;
      }
      i = (int) (ptr - strng + 1);
      return(i);
   }
   else
      return(0);
}