#### 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: C 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;
}

• 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

}