RPG Developer Network News
www.RPGIV.com

It's not your father's Q38
(c) 1999 by Robert Cozzi Jr. All rights reserved.

Monday, February 1, 1999

Editor: Robert Cozzi, Jr.

Adding High-Level Math to RPG IV
Interfacing with the C Language is easy with prototypes


Add High-level Math to RPG IV – The Easy Way

A few years ago Jon Paris, an IBM retiree who know hangs his hat at HAL North America, outside of Toronto, Ontario Canada, started enhancing RPG IV by adding interfaces to the C language. Jon provided interfaces to the C runtime library to perform dynamic memory allocation. These interfaces included MALLOC, REALLOC, and FREE. While RPG IV now supports this function natively, via ALLOC, REALLOC, and DEALLOC, Jon's techniques are portable from V3R2 to the upcoming V4R4.

Since Jon told me about these techniques, I've wanted to add support to RPG IV to do high-level math functions. Jon also wanted these interfaces published, but didn't have the free time or the familiarity with C to complete them. So we talked about it, and decide I would do it.

Binding Directories, A Way of Life

The first thing you should be aware of when building RPG IV applications with multiple modules (source members) is the binding directory. Binding directories contain lists of either modules or service program objects. The AS/400 binder uses these objects to compile RPG IV programs.

A binding contains only a list of the modules or service programs, not the actual objects. So as new versions or fixes or introduced, the latest object is used by the compilers. Another wonderful byproduct of binding directories is that you don't have to specify a long list of module names for the program your compiling.

While you can create your own binding directories, which is something I do for each application I create, you can also take advantage of a binding directory that is provided with all AS/400 systems. That binding directory name is QC2LE.

QC2LE Binding Directory

There is a special binding directory on your AS/400 named QC2LE. It contains a list of modules and service programs needed for the C language runtime environment.

The C language has several interesting methods for evoking a procedure call, fortunately one of these methods allows the procedure to be called via a pointer to a procedure. Consequently, the functions for the C runtime library are stored in service programs. This is where the binding directory comes in. IBM provides with OS/400, the QC2LE binding directory. In this binding directory is a list of all the modules and service programs that make up the C runtime library.

Since the C runtime library is stored in modules and service programs, binding to them is as easy as writing and RPG IV procedure prototype. In fact, it is so easy to interface RPG IV with C, that I tend to claim that the RPG IV language now natively supports everything in the C language. Take that you C bigots!

Reading C Function Prototypes

The easiest way to call an ILE procedure in RPG IV is to write a prototype for that procedure. Since all C language functions are actually ILE procedures, simply writing a prototype is all we have to do. Let's look at a simple math function in C, the sine function.

In the C language, the sin() function returns the sine, in radians, of the value specified as the first and only parameter of the function. In C the parameters are double precision floating point values. Since the C language uses natural expression syntax, the syntax for a prototype, written in C for the sin() function is as follows:

double sin( double );

When used in the C language, this prototype would call the sin function stored in the C runtime library. An example of this call would be something like this:

double deg;
double mySine;
mySine = sin( deg );

The first two lines declare the fields named "deg" and "mySine". They both have a data-type of double. The third line is similar to the EVAL opcode in RPG IV. It calls the sin() function, passing to it the value of the deg field. Upon return, the function is effectively replaced with the sine of the value stored in deg. The equals sign causes that value to then be stored in the mySine field.

Translating C Prototypes to to RPG IV Prototypes

Knowing the C syntax and knowing RPG IV should allow you to translate this prototype for the sin() function to RPG IV. We need a procedure prototype that will evoke the sin function. It must accept one parameter. The parameter must be a double precision floating point value. RPG IV uses the "F" for floating point values, and they are double-precision floats. The following RPG IV code is the prototype for the sin function.

.....DName+++++++++++EUDS.......Length+TDc.Functions++++++++++++++++++++++++++++
     D sin             PR                  extproc('sin')
     D parm1                           F   value

 

The first line in this prototype contains the name of the prototype, and the EXTPROC keyword. Normally, prototypes don't contain the EXTPROC keyword, as this keyword is the default. However, since the name of the sine function in the C language is 'sin' (all lowercase letter) and RPG IV automatically converts all non-quoted source code to uppercase, we need to specify the EXTPROC keyword with 'sin' enclosed in quotes.

The second line of the RPG IV prototype declares the parameter. This parameter is a floating-point value, whose data-type is "F". Note the VALUE keyword. This informs the compiler that this parameter is passed to the function by value, not by reference. C functions default to pass-by-value, which is the opposite of AS/400 and RPG IV functions, which default to pass-by-reference.

To use this math function in RPG IV, we use the sin procedure just like and procedure we would write or IBM-supplied built-in function. For example:

.....C*Rn01..............OpCode(ex)Extended-factor2+++++++++++++++++++++++++++++
     C                   Eval       mySine = sin( deg )
     C                   eval       *INLR = *ON
     C                   return

The result of this returns the sine of value in the deg variable.

Does this seem too easy? Well it is this easy. The only other thing you need in order to use the C function in your RPG IV program is to specify BNDDIR(QC2LE) when compiling. Both the CRTBNDRPG and CRTPGM commands support this parameter.

I have created the RPG IV prototypes for all the high-level math routines that are available with the IBM AS/400 C/400 compiler. In most cases, the functions require only one parameter: a "double" or floating-point value. This parameter is passed by value. Since it is passed by value, RPG will convert non-floating point values into floating point before evoking the procedure. Hence, you can specify the following:

.....C*Rn01..............OpCode(ex)Extended-factor2+++++++++++++++++++++++++++++
     C                   Eval      mySine = sin( 3.50 )

 

All these routines return their value in degrees radian.

To download the RPG IV source code for the C library math functions, click the links that follows. To view documentation on these routines check out the IBM AS/400 C/400 runtime library manual, or click here to view the ANSI documentation for these C functions. Note the UNIX/ANSI documentation is somewhat vague.

Source Member Description
Mathproto.rpgle RPG IV prototypes for the C language runtime library.

This is a /COPY source member.

Mathrpg.rpgle Example RPG IV program that calls all the C language runtime math routines.
datatype.rpgle Used to include "primitive" data-type variables such as INT, LONG, SHORT, DOUBLE and PTR. These fields are used with the LIKE keyword, for example"

D/COPY datatype
D myValue     S                  Like(int)

This is a /COPY source member.