19 2 5 Example A Simple Averaging Function

LANSA Application Design

19.2.5 Example - A Simple Averaging Function

Defining a Built-In Function as a 3GL program

This section goes through the steps involved in creating a Built-In Function as a program. The example shown is very simple, but should give an insight to how LANSA uses a Built-In Function. 

SCENARIO: This is a User Defined Built-In Function. The Built-In Function is used to retrieve system values.

A simple C program. The program will be passed the system value name and will return the system value.

The name will be UD_AVERAGE

The next available identifier at this site is 413.

This Built-In Function might be accessed in the LANSA RDML language like this:

  define field(#number1) type(*dec) length(7)                
  define field(#number2) type(*dec) length(7)                
  define field(#mean) type(*dec) length(7)                   
                                                             
  request fields(#number1 #number2)                          
  use  ud_average with_arg(#number1 #number2) to_get(#mean)  
  pop_up  fields(#mean)                                      

Following is a C user-defined Built-In Function definition called UD_AVERAGE that receives 2 decimal values as arguments and returns their average value.

All arguments and return values are mandatory values.

While this Built-In Function is trivial and the example of its use is trivial, it is a simple starting point:

BIF Definition  (as per DC@F47 file on IBM i/ LX_F47 file on Windows)

BIF Name:

UD_AVERAGE

Unique Identifier:

413

Description:

Retrieve a system value

Call or Execute:

Program Name:

U_BIF413

Terminates between calls:

N     (Y or N)

Number of arguments:

2

Number of return values:

1

 

 

BIF Arguments  (as per DC@F47 file on IBM i/ LX_F47 file on Windows)
Parameter 1

BIF Name:

UD_AVERAGE

Parameter Type

ARG

Parameter Sequence:

1

Parameter Number:

1

Parameter Identifier:

A

Description:

First Value

Required / Optional:

R    (R or O)

Parameter Type:

N    (A, N or L)

Minimum Length:

7

Maximum Length:

7

Minimum Decimal:

 

Maximum Decimal:

 

Pass Length:

10

Pass Decimal:

 

Default:

 

 

 

Parameter 2

BIF Name:

UD_AVERAGE

Parameter Type

ARG

Parameter Sequence:

2

Parameter Number:

2

Parameter Identifier:

B

Description:

Second Value

Required / Optional:

R    (R or O)

Parameter Type:

N    (A, N or L)

Minimum Length:

7

Maximum Length:

7

Minimum Decimal:

 

Maximum Decimal:

 

Pass Length:

10

Pass Decimal:

 

Default:

 

 

 

BIF Return Values  (as per DC@F47 file on IBM i/ LX_F47 file on Windows)

BIF Name:

UD_AVERAGE

Parameter Type

RET

Parameter Sequence:

1

Parameter Number:

3

Parameter Identifier:

C

Description:

Mean Value

Required / Optional:

R     (R or O)

Parameter Type:

A     (A, N or L)

Minimum Length:

7

Maximum Length:

7

Minimum Decimal:

 

Maximum Decimal:

 

Pass Length:

256

Pass Decimal:

 

 

 

Now, enter the data into the Built-In Function definition files:

/* =============================================================== */
/* ========== USER DEFINED BUILT-IN FUNCTION DEFINITION ========== */
/* =============================================================== */
/*                                                                 */
/* This is a sample of how a user defined built-in function may be  */
/* defined. It is provided as an example only. No warranty of any   */
/* kind is expressed or implied. The programmer copying this code   */
/* is responsible for the implementation and maintenance of this    */
/* function, both initially and at all times in the future.         */
/*                                                                  */
/* User defined built-in functions are a powerful facility. However,*/
/* you should note that YOU are responsible for any impact the      */
/* use of a user defined built-in function has on the performance,  */
/* security, integrity, portability and maintainability of your     */
/* applications.                                                    */
/*                                                                  */
/* ================================================================ */
/*                                                                  */
/* Source File               : U_BIF413.C                           */
/* Entry Point Name          : U_Builtin_413                       */
/* Linked DLL Name           : U_BIF413.DLL                         */
/* Shared Object Name        : u_bif413.O                           */
/* OS/Dependencies           : Yes/No                               */
/*                                                                  */
/* Amendment History   :                                            */
/*                                                                  */
/* Task Id  Date    Description                                     */
/* =======  ====    ===========                                     */
/*                                                                  */
/* ================================================================ */
#define U_BIF_FUNCTION       U_Builtin_413
#define U_BIF_FUNCTION_NAME "U_Builtin_413"
#define U_BIF_DESCRIPTION   "This is a description of this built-in"

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

#include "x_glodef.h"
#include "x_glousr.h"

#ifdef X_OPERATING_SYSTEM_WIN
#include <windows.h>
#endif

#include "x_funstr.h"
#include "x_funpro.h"
#include "x_bif000.h"

/*==================================================================*/
/*                                                                  */
/* Arguments    : pX_Ids       - Standard X_IDS system definition   */
/*                pX_Pro       - Standard X_PRO process definition  */
/*                pX_Fun       - Standard X_FUN function definition */
/*                pX_Bif       - Standard X_BIF built-in definition */
/*                X_Fld[:      - Standard X_FLD field definitions   */
/*                X_List[:     - Standard X_LIST list definitions   */
/*                sInCount     - Number of arguments passed in      */
/*                sInVec[:     - Vectors of arguments               */
/*                sRetCount    - Number of return values            */
/*                sRetVec[:    - Vectors of return values           */
/*==================================================================*/
 X_VOID_FUNCTION U_BIF_FUNCTION ( U_BIF_STANDARD_PARAMETERS )
{

   /* ------------------------------------------------------------- */
   /* Handle a shutdown request (usually no activity is required)   */
   /* ------------------------------------------------------------- */
    if (U_BIF_SHUTDOWN_REQUEST)
   {
      U_BIF_SET_GOOD_RETURN
   }
   /* ------------------------------------------------------------- */
   /* Else perform the requested activity                           */
   /* ------------------------------------------------------------- */
    else
   {
      X_LONG lArg1;
      X_LONG lArg2;
      X_LONG lAverage;

      /* ------------------------------------- */
      /* Get argument 1 (C convention is 0)    */
      /* and argument 2 (C convention is 1)    */
      /* and compute their average             */
      /* ------------------------------------- */

       U_BIF_GET_ARG_AS_LONG (0,lArg1)
       U_BIF_GET_ARG_AS_LONG (1,lArg2)
       lAverage = (lArg1 + lArg2) / 2;

      /* ------------------------------------- */
      /* Return the result in return value 1   */
      /* (C convention is  0)                  */
      /* ------------------------------------- */

        U_BIF_SET_RET_FROM_LONG (0, lAverage);

      /* ------------------------------------- */
      /* Set a "good" return (Operating Level) */
      /* ------------------------------------- */
       U_BIF_SET_GOOD_RETURN
   }
   /* ------------------------------------------------------------- */
   /* Return control to caller                                      */
   /* ------------------------------------------------------------- */
    U_BIF_RETURN;
}

Some significant things to note about this example are:

  • The very extensive use of C macros. All the U_BIF_xxxx references are to macros contained in header (.H) file X_BIF000.H.

    These are expanded at compile time into C code. By using these wherever possible as your "interface" between your Built-In Function and the Visual LANSA definitions and call interface, you can protect your application from future changes.

    There are a number of U_BIF macros available. Refer to 19.2.8 Shipped U_BIF Macros for a complete list.
  • The definition of local variables by using types such as X_LONG. These definitions are contained in the standard header file X_GLODEF.H and are shipped with Visual LANSA. Variables passed into U_BIF macros should always be declared using these types (as indicated in the macro definition):
Variable Declaration Pointer Declaration Actual C Type involved

X_VOID

X_PVOID

Void

X_BOOL

X_PBOOL

Int

X_SHORT

X_PSHORT

Short

X_USHORT

X_PUSHORT

unsigned short

X_LONG

X_PLONG

Long

X_ULONG

X_PULONG

unsigned long

X_LONGLONG

X_PLONGLONG

LONGLONG in Windows: 64 bits signed Integer. Not recommended if used with WATCOMC

X_DOUBLE

X_PDOUBLE

double

X_CHAR

X_PCHAR

char (single character only)

X_VCHAR

X_PVCHAR

char ( > 1 character with a null/end of string terminator)

X_LIST_COUNT

X_LIST_COUNT *

Long

 

  • The use of the C numbering convention. By convention most C objects are numbered by offset (i.e. "N" things are numbered from 0 to N-1).

    This convention is used in all the U_BIF macros. So "Argument Number 3" is actually referenced in U_BIF macros as number 2.

    Generally this approach makes coding easier. For example, you might make this function more generic and receive from 2 to 20 numbers as arguments (i.e. no zero divide test is required). To do this you might change the body of the function to be like this:

 X_LONG lArgValue; 

 X_SHORT sTotalArgs; 

 X_SHORT sCurrentArg; 

 X_DOUBLE dTotal = 0;

 

 U_BIF_GET_ARGUMENT_COUNT (sTotalArgs)

 

 for (sCurrentArg = 0; sCurrentArg < sTotalArgs; sCurrentArg++) 

 { 

    U_BIF_GET_ARG_AS_LONG (sCurrentArg, lArgValue) 

    dTotal = dTotal + lArgValue; 

 }

 lAverage = dTotal / sTotalArgs;

 

 U_BIF_SET_RET_FROM_LONG (0, lAverage)

 

 U_BIF_SET_GOOD_RETURN 

}