Functions in Free-Format RPG IV

Functions in Free-Format RPG IV

by Jim Martin

NOOK Book(eBook)

$34.99 $59.99 Save 42% Current price is $34.99, Original price is $59.99. You Save 42%.
View All Available Formats & Editions

Available on Compatible NOOK Devices and the free NOOK Apps.
WANT A NOOK?  Explore Now
LEND ME® See Details

Overview

Written especially for programmers adopting a free-format style, this manual explores the role of functions in writing RPG IV programs. Demonstrating the potential of functions, many topics are explored such as details about existing RPG IV built-in functions, writing new functions, using ILE concepts to use C functions, and utilizing IBM API’s functions. Explaining how to write small programs, either as sub-procedures or modules, and how to gather those parts together to make programs that are easy to write and maintain, this is a natural next step for programmers familiar with a free-format style of coding.

Product Details

ISBN-13: 9781583476758
Publisher: Mc Press
Publication date: 03/01/2012
Sold by: Barnes & Noble
Format: NOOK Book
Pages: 250
File size: 3 MB

About the Author

Jim Martin was employed by IBM for 26 years writing applications primarily in RPG and as a programmer at the Rochester, Minnesota programming laboratory working on portions of CPF and OS/400. He is a frequent speaker at COMMON and is certified by IBM as an iSeries RPG IV specialist. He lives in Kansas City, Missouri.

Read an Excerpt

Functions in Free-Format RPG IV


By Jim Martin

MC Press

Copyright © 2009 Jim Martin
All rights reserved.
ISBN: 978-1-58347-675-8



CHAPTER 1

An Introduction to Functions

Make it right before you make it faster.

— Brian Kernighan and P. J. Plauger


The word "function" has been used for decades in the world of computer science. However, it was not used in the niche world of RPG programming until the mid-1990s. This is when the term "built-in function" entered the RPG programmer's lexicon, with the advent of RPG IV. The term was not altogether new, since Control Language (CL) had used the built-in functions %SST (substring) and %BIN (convert binary), and nearly all RPG programmers also write CL programs.



Today, the word "function" is used regularly in RPG technical manuals, articles, and presentations. Since a word can have many possible meanings, this chapter starts by defining "function" in the context of the RPG IV application development environment, and then compares a function to an operation code. The last section of this chapter breaks down a function into its two main components: a return value and parameters.


What Is a Function?

According to Merriam-Webster's dictionary, a function is defined as follows:

A computer subroutine; specifically: one that performs a calculation with variables provided by a program and supplies the program with a single result

This definition begs for a definition of "subroutine." Here it is, this time from:


A sequence of instructions for performing a particular task. Most programming languages, including most machine languages, allow the programmer to define subroutines. This allows the subroutine code to be called from multiple places, even from within itself (in which case it is called recursive). The programming language implementation takes care of returning control to (just after) the calling location, usually with the support of call and return instructions at machine language level. Most languages also allow arguments to be passed to the subroutine, and one, or occasionally more, return values to be passed back.

A function is often very similar to a subroutine, the main difference being that it is called chiefly for its return value, rather than for any side effects.


In the RPG IV language, subroutines use global variables, so they do not need parameters. Also, subroutines in RPG do not return anything, since programs can access all global variables. With the advent of RPG IV, the subprocedure facility meets most of the dictionary definition of a subroutine or function. You can pass parameters to a subprocedure and get one return value. Also, a subprocedure can call itself recursively, if desired.

RPG IV has two types of subroutines: the legacy version already discussed (dating from the early 1970s), and the new form, called a subprocedure. Together, these two types of subroutines provide programmers with the tools needed to modularize programs.

A function is similar to a procedure in that it has parameters and performs a particular task. The main difference between a function and a procedure is that a function has a return value. A review of RPG IV's built-in functions (BIFs) shows that most, but not all, meet the definition of a function exactly. If you have explored the capabilities of RPG IV subprocedures, you could accurately describe those with return values as "functions."


Functions vs. Operation Codes

It's not easy to compare functions and operation codes (op-codes), so let me break it down. Could functions be considered op-codes? The answer is somewhere between "no" and "sort of." Generally, an op-code performs something that is multi-step and fairly complex. For example, an I/O operation such as Read must do the following:

• Use one or more parameters (such as key arguments or a file name) to interface with the operating system.

• Wait for a response.

• Move data to fields and possibly to data structures.

In the case where end-of-file is reached, the op-code does not move data; instead, it sets an internal end-of-file flag. There is also the possibility of a record lock if the specified file has a file type of update. The Read op-code, then, is very complex.

How about the For op-code? It has many possible parameters. Upon entry, it must set its index, check to see if the index exceeds the limit imposed by a parameter, and determine where to go next — whether to go to the next sequential instruction or the instruction after Endfor. The For op-code, then, is also complex.

Prior to free-format RPG IV, there were many simple op-codes, such as sqrt, scan, cat, and subst. These simple, single-purpose op-codes become BIFs in free-format. Simple math operations became expression symbols, such as + (the plus sign) for addition and - (the minus sign) for subtraction.

Since built-in functions now perform the work previously done by op-codes, does that somehow make BIFs op-codes? No, but it reveals something about the modern RPG language. RPG has evolved from a fill-in-the-blanks report writer, to an operation-rich language, to the highly "functional" language that it is today.


Return Values

The preceding pages used the term "return value" without fully explaining the concept. It's time to do that now.

You probably know what a parameter is, and have passed parameters to a called program. Upon return, the value of one or more of the parameters might have changed. You might wonder, is this a return value? A parameter that changes its value when returning to the called program? The answer is no, not at all.

A simple BIF will help illustrate the concept of a return value. Here is a Read followed by a check for end-of-file:

Read filename;

If %oef(filename);

In this example, a Read operation is performed. Either a record is retrieved and placed in storage, or end-of-file is found. The If operation checks the value of its expression for true (or one). The expression is the BIF %eof, with the file name as a parameter. This BIF has a return value of data type indicator, which means that if we are not at end-of-file, the return value is zero. If we are at end-of-file, the return value is one. The return value replaces the BIF. In effect, then, the code would be either this:

If '0';

or this:

If '1';

In the first case, If '0' translates to false, so the If clause is bypassed. In the second case, If '1' translates to true, so the If clause is entered and performed.

Return values can be any data type, including indicator, character string, pointer, decimal, integer, date, and others. For example, the %alloc BIF returns a pointer data type. The %trim BIF returns a character string, and the %lookup BIF returns an unsigned integer. (BIF return values are explained in more detail in Chapter 2.)

When you write your own subprocedure, you can choose to have a return value of any data type. If you specify a return value, the subprocedure will have all the characteristics of a function, and the return value will be just as valid as with built-in functions. (Writing subprocedures is described in detail in Chapter 4.)


Function Parameters

As mentioned earlier, functions typically have parameters, also called arguments. The purpose of these parameters is to give the function a broader range of capability. For example, let's say you write a function (subprocedure) that returns the sales tax for your city and state. This function uses one parameter, a decimal amount field holding the total price (as input). As your business grows, you might need to compute the sales tax for other city/state combinations. By adding a city/state parameter to your function, you keep the sales-tax computation in one place. The function is given more breadth by having the additional parameter. Another way to explain this is to say the function has greater utility.

As another example, consider the %lookup BIF:

%Lookup(argument:array_name{:starting_index{:number of elements}})

This BIF is the array lookup function for an equal match between the first parameter and the array specified in the second parameter. A third parameter is for specifying a starting index (other than one). There is also a fourth parameter in the %lookup BIF that never existed in the Lookup op-code. This parameter specifies how many elements to search before stopping. If this parameter is not specified, the default value is the total number of elements defined for the array. The return value is an unsigned integer of the index of the element that matches the argument. Zero is returned if no match is found.

Most of the time, the default value for the fourth parameter is fine, but if you are using an array based on dynamic storage, you really need that fourth parameter. Therefore, the %lookup BIF has more capability than the op-code it replaced.

Validity checking of function parameters is done by the system for BIFs and by the prototype process for subprocedures and other called procedures. It's always possible to supply a valid parameter to a function, but provide a value that is invalid. It is up to the function to reject values that cannot be used in the function, requiring run-time error messages.

At some point in your development of functions, you might find yourself designing a function with eight, 10, or more parameters. At this point, I suggest you stop and ask yourself, why so many parameters? Perhaps your function, while returning just one value, is too large in its scope. For example, suppose you want to write a function that returns net pay, in a payroll application. That doesn't seem too difficult, until you realize how many parameters you'll need, including gross pay, marital status, exemptions claimed (both state and federal), federal taxes, state taxes, non-taxed deductions such as 401K and 503B, and many more. The determination of net pay, then, is not as easy as it first seemed. Perhaps you could still write the calculation as a module or subroutine. You could also write functions for federal income tax and state income tax.

Be careful not to write functions that require too many parameters. My rule of thumb is to keep the number of parameters under 10. An alternative is to write the big routines as modules, use ILE binding, and implement export /import for variables instead of a large number of parameters.


Summary

Functions are the next frontier in coding RPG IV. Break down your work and use RPG's BIFs as much as possible. Write your own functions in the form of subprocedures. Write code in smaller units, and use ILE to bind the pieces and provide excellent performance. Use the "return value" concept liberally, including nesting of functions within functions.

The next chapter provides examples of nesting BIFs. This concept works just as well for your own functions (subprocedures).

CHAPTER 2

Essential BIFs in Free-Format RPG IV


Don't sacrifice clarity for small gains in efficiency. — Brian Kernighan and P. J. Plauger


In the 2001 definition of free-format RPG IV, many fixed-format operations were removed. There is still controversy over the removal of many popular operation codes, notably Move, Movel, and MoveA. My first book, Free-Format RPG IV (MC Press, 2005), addressed this situation. Overall, however, most RPG programmers (even the old-timers) have come to appreciate the virtues of free-format.

As of V6.1 of the i operating system, there are 116 fixed-format op-codes, but only 61 free-format op-codes. Many of the "missing" op-codes have been replaced with one or more built-in functions (BIFs). For example, the SUBST op-code is now the %subst BIF, in free-format. The LOOKUP op-code could be any of 10 BIFs in free-format RPG IV! In other words, if you write programs in free-format RPG IV, you must use BIFs to accomplish the needs of your programs. It's clear that a paradigm shift in RPG IV programming has occurred, away from an op-code style coding environment. Embracing the free-format style of programming means embracing function-oriented coding.


Different Uses for Built-in Functions

Built-in functions provide an essential part of free-format procedures. BIFs provide some new programming capabilities, as well as just doing the work previously performed by op-codes or resulting indicators. An important use of BIFs is the role they play in definition specifications. Many BIFs are referenced in the remainder of this chapter. For more details on these BIFs, refer to Appendix B in this book.

BIFs Used in Definition Specifications

At compile time, six BIFs can be used to help set initial values or the dimension size for arrays.


The %size BIF

The %size BIF returns the number of bytes of the named parameter. If the second parameter, *All, is specified, the total number of bytes of an array or data structure is returned. This BIF can be used as the value of the INZ keyword or the DIM keyword.


Here is an example:

D Name
S 30
D Name len S 5u 0 Inz(%size(Name)
D Array
S 1
Dim(%size(Name))

In this example, the variable Namelen is initialized to 30, the size of the parameter Name. The variable Array (an array) is defined with 30 elements.

Be extra careful with %size. It returns the number of bytes, which is different than the length for many data types. The examples in Appendix B illustrate the values returned for different data types.


The %len BIF

The %len BIF returns an unsigned integer of the defined or current length of a field. This BIF can be used in setting an initial value (with the INZ keyword) or a dimension size (with the DIM keyword).

Here is an example:

D Amount
S 9P 2
D Amountlen S 5u 0 Inz(%len(Amount))
D Array
S 11
Dim(%len(Amount))

In this example, the variable Amountlen is initialized to nine, the length of the parameter Amount. The variable Array (an array) is defined with nine elements.


The %decpos BIF

The %decpos BIF analyzes the numeric parameter specified and returns the number of decimal positions of the numeric variable or expression. This BIF could be used as the parameter in the INZ keyword.

Here is an example:

D Amount
S 15 5
D Amountdp S 5u 0 (Inz(%decpos(Amount))


In this example, the variable Amountdp is initialized to five, the number of decimal positions of the parameter Amount.


The %addr BIF

The %addr BIF returns the memory address of the variable specified as a parameter. This BIF could be used to set the initial value of a pointer variable, using the INZ keyword.

Here is an example:

D IndPtr S * Inz(%addr(*N))

The pointer variable IndPtr is initialized to the address of the indicator array, *IN. Indicators can now be accessed using the pointer.


The %paddr BIF

The %paddr BIF returns the procedure address pointer of the named procedure. This BIF could be used to set the initial value of a procedure pointer, by using the INZ keyword.

Here is an example:

D ExHandPgm S * Procptr
D
Inz(%paddr('EXHANDLER'))

In this example, the procedure pointer ExHandPgm is initialized to the procedure address of program EXHANDLER. This is especially useful when calling IBM APIs.


The %elem BIF

The %elem BIF returns the number of elements of the named array, table, dimensioned data structure, or multi-occurrence data structure. This BIF could be used to set the initial value of a field using the INZ keyword, or the dimension size using the DIM keyword.

Here is an example:

D Array
S 9p 2 Dim(200)
D NewArray S 5
Dim(%elem(Array))
D Array
S 5u 0 Inz(%elem(Array))

In this example, the variable NewArray (an array) is defined with the same number of elements (200) as its parameter, Array. The variable NumElem is initialized to the value of the number of elements of array Array, which is 200.


BIFs in a Procedure, by Return Value

The BIFs in RPG IV can be categorized several ways. In Appendix B, for example, they are listed in alphabetical order. In this section, however, I have chosen to organize BIFs by their return value. A return value is a common function attribute. In this concept, the return value takes the place of the function after the function has performed its work. Some BIFs do not use a return value. These BIFs (discussed separately in a later section of this chapter) include those used for date manipulation, lists, and XML.


The Indicator Return Data Type

The indicator data type is a Boolean, defined with two values, zero and one. These values correspond identically to the values of named or numbered indicators as you have typically used them in your programs. These values are also known by their figurative constant names, *Off and *On. In hexadecimal, they have the values x'F0' and x'F1', and in EBCDIC, they are defined as character 0 and character 1.

Expressions used in conditional op-codes, such as If and Select/When, use an indicator data type (Boolean) as the result of the expression. Here is an example:

If AmountDue > Payments;

In this case, if the AmountDue value is greater than Payments, then the expression is said to be "true," which translates to a value of one. If it is not true, then the expression translates to a value of zero. A BIF that returns an indicator data type can be used directly as the conditional expression, if you want to process on a true condition.

An assignment statement that has an indicator data type to the left of the equal sign will accept a BIF returning an indicator data type. Here is an example:

Sflend = %eof(datafile);

Many RPG IV built-in functions return a value of the indicator data type. Table 2.1 lists these BIFs.


(Continues...)

Excerpted from Functions in Free-Format RPG IV by Jim Martin. Copyright © 2009 Jim Martin. Excerpted by permission of MC Press.
All rights reserved. No part of this excerpt may be reproduced or reprinted without permission in writing from the publisher.
Excerpts are provided by Dial-A-Book Inc. solely for the personal use of visitors to this web site.

Table of Contents

Contents

Title Page,
Copyright Page,
Dedication,
Acknowledgements,
Preface,
CHAPTER 1 An Introduction to Functions,
CHAPTER 2 Essential BIFs in Free-Format RPG IV,
CHAPTER 3 Using C Functions,
CHAPTER 4 Subprocedures,
CHAPTER 5 Using Prototyping and ILE to Connect the Functional Parts,
CHAPTER 6 Coding RPG IV the Modular [and Functional Way,
APPENDIX A - Free-format RPG IV Coding Standards and Recommendations,
APPENDIX B - Built-in Functions Reference,
More RPG Books from MC Press,
Your Source for Everything IT,

Customer Reviews

Most Helpful Customer Reviews

See All Customer Reviews

Functions in Free-Format RPG IV 0 out of 5 based on 0 ratings. 0 reviews.