C functions provide capabilities that are useful to you as an RPG IV programmer.
Note: This article is an excerpt from the book Functions in Free-Format RPG IV, published by MC Press.
The data types used by C functions are nearly all integer, float, and null-terminated strings. RPG IV supports all integer and float data types, and can convert null-terminal strings to RPG character fields, and vice versa (using the %str BIF). The integer and float data types available with RPG IV make it easy to pass variable data back and forth between RPG IV and C.
One of the hurdles for RPG IV programmers is understanding the data types used by C and matching them to RPG IV's scheme. Typically, RPG programmers have only used zoned or packed decimal numeric fields. Table 3.1 describes how data types in the two languages relate to each other, including recommended RPG variable sizes.
Table 3.1: Most Common Data Types for C and RPG IV |
||
C Definition |
RPG IV Prototype Parameter Definition |
Notes |
int short |
5i 0 |
Signed integer, two bytes |
int long |
10i 0 |
Signed integer, four bytes |
unsigned int |
5u 0 |
Unsigned integer, two bytes |
unsigned int long |
10u 0 |
Unsigned integer, four bytes |
Float |
|
Floating-point, standard precision |
Double |
|
Floating-point, double precision |
Char * |
* |
Defined in RPG with the VALUE and Options(*String) keywords |
(*) |
* |
Defined in RPG with the VALUE and PROCPTR keywords |
Parameter Passing to C Functions
When passing parameters to another procedure, RPG normally uses a technique called passing by reference, which means that a pointer address is used. In the called program, the parameter field is a template over the "passed" field in the calling program. If you modify the variable in the called program, you are really modifying the field in the calling procedure.
The C language uses a parameter-passing technique called passing by value. In this scheme, the actual value of the parameter is passed. The value of the passed field can be changed in the called procedure, but the parameter field in the calling program is not changed. The RPG IV language can also pass parameters by value, simply by using the VALUE keyword for the parameter in the definition on the prototype.
A more flexible option is to use the keyword CONST instead of VALUE. This also passes parameters by value but has some additional features. The CONST keyword allows you to use fields of different data types (for numeric data types) and lengths as a parameter (different than the prototype), including the use of a constant.
Character String Differences Between C and RPG IV
The RPG IV language and C differ in their method of handling character strings. RPG IV uses fixed- or varying-length character fields. The C language uses an array of a variable length, with the last entry in the array a null character (hex '00'). If you use the Options(*String) keyword on the parameter in the prototype for a character field, the compiler places the RPG IV character field specified into a work area and then automatically adds the null character. The data in the work area is then passed to the C function.
Binding RPG IV and C Functions
After coding an RPG IV program with the proper prototypes and using an implicit call to the C function using the prototype(s), there is still one more step to "glue" the pieces together. The C functions are in service programs known only to IBM, but IBM has given us access to these programs via binding directory QC2LE. By simply putting Bnddir('QC2LE') on the H control specification, the binder will locate and include the C functions you have requested.
You must also specify an activation group, but not the default activation group, since you are using ILE's binding by reference. While you are testing your new program, use *New as the activation group. This helps avoid testing problems. Otherwise, named activations stay around and are used on subsequent calls, even if you recompile and replace the program.
Here's an example of an H control specification:
H Bnddir('QC2LE') Actgrp(*New)
This specifies that binding directory QC2LE be used during the binding phase and that activation group *New be applied when the program is loaded and run. When you are past the testing phase, a named activation group might be your best alternative.
Using C Functions to Make Your Job Easier
I was asked to help with a data conversion where the customer name in the "from" database was one big field, with spaces separating the parts of the name. In the "to" database, the name was divided into title, first name, middle initial, and last name fields. Other information about the "from" database included the following:
- Not every name had a title, but if a title existed, it was a standard title.
- A middle initial was optional, but if it existed, there was a period after it.
- Every character after the middle initial was part of the last name.
- If only one name appeared, it was the last name, not the first name.
Moving each part of the multi-part name field into the right new field became a programming project. It was accomplished completely in RPG IV, but a nagging inner voice kept saying to me, "This task could have been done more easily, somehow." After some research, I found a C function that could have helped: the Strtok (string token) function.
This is a parser-type function that helps in dividing portions of a character string. Something in the string has to be the delimiter, to tell the parser where one portion ends and the next begins. The C language calls these short string portions tokens. For example, using the Strtok function with the sentence "See Spot Run" and a space as the delimiter, you get "See" with one pass, "Spot" with a second pass, and "Run" with a third pass. This scheme would fit my data conversion situation pretty well, where blanks would be used to separate parts of the big name field. Of course, some logic would still need to be used to place each "token" item into its rightful place.
The Strtok Function
We'll review the most important elements of the new Strtok program in this section. (The entire program takes over a hundred lines of code, so it is not included here.) The field with the name to be parsed is FullName, defined 40A.
The first part of the main procedure is shown here:
h Bnddir('QC2LE') Actgrp(*New)
d GetToken pr * ExtProc('strtok')
d Name * Value Options(*String)
d Delimit * Value Options(*String)
It has the H control specification with the IBM binding directory QC2LE specified, and the activation group *New. Following that is the prototype for the Strtok C function. The return value is a pointer to the found token or a null pointer if no token is found. The two parameters are the field to be parsed and the delimiter.
The next section is a work array to hold all of the tokens, and a work field to hold the most current token:
d artok s like(FullName) dim(30)
d token s like(FullName)
The next few lines are work fields used in the procedure. The definition 5u 0 indicates an unsigned integer of five digits:
d ReturnAdr s *
d count s 5u 0
d Space c ' '
The count field defined here is used to count the number of tokens found, and used later in processing the token array elements.
The procedure begins by clearing the previous contents of the Title, FirstName, Initial, and LastName fields:
/free
//* Clear output fields
Clear Title;
Clear FirstName;
Clear Initial;
Clear LastName;
The procedure continues by first checking for all-blank input. Next, it left-adjusts the FullName field and then retrieves the first token from the FullName field:
If FullName <> *blank;
// Name is not all blank
// Shift Name to left, removing left blanks
FullName = %triml(Fullname);
ReturnAdr = GetToken(FullName:Space);
The function call GetToken here gets the first token. In the next section, GetToken gets the remaining tokens.
The next section is a loop to obtain and store the tokens of the FullName field:
Dow ReturnAdr <> *Null; // Load Tokens into Artok array
Token = %str(ReturnAdr);
Count += 1;
Artok(count) = %trim(Token);
ReturnAdr = GetToken(*Null:Space);
Enddo;
Notice that the return value for the C function is a pointer to the token. The %str BIF takes the null-terminated string and moves the characters into a regular character-field token. A count is made of how many tokens are saved in the array, to handle later processing. At this point, the tokens are stored in elements of the Artok array.
The use of the Strtok C function makes parsing the long FullName string very easy. The remainder of the program, not shown here, just puts the tokens in the correct output fields.
Exponentiation
There was a time when RPG could do little in the way of powers and roots. Powers were done by repetitive multiplications, and the only "root" capability was the square root. The use of C functions was the only solution for anything more complex. You might have done this.
It might seem contrary to bring this up in a chapter on using C functions, but the truth of the matter is that native RPG can now provide all you need in this mathematical arena.
With the advent of the ** (exponentiation) operator, all business formulas using an exponent can be done without using the C function library. In RPG IV, the exponentiation operator gives you the complete capability to determine the root or power of a number.
The form of an exponentiation operation is as follows:
Answer = number ** power;
In this formula, "power" can be a whole number, a fraction, or a mixed number. It can also have a negative sign.
Here are several examples of exponentiation, for your review:
/free
// Simple power and roots:
Area_Circle = 3.1416 * Radius ** 2;
// The above computes the area of a circle using the power 2
Cube_Root = 8 ** (1/3);
// The above line computes the cube root of 8, making Cube_root = 2
Future_Val_Annuity = Period_Amt * (((1+i)**n-1)/i);
// The above expression computes the future value
// of an annuity. i is the periodic rate, and n
// is the number of periods. With this formula, you can
// determine how much money you will have if you save
// Period_Amt for n periods at interest rate i.
As you can see, any formula needing exponents can be done without using C functions.
Summary
C functions provide capabilities that are useful to you as an RPG IV programmer. In particular, if you have a math requirement needing the use of trigonometry or other higher mathematics, the appropriate C function will make the overall programming much easier. Other specialized C functions, such as the random number generator, are helpful for special projects.
The example of the Strtok C function in this chapter shows that combining C functions with native RPG operations enhances your overall programming toolset.
LATEST COMMENTS
MC Press Online