introduction to rpg

35
INTRODUCTION TO RPG Over the years, the RPG programming language has evolved from strictly a reporting tool (not too different in scope from today's Query/400) to a robust, full-featured language. In version 3, release 1 (V3R1) IBM introduced a new version of RPG named ILE RPG for AS/400. This release was perhaps the most significant since the original inception of the language. There is often a great deal of confusion about the naming convention of the RPG versions. The terms RPG ILE and RPG IV are often used interchangeably, and in truth, they are the same product. However, there is a difference between RPG IV and RPG ILE. The way I like to explain this is that RPG IV is simply the next version of RPG. After this will be RPG V. RPG IV has a whole host of improvements over RPG III (also known as RPG/400) many of which we'll be covering later on. ILE on the other hand is a set of functionality that exists across multiple programming languages (C, CL, Cobol). ILE stands for Integrated Language Environment. It gets it's name from the ability to create a single program using multiple programming languages. Therefore, RPG IV is ILE compliant. Calling the language RPG ILE is not really sufficient, as when RPG V is released, it will be ILE compliant as well. Throughout this document however, the terms RPG IV and RPG ILE may be used interchangeably. The ILE functionality of RPG IV provides a vast number of functional, performance, maintenance, and productivity benefits to the RPG programmer (not just the ability to integrate multiple languages). We've included an ILE primer to give a brief overview of the concepts and benefits of ILE. However, the enhancements can be a bit overwhelming, especially if you have no experience with object oriented programming languages such as Java or C++. Although not truly object oriented, ILE does provide many of the benefits of object-oriented languages. Therefore, it is recommended that an RPG III programmer begin exploration of RPG IV with the non-ILE specific language elements. As you begin to get comfortable with the new features and layouts, then explore the benefits of ILE. Putting ILE functionality aside for the moment, RPG IV has a number of enhancements from RPG III that justify making the switch. Longer field names Source level debugging

Upload: subashdot

Post on 24-Oct-2014

91 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Introduction to Rpg

INTRODUCTION TO RPG

Over the years, the RPG programming language has evolved from strictly a reporting tool (not too different in scope from today's Query/400) to a robust, full-featured language. In version 3, release 1 (V3R1) IBM introduced a new version of RPG named ILE RPG for AS/400. This release was perhaps the most significant since the original inception of the language.

There is often a great deal of confusion about the naming convention of the RPG versions. The terms RPG ILE and RPG IV are often used interchangeably, and in truth, they are the same product. However, there is a difference between RPG IV and RPG ILE. The way I like to explain this is that RPG IV is simply the next version of RPG. After this will be RPG V. RPG IV has a whole host of improvements over RPG III (also known as RPG/400) many of which we'll be covering later on.

ILE on the other hand is a set of functionality that exists across multiple programming languages (C, CL, Cobol). ILE stands for Integrated Language Environment. It gets it's name from the ability to create a single program using multiple programming languages. Therefore, RPG IV is ILE compliant. Calling the language RPG ILE is not really sufficient, as when RPG V is released, it will be ILE compliant as well. Throughout this document however, the terms RPG IV and RPG ILE may be used interchangeably.

The ILE functionality of RPG IV provides a vast number of functional, performance, maintenance, and productivity benefits to the RPG programmer (not just the ability to integrate multiple languages). We've included an ILE primer to give a brief overview of the concepts and benefits of ILE. However, the enhancements can be a bit overwhelming, especially if you have no experience with object oriented programming languages such as Java or C++. Although not truly object oriented, ILE does provide many of the benefits of object-oriented languages.

Therefore, it is recommended that an RPG III programmer begin exploration of RPG IV with the non-ILE specific language elements. As you begin to get comfortable with the new features and layouts, then explore the benefits of ILE.

Putting ILE functionality aside for the moment, RPG IV has a number of enhancements from RPG III that justify making the switch.

Longer field names Source level debugging Date and time support Additional data types (floating point, boolean, pointers) Free-format expressions Built in functions Case tolerance

The quickest and easiest way to get started with RPG IV is to convert an existing RPG III program and explore that.

Converting To RPG IV:

Because there are syntax differences, IBM has included the CVTRPGSRC command to automatically convert RPG III source code to RPG IV. Before using this utility, you should create new source files (or change your existing ones) to have a record length of 112 bytes. This is necessary because the format of source records was changed to support expanded field names and op-codes.

Enter the CVTRPGSRC command in the following format:

Page 2: Introduction to Rpg

CVTRPGSRC FROMFILE(library/source-file) FROMMBR(source-member)TOFILE(library/source-file) TOMBR(source-member)

The FROMFILE and FROMMBR parameters should indicate the old RPG III source file and member. The TOFILE and TOMBR parameters should indicate the name and location where the generated RPG IV source code will be placed.

Note: If this is the first time the CVTRPGSRC command has been run on your system, you may get an error message stating "Log file QRNCVTLG in library *LIBL not found". If this is the case, either (a) use the Create Duplicate Object command (CRTDUPOBJ) command to copy the existing log file QARNCVTLG from library QRPGLE to a log file named QRNCVTLG in the library in your library list, or (b) specify LOGFILE(*NONE) on the CVTRPGSRC command.

When the command completes, you will have an RPG IV version of the program in the specified location. Note that if you have any "/copy" statements in your program, the copy member(s) will also need to be converted.

The CVTRPGSRC command will simply convert your RPG III code line-by-line to RPG IV syntax. It will not automatically update your code to use the enhanced RPG IV op-codes (such as Eval) .

Note: There are third party conversion utilities on the market (reasonably priced) that will automatically convert your code to use some of the RPG IV language elements. These utilities do a good job, but you should be careful, as there may be undesired effects when switching to the new RPG IV op-codes. We'll cover some of these effects in the next few sections.

Start by converting a small, working program that you are familiar with and look at the results. Use PDM option 14 to compile the program. Notice that the command CRTBNDRPG (Create Bound RPG Program) is used instead of CRTRPGPGM (Create RPG Program). This is a one-step compile process, as opposed to the two-step process we'll cover in the ILE section. Your program should compile and run normally.

Now, go back to the original RPG III program and add a data-structure and a table or array. Perform the conversion again and see how it converted those elements.

Before you proceed to the language element sections, there are a few important points you should know about the differences between ILE programs and Original Program Model (OPM) programs.

OPM Vs ILE:

Versions of RPG prior to RPG IV ILE use what IBM has dubbed the Original Program Model (OPM). OPM's counterpart is ILE (Integrated Language Environment). OPM is characterized by the structure of one source member being compiled into one executable program (figure 1).

ILE on the other hand requires a two-step process to create programs. Source members are first compiled into module objects (type *MOD). For RPG, the command CRTRPGMOD (create RPG module) or PDM option 15 is used. Modules can be thought of as sub-programs. They are validated and compiled machine code, but are not

Page 3: Introduction to Rpg

executable. One or more modules must then be bound into an executable program using the CRTPGM (create program) command (figure 2).

Note that modules created using different programming languages may be bound into the same program object. We'll cover the specific procedures for doing this and the advantages that the ILE environment provides in later sections. For now, it is only important to know that this is the structure of ILE programs.

This structure applies, even if the one-step CRTBNDRPG (create bound RPG) command is used to compile the program. In fact, you can think of the CRTBNDRPG command as a "wrapper" around both the CRTRPGMOD and CRTPGM commands. The module is created in library QTEMP and the two-step process is transparent to the user (figure 3)

It is important to keep in mind this hierarchy of ILE programs. Lets say for example that we want to use the WRKPGM command (work with programs) to determine the change date of the source member was used to create a program. If the program is OPM, we can simply display the program's attributes.

On the other hand, if the program is ILE, source members are not directly associated to a program. Instead a source member is used to create a module, and one or more modules are used to create a program. Displaying a program's attributes shows - among other things - the module(s) used to create the program. By displaying the module's attributes (this can all be done through the WRKPGM command) we can determine the source information. Keep in mind that we need to go through this extra step because one ILE program may actually be created from multiple source members.

Also note that the CRTBNDRPG command creates the module in library QTEMP. This seems to imply that once the program is created, the module is no longer needed. This is indeed true. The program object contains a complete copy of the module. The exception to this is when service programs are used. Service programs are a slightly more

Page 4: Introduction to Rpg

advanced concept that allows program to be created with references to modules instead of actually making a separate copy of them.

All this information is covered in much more detail in the ILE section. Now that you have a decent understanding of the differences between OPM. The next step is to familiarize yourself with the language differences between RPG III and RPG IV.

RPG IV Language Elements:

There are several changes you'll immediately notice when editing RPG IV programs with the Source Entry Utility.

Case-tolerance

If you experiment with changing the RPG IV source code, one of the first things you'll notice is that RPG IV is case-tolerant. Note that being case-tolerant is different from being case-sensitive. Variable names, op-codes, etc. are recognized as being the same regardless if they're upper-case, lower-case or mixed-case. For example, each of the three examples below are considered the same:

Z-ADD *ZERO ITEMNUMBERz-add *zero itemnumberz-add *zero ItemNumber

Note that case-tolerance does not apply to literals within quotes. For example:

call 'PROGRAM'

is NOT the same as:

call 'Program'

As with many of the features in RPG IV/ILE, usage of capitalization is left to your discretion. You may want to establish a capitalization standard for your shop. One word of caution however, not all programmers are efficient typists. Try to establish your standards so they don't inhibit programming productivity. My personal preference is to only use capitalization to improve readability of program field names and imbedded SQL statements.

Long field names

One of the most appreciated features of RPG IV is the ability to use long field names. RPG III had a restriction of 6 characters for field names. This led to some very cryptic naming conventions, especially for multi-level break reports.

You'll be happy to know that field-name length restrictions have virtually been eliminated. As of V4R5 the maximum field length is 4,096 characters! Keep in mind however that RPG is still a positional language to some extent however. Field names longer than 15 characters - although allowed - require a continuation specification, and therefore may become awkward to use. It's generally a good idea to keep field name lengths to a maximum of about 12-13 characters.

The long field name lengths allow also for easier adapting of standards which may include field name prefixes. As an example, you may want to prefix all program-described fields with a "@", and all display-file fields with a "#". RPG IV

Page 5: Introduction to Rpg

also now allows and underscore ("_") as part of a field name (it cannot be the first character however). These combined features allow for very readable naming conventions - "@Apr_Unit_Total" instead of "UNTL04".

Now, we'll cover the differences in each of the RPG IV specification types. Aside from layout changes to accommodate larger field names, O-specs (output) remained relatively unchanged and therefore are not covered. A new D-spec was added to RPG IV that replaces most of the functionality of the I-spec (input specifications) and eliminates the E-specs (tables/arrays).

H-specs (control specifications)F-specs (file specifications)D-specs (data specifications)C-specs (calculation specifications)

H-SPECS:

Control (or Header) specification allow you specify global parameters for how your program functions and is compiled. RPG III allowed one H-spec per program with the positional parameters.

RPG IV on the other hand uses free-form keywords for these parameters. Multiple H-specs may be used, and the keywords may be specified in any order.

For example, an H-spec coded in RPG III to format UDATE as YYMMDD would look like this:

*...1....+....2....+....3....+....4....+....5....+....6....+....7... H Y

The same H-spec in RPG IV looks like this (capitalization is up to you):

*...1....+....2....+....3....+....4....+....5....+....6....+....7... H Datedit(*YMD)

New H-spec keywords are added to each release. A great deal of the newer keywords are compile-option keywords that override the default or specified options on the CRTBNDRPG and CRTRPGMOD commands. This is potentially a very valuable feature, especially when using the more advanced features of ILE. If a program requires special compile-time parameters, they can be included in an H-spec instead of relying on programmers to remember those options when compiling future changes.

Some of the more useful H-spec keywords are described below. Many of these keywords deal with somewhat more advanced ILE functionality. Don't feel discouraged if you don't understand these yet - these ILE features will be covered in later sections.

BNDDIR('binding-directory-name' {:'binding-directory-name'...})Allow you to indicate which binding directory(s) to use at compile time. See ILE section for more information on binding directories.

DATEDIT(fmt{separator})This keyword allows you to specify the format of UDATE and *DATE within your program. The possible values are *DMY, *MDY, or *YMD. The default separator is "/". A separator character of "&" may be used to specify a blank separator. It is generally a good idea to explicitly specify the date format in the H-spec. If it is not used, the date

Page 6: Introduction to Rpg

format will be defaulted from the system date format. Otherwise, if the system date format is ever changed, or your program is distributed to and run on a different system, you may have unexpected results.

DATFMT(fmt{separator})As opposed to the DATEDIT keyword which specifies the format of UDATE and *DATE, the DATFMT keyword specifies the default format for date-type data fields. The default format is *ISO (ccyy/mm/dd). Click here to see a complete list of date formats from IBM's V4R5 RPG documentation.

DEBUG{(*NO | *YES)}Use this keyword to indicate whether or not to perform DUMP operations in your RPG program. The default is *NO, which means DUMP operations will not be performed. If you have an error handler that uses the DUMP op-code, you should specify DEBUG(*YES) in your H-spec.

NOMAINThis parameter should be used in procedure modules (we'll cover this later). When used, the compiler will not generate the code to handle the RPG cycle.

OPTION(*{NO}SRCSTMT *{NO}DEBUGIO)Over the past few releases, several new parameters have been added to the option keyword. I still think however that *SRCSTMT and *NODEBUGIO are the two most useful parameters. If OPTION(*NOSRCSTMT) is coded or omitted, the compile will re-number the source statements in the compiled module. What this means is that if your program gets a run-time exception, the statement it indicates will be virtually meaningless unless you saved the compile printout. This could be a major issue if the program blows up in production. The OPTION(*SRCSTMT) will prevent the compile process from renumbering the statements in the compile process. My opinion is that IBM should have made this the default, as I honestly can't think of a reason why you wouldn't code this in your program.

The *NODEBUGIO parameter is more of a convenience feature. If not specified, when stepping through a program using the interactive source debugger, a separate break will be inserted for each field returned from an I/O operation. When the *NODEBUGIO parameter is coded, the I/O statement only breaks once.

The minimum control specification that I personally use is as follows:

*...1....+....2....+....3....+....4....+....5....+....6....+....7... H datedit(*YMD) datfmt(*ISO) option(*SRCSTMT *NODEBUGIO)

Using more (or less) keywords is entirely up to you, depending on your requirements.

Using a Data Area to create a default H-spec

Instead of relying on every programmer to include the appropriate H-spec in their programs, it is possible to create a data area with your default keywords that will be automatically be included at compile time.

If an H-spec is included in the program, it will override any external H-specs in data areas.

If no H-spec is included however, the compiler will look for a data area named RPGLEHSPEC in your library list. If it is found, the contents of the data area will be used as your H-spec. There can be multiple data areas with this name in different libraries.

Page 7: Introduction to Rpg

If RPGLEHSPEC is not found in the library list, the compiler will look for a data area named DFTLEHSPEC in library QRPGLE. If this if found, it's contents will be used as your H-spec.

The data areas must be type character, and can be whatever length you need.

F-SPECS:

With the following exceptions, F-specs remained relatively unchanged:

1. The positional format was changed by moving some of the more commonly used parameters towards the left side of the line.

2. The less-commonly used parameters were converted to free-format keywords similar to the H-spec keywords.

3. The F-spec continuation ("K") was eliminated, as free-format keywords may span multiple lines.

The new F-spec layout is as follows:

*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 ...+... 9 ...+... 10FFilename++IPEASFRlen+LKlen+AIDevice+.Keywords+++++++++++++++++++++++++++++Comments+++++++++++++

See IBM's online documentation for details on the positional parameters V4R5.

By compressing the more commonly used fixed parameters towards the left of the line, the right side of the line is open for free-format keywords. The fixed format keywords that were removed, as well as the options on continuation lines, were converted to keywords. For example, the F-spec continuation line SFILE was converted to a keyword with the format SFILE(recformat: rrnfield).

Also, if a record format needs to be renamed, instead of using the "KRENAME" notation from RPG III, use the keyword RENAME(external-rec-name: internal-rec-name).

Another useful F-spec keyword is PREFIX(string). The prefix keyword allows you to rename all fields in an externally described file by attaching a prefix to the field names. This allows you to easily handle the situation where two different files have duplicate field names. Previously this had to be handled by renaming the fields in I-specs. Although I wouldn't necessarily recommend it, theoretically, you could eliminate the prefix portion of the field names in the DDS and instead rely on the PREFIX keyword to uniquely identify field names.

D-SPECS:

Prior to RPG IV, Input Specifications (I-specs) were used to define data elements (data structures, named constants, etc) within a program. Over the years I-specs were distanced from their original intent of defining program-described input files.

As of RPG IV I-specs were returned to their original intent - to define program-described input files. All other types of data elements may be defined using the new D-specs. In addition to having a much more streamlined and intuitive layout that I-specs, D-specs also offer much more functionality. The D-spec layout is as follows:

*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 ...+... 9 ...+... 10DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords+++++++++++++++++++++++++++++Comments++++++++++++

Page 8: Introduction to Rpg

I won't attempt to thoroughly cover the syntax of a D-spec here. I've found that the best way to learn D-specs syntax is to code the I-spec the way you want in RPG III and then run the conversion process. Instead,

In addition to allowing you to define data structures, D-specs also allow you to define named constants and stand-alone fields. Positions 24-25 are used to identify the type of data element that is defined:

"DS" is used to define a data-structure. The sub-fields of a data structure should have these positions blank.

"C" is used to define a named constant. The keyword CONST(value) is then used to identify the value of the constant.

"S" is used to define stand-alone fields. The keyword INZ(value) may be used to initialize the value of a stand-alone field.

"PI" and "PR" may be used to define procedure interfaces and prototypes. These are somewhat more advance ILE elements and will be covered later.

One of the opportunities that D-specs provide is the ability to define and initialize all program-described fields (stand alone fields as well as named constants) in D-specs rather than throughout the program. This practice can greatly improve program readability.

Field names within a D-spec may be indented for readability and to imply a hierarchy for data structure subfields. Indenting is for readability however and has no affect on the data.

Note also, that like H-spec and F-specs, D-specs also have free format keywords available. In addition to INZ (for stand alone fields) and CONST (for named constants), some of the available keywords include:

DIM(numeric_constant): This keyword replaces the old E-specs by defining the field as a table or array. The CTDATA, FROMFILE, and TOFILE keywords may also be used in conjunction with the DIM keyword. CTDATA defines the array as being loaded with compile time data (described at the end of the source member). The FROMFILE and TOFILE keywords may be used to automatically load the array from a file at pre-runtime or update a file from the array at post-runtime.

DTAARA{(data_area_name)}: This keyword associate a data element with an external data area. It is equivalent to using the *DTAARA DEFINE opcode. If the data element is defined as a data structure ("DS" in positions 24-25) and a "U" is coded in position 23, the data area will automatically be retrieved when the program is initialized, and updated when the program ends.

EXPORT{(external_name)}, IMPORT{(external_name)}: The export and import keywords allow you to implicitly share data across modules in a program. This is a useful concept when creating ILE applications and will be covered in later sections.

LIKE(RPG_name): The LIKE keyword allows you define a data element so that it has the same data type and length as another field. This keyword may be used in place of the *LIKE DEFINE opcode.

OCCURS(numeric_constant): OCCURS, when used on a data structure, defines it as a multiple occurrence data structure.

Page 9: Introduction to Rpg

OVERLAY(name{:pos | *NEXT}): The OVERLAY keyword allows a field name to be created as an overlay of a data structure or a data structure subfield. The keyword is only valid on data structure subfields. For example:

DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords++++++++++++++++++++++++++++

D DataStructure DS

D Field10 10

D Field1to5 5 overlay(Field10)

D Field6to10 5 overlay(Field10:*next)

In the above example, FIELD10 is defined a 10 byte alpha subfield of data structure DATASTRUCTURE. FIELD1TO5 will be overlayed with the first 5 positions of FIELD10 and FIELD6TO10 will be overlayed with the last 5 positions. Keep in mind that all 4 data names refer to areas of the same 10 bytes of memory.

For a complete list of D-spec keywords (as of V4R5) see IBM's online documentation.

Additional data types

In addition to the syntax changes of D-specs, RPG IV also allow you to define a number of new data types. Some of the more interesting types include:

Date (D), Time (T), and Timestamp (Z): One of the most long-awaited enhancements to RPG IV is the inclusion of date and time support. Timestamp fields combine both date and time (including micro-seconds) into one field. Prior to this, normally a six-digit number was used to represent date and time fields. Date, time, and timestamp fields are internally stored as a number of days (for date fields), seconds (for time fields), or micro-seconds (for timestamp fields) from a given base date or time. The INZ(*SYS) keyword may be used when defined date, time, or timestamp fields to initialize the value to current system date as in:

DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords++++++++++++++++++++++++++++

D @CurrDate S D inz(*sys)

D @CurrTime S T inz(*sys)

D @CurrTimestmp S Z inz(*sys)

For more information on date and time data types, see the Date and Time section.

Floating Point (F): Floating point fields are often useful for storing calculated values where you don't know beforehand the number of decimal places or significant digits you'll need.

Floating point fields may either be defined as standard 4-byte, or double precision 8-byte lengths.

Page 10: Introduction to Rpg

DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords++++++++++++++++++++++++++++D @Float S 4FD @FloatDouble S 8F

Single precision floating point fields allow for a numeric range from 1.1754944-38 through 3.4028235+38. Double precision allows for a range of 2.225073858507201-308 through 1.797693134862315+308.

Indicator fields (N): By defining fields of type N, you can create your own boolean variables for true/false evaluations.

Pointers (*): Yes, RPG IV even supports pointers! Pointer variables, when used with the BASED keyword and ALLOC and DEALLOC opcodes provide some very sophisticated functionality. For more information as well as some examples, see the Pointers page.

C-SPECS:

One of the first differences you'll notice when coding RPG IV programs (aside from the mixed case entry) is that the C-spec layout has shifted significantly. This is primarily to allow for longer field names and support free-form expressions. There are two primary C-spec layouts - one for fixed format lines and one for free-format expressions.

Fixed format:

*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 ...+... 9 ...+... 10CL0N01Factor1+++++++Opcode(E)+Factor2+++++++Result++++++++Len++D+HiLoEq....Comments+++++++++++++

Free format:

*.. 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8 ...+... 9 ...+... 10CL0N01Factor1+++++++Opcode(E)+Extended-factor2+++++++++++++++++++++++++++++Comments+++++++++++++

Note that by default, PDM will position to column 6 (instead of column 1 for RPG III code). If your shop uses columns 1 to 5 for comments or begin/end tags, you should be aware of this as most programmers will not see these positions and may inadvertently copy comments erroneously.

Also note that there is only one left-hand conditioning indicator. Left-hand conditioning indicators were used extensively in RPG II - not as much in RPG III. If you use CVTRPGSRC to convert your RPG III code to RPG IV and the original code used conditioning indicators liberally, the result can be pretty ugly! It is strongly recommended that you convert conditioning indicators to IF statements. Some third-party RPG IV conversion programs will do this for you automatically.

Factor 1 and factor 2 now each have room for 14-byte field names. Take advantage of this by naming internal fields less cryptically. For example, if you have a field that totals net sales by account, instead of naming it NTSLAC, you may want to name it something like @NetSlsByAcct.

Note: Although you can still define fields on the fly by supplying a length, it is considered good structure to define all internal fields as stand-alone fields in D-specs.

Operation codes have also be extended. In RPG III, there was a limitation of 5-characters, which forced some opcodes to be abbreviated (for example, BITOF, DELET, and LOKUP). RPG IV has expanded the length of opcodes and

Page 11: Introduction to Rpg

name some of the RPG III opcodes more logically (BITOFF, DELETE, and LOOKUP). The operation extender that was in position 53 in RPG III has been moved next to the opcode itself (the operation extender is used much more extensively in RPG IV).

Extended factor 2

There are a number of opcodes new to RPG IV that take advantage of the new extended factor 2 layout. The extended factor 2 area allows you to enter free-format expressions and take advantage of RPG's built-in-functions.

All RPG III opcodes that include a comparison operator (for example, IFEQ, DOWLT, etc) can be written in RPG IV using the free-form extended factor 2 format. For example:

CL0N01Factor1+++++++Opcode(E)+Factor2+++++++C *in99 ifeq *offC cust# andne @SaveCust#

can be re-written as:

C if *in99 = *off andC cust# <> @SaveCust#

While both statements function identically, the free-format version can be much more readable, especially with complex evaluations. Note that factor 1 is not used, and the ANDxx or ORxx operation codes are not needed to continue an expression on a new line. Parenthesis may be used to prioritize expression. Evaluations in the innermost parenthesis pair are always performed first.

C if (*in99 = *off andC cust# <> @SaveCust#) orC (cust# = *blanks orC cust# = '00000') orC (*in03 = *on)

Free-format expressions may also include calculations:

C if x = y + z and C (a = (b * c) - d) or C (cust# = *blanks orC cust# = '00000') orC (*in03 = *on)

The following operation codes allow use of extended factor 2:

RPG IV RPG III equivalent

IF IFxx (IFEQ, IFLE, etc.)

Page 12: Introduction to Rpg

DOW DOWxx

DOU DOUxx

WHEN (used in a SELECT group) WHxx

EVAL (none)

EVALR (new to V4R4) (none)

FOR (new to V4R4) (none)

EVAL/EVALR operations

The EVAL opcode (new to RPG IV) allows you to assign values to variables using a free-format expression.

C eval x = y + zC eval @String = "Midware Services"

EVAL may be used with any data types - however the right side of the equation must evaluate to the same type as the variable on the left side of the equation. For example EVAL may not be used to assign a numeric field to a character string. (Built-in-functions may be used to convert data types however)

EVAL may be thought of as combining the functionality of the Z-ADD, MOVEL, ADD, SUB, MULT, and DIV operation codes into a single statement. Previous functionality that used to be only possible with multiple lines of code may now be combined into a single statement:

D @DailyRate S 4F

C @WeeklyRate div 7 @DailyRate

C @NumberDays mult @DailyRate @InvoiceAmt

may be re-written as:

C eval @InvoiceAmt = (@WeeklyRate / 7) *C @NumberDays

Note that in the first example, we needed to define @DailyRate as an interim field. We defined it as a floating point (single precision) because we don't know how the divide will truncate. An interim field is not required in the EVAL statement.

If the EVAL operation is used on character strings of unequal length, it will truncate the same as the MOVEL opcode. The EVALR opcode (new to V4R4) may be used to simulate the MOVE opcode:

Page 13: Introduction to Rpg

D X S 2A

D Y S 4A

D Z S 3A inz('ABC')

C eval X = Z

C* X = "AB"

C eval Y = Z

C* Y = "ABC "

C evalr X = Z

C* X = "BC"

C evalr Y = Z

C* Y = " ABC"

Converting to EVAL

Once you get comfortable with the EVAL statement, you may want to convert your existing code to take advantage of the benefits. Some third-party RPG III conversion programs will even do this conversion for you. There are several gotcha's you should be aware of before you do this however.

Eval vs. EvalR: Keep in mind that for character strings, EVAL is equivalent to MOVEL, and EVALR is equivalent to MOVE. EVALR is also not available until V4R4.

Numeric overflow: The traditional numeric handling opcodes (Z-ADD, MULT, etc.) will automatically truncate significant digits if the result field is not long enough. The EVAL opcode, however, will produce a run-time machine error. Unfortunatly, the only way to handle this gracefully at the present time is to code a *PSSR error handling subroutine.

Interim calculated values: Converting several calculations into a single EVAL statement may not always have the expected result. Take the following example:

C X div Y @TempC @Temp mult 3.14159 Z

C eval Z = (X / Y) * 3.14159

Although it looks like the two methods are the same, you may get slightly different results depending on how @Temp is defined. In the EVAL statement, a floating point value is used for the interim result. Truncation may occur however in the first DIV statement causing different results.

Page 14: Introduction to Rpg

Note: Unless truncation is desired, the EVAL statement will produce the more accurate result. This may cause unexpected differences in parallel testing however.

DATE & TIME FORMAT:

As of V3R1, the AS/400 and RPG now support date and time data types. Prior to this support, numeric fields were often used to represent date and time data. Custom written programs then had to be developed to manipulate, validate, and interpret dates.

With date and time fields comes a whole host of added support to validate, format, compare, and manipulate dates and times. You may still have the need to write some custom date/time routines, but development of these will be greatly simplified using the new data types.

Declaring Date/Time Fields

Date and time data type fields may defined either in physical files using DDS, or as internal fields in RPG (using D-specs). Timestamp fields, which include both date and time (including micro-seconds), may also be defined.

Type Data type code

Date D

Time T

Timestamp Z

When defining date fields in D-specs, the INZ keyword may be used to assign an initial value to the date/time field, as in:

DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords++++++++++++++++++++++++++++

D @CurrDate S D inz(d'2000-01-01')

D @CurrTime S T inz(t'23:59:59')

D @CurrTimestmp S Z inz(*sys)

Note that a value of *SYS may be specified to initialize a date, time, or timestamp to the current system date/time.

Date and time fields may be defined in a number of different formats. The format determines how date and time field is displayed and printed. Use the DATFMT keyword in D-specs or H-specs to define the format of a date field. The available date formats are (note the separator characters):

DATFMT Format Sample

Page 15: Introduction to Rpg

*MDY mm/dd/yy 12/31/99

*DMY dd/mm/yy 31/12/99

*YMD yy/mm/dd 99/12/31

*JUL yy/ddd 99/365

*ISO ccyy-mm-dd 1999-12-31

*USA mm/dd/ccyy 12/31/1999

*EUR dd.mm.ccyy 31.12.1999

*JIS ccyy-mm-dd 1999-12-31

See IBM's online RPG documentation for a complete description of date formats, as well as minimum and maximum values for each format.

The TIMFMT keyword is used in D-specs or H-specs to define the format of a time field.

TIMFMT Format Sample

*HMS hh:mm:ss 13:59:00

*ISO hh.mm.ss 13.59.00

*USAhh:mm amhh:mm pm

1:59 pm

*EUR hh.mm.ss 13.59.00

*JIS hh:mm:ss 13:59:00

There is only one format available for timestamp fields:

CCYY-MM-DD-hh.mm.ss.xxxxxx

The last 6-positions of the timestamp field are microseconds (timestamp fields are often used to generate unique keys for a file).

When declaring date or time fields in an RPG program, if DATFMT or TIMFMT is not specified on the D-spec, the formats will default to the DATFMT and TIMFMT specified on the H-spec. If these keywords are not defined on the H-spec, the format will default to *ISO.

Page 16: Introduction to Rpg

Validating Date/Time values

It's one thing to be able to initialize date/time fields at compile time, but in the real world, more often than not, we need to populate date/time fields with run-time data.

As of V4R5, display files don't support date or time data-type fields. Therefore, if we need to allow a user to enter a date or time, we must first define a numeric or character field, test the field for a valid value, and then move that value to a date or time field.

Date fields are stored internally (in memory) as an integer representing a number of days from a given base date. Sometimes this format is referred to as super-julian. When ever the date is to be displayed, printed, written to a file, etc, an algorithm is run to convert the date from an integer to the specified format.

This is the same way date fields are stored in most PC applications as well. To illustrate this, open a workbook in Microsoft Excel. Enter "12/31/1999" (without quotes) in a cell. It will be interpreted and displayed as a date.

Now, change the format of the cell to General. The value displayed now will be 36525, which is the number of days from January 1, 1900 - the base date used in Excel. Change the number to 2, and re-format the cell as a date (make sure to include year). The date now displayed will be January 2, 1900.

This is actually very similar to the method the AS/400 uses to store dates. One limitation of Excel however is that dates before 1/1/1900 are not supported. Depending on the date format used, the AS/400 will support dates as early as 1/1/0001 and as late as 12/31/9999. Time and timestamp fields are stored in a similar (slightly more complex) manner.

Note: The exception to this is with date formats the utilize a two-digit year (*mdy, *ymd, *dmy, and *jul). These dates have a valid range of January 1, 1940 through December 31, 2039. Moving a field with a 4-digit year outside of this range to these fields will cause a runtime exception. If there is any possibility that an application will use dates outside of this range two-digit year date formats should not be used.

Because of the way dates and times are stored internally, the AS/400 is very intolerant of bad data. If you try to move an invalid date to a date field you will immediatly get an error. This is an important consideration. Many applications use special values of all 9's or all 0's to indicate certain meanings. For example, a program may assign a value of 99999999 to a Date-Processed field to indicate the records has not been processed yet. If you attempt to move these values to a date field, you will get a run-time exception.

Therefore, if there is any question about the validity of a date or time, you should use the TEST opcode. TEST will check for a valid date, time, or timestamp format in a numeric or character field. An opcode extender of D (date), T (time), or Z (timestamp) is used to indicate the type of data being tested for. Use factor-1 to indicate the format you're testing for, and the result field for the data being tested. An error indicator will be turned on if the data is invalid. Some examples:

CL0N01Factor1+++++++Opcode(E)+Factor2+++++++Result++++++++Len++D+HiLoEqC eval @Num = 123199C *mdy test(d) @Num 99 *** *in99 = *off

Page 17: Introduction to Rpg

C *ymd test(d) @Num 99 *** *in99 = *on (99 is not a valid day)C eval @Num = 20010229C *iso test(d) @Num 99 *** *in99 = *on (2001 is not a leap year)C eval @Num = 010101C *iso test(d) @Num 99C *in99 = *offC *hms test(t) @NumC *in99 = *off

Note: The built-in-function %ERROR may also be used to check the result of a test operation. Built-in-functions will be covered in the next section.

When the TEST opcode is used to check a character field, the separator character is also tested.

CL0N01Factor1+++++++Opcode(E)+Factor2+++++++Result++++++++Len++D+HiLoEqC eval @String = '12/31/99'C *mdy test(d) @String 99C *in99 = *offC eval @String = '123199'C *mdy test(d) @String 99C *in99 = *on (invalid separators)

Note that the default date separator may overridden in D-specs or H-specs with the DATSEP keyword.

If the TEST opcode fails, attempting to move the data to a date or time field will also fail. If it does not fail, the data may be safely moved to a date/time field.

Working with Date/Time data

Once you've verified that a character or numeric field has valid date or time data in it, you may move it to a date or time data type using the MOVE operation code.

D @Date S D datfmt(*usa)D @Num S 8P 0 inz(12311999)

C *usa test(d) @Num 99C if *in99 = *offC move @Num @DateC endif

Note that in this example, @Num is in the same format as @Date (*usa). The move operation will assume that factor-2 and the result field are the same format. If this is not the case, factor-1 must be used to indicate the format of the source data. For example:

Page 18: Introduction to Rpg

D @Date S D datfmt(*iso)D @Num S 8P 0 inz(12311999)

C *usa test(d) @Num 99C if *in99 = *offC *usa move @Num @DateC endif

By coding *usa in factor-1 of the MOVE statement, we are telling the compiler to convert the data in @Num from the *usa format to whatever format @Date is defined as. After this operation, @Date will contain the value '1999-12-31'. It is generally considered good practice to always code factor-1 on date move operations. By using the same format on the MOVE as you did on the TEST, your are guaranteed to always have a successful move.

Note: The EVAL opcode may not be used to move character or numeric data to a date/time field. Keep in mind that the left-hand and right-hand side of EVAL expressions must be the same data type.

Once data is moved to a date/time field, it can be manipulated or compared to other date/time fields easily. Dates can be compared to each other without concern for the format. For example a date in format ccyy/mm/dd can accurately be compared to a date in format mm/dd/ccyy.

Note: Again, the exception to this rule is comparing two-digit year formats to four-digit formats. Because dates before 1940 or after 2039 are not supported with two-digit year formats, comparing or moving a four-digit year format outside of this range will cause unexpected results.

Elements from date or time fields (month, seconds, etc.) may be extracted from to a numeric field using the EXTRCT operation code. Factor-2 should contain the date or time field, followed by ":" and a duration code. Valid duration codes are *YEARS, *MONTHS, *DAYS, *HOURS, *MINUTES, *SECONDS, *MSECONDS. Abbreviated duration codes may also be used: *Y, *M, *D, *H, *MN, *S, *MS.

C extrct @Date:*m @MonthC extrct @Time:*hours @Hours

Dates may also be manipulated by using the ADDDUR and SUBDUR operation codes (add/subtract duration).

*** Add 1 month to @DateC adddur 1:*month @Date *** Set @DueDate to 90 days after @DateC @Date adddur 90:*days @DueDate

SUBDUR has the same format and functionality as ADDDUR with one additional benefit. If date fields are used in both factor-1 and factor-2, it will calculate the duration between the two dates and update the result field. The result field may be calculated as any one of the valid duration codes.

*** Calculate number of days between @FromDate and @ToDateC @ToDate subdur @FromDate @NbrDays:*d *** Calculate number of seconds between @FromTime and @ToTimeC @ToTime subdur @FromTime @NbrSecs:*s

Page 19: Introduction to Rpg

One thing to keep in mind is that using ADDDUR and SUBDUR on dates with durations other that *DAYS may cause unexpected results. For example, look at the following code:

D @Date S D inz(d'2000-01-31')

C adddur 1:*month @Date *** @Date will be 2000-02-29

C subdur 1:*month @Date *** @Date will now be 2000-01-29

Even though we added one month and then immediately subtracted one month from a date, the result is not the same as what we started with. While not necessarily wrong, peculiarities like this should be understood before using this functionality.

Summary

As mentioned earlier, RPG's built in date and time support probably won't replace all your custom date routines, but it will make developing these date routines much easier. Following are some examples of how you can simplify previously mundane programming tasks.

Checking for leap year

This used to involve a series of division statements (first by 4, then by 100, then by 1000) with work fields to capture the remainders. Now it is as easy as checking the year for a valid date of February 29.

The following piece of code may be used to check if the 4-digit field @Year is a leap-year:

C eval @TestDate = (@Year * 10000) + 0229C *iso test(d) @TestDate 99

If *in99 is set on, @TestDate is invalid, and @Year is not a leap year.

Last day of month

Determining the last calendar day of a month used to involve arrays containing the number of days in each month and a routine to check for leap year. Calculating the last day of the month for a year/month combination (ccyymm) can now be accomplished in four lines of code:

C eval @WorkDate = (@YrMth * 100) + 01C *iso move @WorkDate @DateC adddur 1:*month @DateC subdur 1:*day @Date

The first line of code sets the numeric field @WorkDate to the first day of the month. The next line of code moves this to a date data-type field (@Date).

Page 20: Introduction to Rpg

The third line of code adds one month to @Date to arrive at the first day of the next month. The last line subtracts one day from this date to arrive at the last day of @YrMth.

Day of week

There are a number of ways to figure the day of week for a given date. Prior to RPG date/time support none of these methods were pretty. The code required now is fairly straightforward to calculate the day-of-week for given date (@Date):

*** We know that 1/2/2000 is a SundayD @BaseDate S D inz(d'2000-01-02')

*** Figure out how many days there are between the base date and @DateC @BaseDate subdur @Date @Days:*d

*** Divide the number of days by 7 & determine the remainderC eval @DayOfWeek = %rem(@Days: 7) *** 0 = Sunday *** 1 = Monday *** 2 = Tuesday *** 3 = Wednesday *** 4 = Thursday *** 5 = Friday *** 6 = Saturday

You could then easily add an array to retrieve the day of week names.

Note that we used the built-in-function %REM to determine the remainder. We'll cover built-in-functions in detail in the next section. The DIV and MVR operation codes could have been used instead, but it is somewhat cleaner with the %REM function.

Even though RPG IV's built in date and time support make programming tasks like the above much simpler, in later sections we'll explain methods to make tasks like this even easier by using ILE procedures.

ILE procedures allow you to bundle your code and create your own versions of built in functions. Instead of executing a subroutine or calling a separate program, ILE procedures can be called directly in expressions. The examples above could easily be re-coded so they may be execute like the following:

C if LeapYear(1970)C (do something)

C if @Date <= EndOfMonth(200102)C (do something)

Page 21: Introduction to Rpg

C eval @Message = 'Your birthday falls on ' +C DayOfWeek(@Birthday)

For now, this is just to whet your appetite. We'll cover the specifics of how to do this in the ILE sections.

Built-in-functions (BIF's) are probably the most exciting new feature in RPG IV - not just because of the functionality they provide, but because of the potential they promise.

Built in functions are actually procedures written by IBM that may be used in expressions (IF, EVAL, etc.) as if they are variables. Procedures are an ILE concept that we will cover in later sections. For now just think of a procedure as a kind of hybrid subroutine. In later sections, we'll show you how you can write your own functions. This is a little more advanced, and requires some knowledge of ILE concepts. There is nothing special you need to do to use built in functions however. If you are using RPG IV, you have full access to all BIF's.

All built in functions begin with a percent sign (%). Most built in functions accept parameters which can be coded in parenthesis. Multiple parameters should be separated by a colon (:). The syntax of built-in-functions is:

%name{(parm1{:parm2...})}

BIF's may be used in any freeform expressions and may be embedded in in other built in functions. For example:

eval @Index = %int(%abs(@Value))

The built in function %ABS returns the absolute value of a numeric parameter. %INT returns the integer portion a numeric parameter. The above example will execute from the innermost parenthesis first. Each BIF will execute a procedure call and return the result in place of the expressions. For example, lets assume that @Value is set to -3.14 at the time the EVAL statement is executed. The sequence the statement will be evaluated is as follows:

eval @Index = %int(%abs(-3.14)):eval @Index = %int(3.14):eval @Index = 3

A wide range of built in functions are available. New functions are added with each release of the operation system. At one point, IBM said that most of the near-term enhancements to RPG will be in the form of new BIF's. Check with IBM's online documentation for the BIF's available in your release or click here for a complete list of BIF's in V4R5.

Following is a rundown of some of the more useful built-in-functions.

%ABS(numeric expression)Returns the absolute value (always positive) of a numeric expression.

Page 22: Introduction to Rpg

%EDITC(numeric : editcode {: *ASTFILL | *CURSYM | currency-symbol})%EDITW(numeric : editword)Applies an edit code edit word or to a numeric expression. This is especially useful when building text strings as in:

eval @Message = 'The current balance for ' + 'Social Security Number + %editw(@SSN: '0 - - ') + ' is ' + %editc(@Balance: 'J')

%EOF{(file_name)}%EQUAL{(file_name)}%FOUND{(file_name)}One thing you may have noticed is that later versions of RPG IV do not require an indicator to be coded on READ and CHAIN operations (instead of manually spacing over to the indicator positions, I used to just press enter, and let the error condition automatically position the cursor). At first, I thought this was an oversight, until I learned of these functions.

%EOF, %EQUAL and %FOUND may be used to replace the status indicators on I/O operations. %EOF is used with read operations (READ, READE, etc.), %EQUAL may be used with the SETLL operation, and %FOUND may be used with the CHAIN, DELETE, SETLL and SETGT operations.

read file1read file2if %eof(file1) or %eof(file2):

If the file parameter is omitted from the function, the status of the last file operation will be returned. For example:

read file1dow not %eof:read file1enddo

The %EQUAL and %FOUND functions may be used also for some non-I/O operations as well. The LOOKUP operation code will set both %EQUAL and %FOUND. %FOUND may also be used with the CHECK, CHECKR, and SCAN operation codes in place of an indicator.

%INT(numeric expression)Returns the integer value of a numeric expression.

eval @Message = 'Your bill is for ' + %char(%int(@BillAmt)) + ' dollars and ' %char((@BillAmt - %int(@BillAmt)) * 100) + ' cents')

Note the use of the %CHAR built in function to convert the numeric data to character format. Remember, you can not mix data types in a free-format expression (%CHAR can only be used to convert numeric data as of V4R4).

Page 23: Introduction to Rpg

%LEN(expression)Returns the length of an expression, or sets the length of a variable length field.

%SCAN(search argument : source string {: start})Scans a text string left to right for a search argument. If a start position is not specified, the search begins at position 1. The expression returns the first position in which the search string was found. If zero is returned, the search string was not found.

%TRIM(string)%TRIML(string)%TRIMR(string)Trims leading and trailing blanks from a text string. %TRIML will only trim leading blanks and %TRIMR will only trim trailing blanks.

eval @Name = %trim(@FirstName) + ' ' + @MiddleInit + '. ' + %trim(@LastName)

Now that you have a good understanding of the language differences between RPG III and RPG IV, as well as the conceptual differences between OPM and ILE, it's time to cover the specifics of ILE.

The effort and complexity converting from OPM to ILE can vary widely depending on how extensively you want to exploit ILE's features. Some of the benefits are as simple as converting a program to ILE. However to take full advantage of ILE requires a great deal of planning during the design phase of an application. There are many issues and strategies that must be fully explored before a system can be fully take advantage of the advanced features of ILE. We'll try to at least touch on most of these issues, but the subject is just too vast, and specific to your company's environment to cover fully.

Before we look forward to where language development in general is going, it may be helpful to look back at the evolution of programming philosophies.

In the 50's & 60's computer programming was in it's infancy. There was little regard given to style or maintainability. And in honesty, the primitive nature of computers at the time didn't offer many amenities to make a programmers life easier.

In the 70's, as new programmers entered the field and had to maintain the existing code, a new programming style emerged know as structured programming. Structured programming involved organizing programs in a top-down structure with common code executed more than once isolated in a subroutine.

Structured programming did in fact improve the readability and maintainability of programs. The usage of subroutines insured that common code would only reside once in a program. If this code needed changed, it would only be need to be changed once -- per program,

Page 24: Introduction to Rpg

There was still the problem of common code existing (although once per program) in many programs. Possible hundreds. This was (and still is) a problem from two points of view. First, it reduces programmer efficiency, and second, it complicates program maintenance.

Two solution were offered to improve this situation: (1) Common code could be moved to external programs and called when needed, or (2) Common code was isolated to copybooks and included automatically at compile time when needed.

Externalizing common code to separate programs and calling them when needed seemed like the answer. However, it was soon discovered that this was very expensive from a CPU usage standpoint. At this point in computer history, many batch processes were already running many hours overnight, or even days for some month-end jobs. Externalizing common code could easily increase run times exponentially.

There are also additional inconveniences with using called programs - primarily the inability to share elements between the calling and called programs unless they are passed as parameters.

Copybooks partially solved these problems, but they themselves have two major drawbacks. First, they do little to improve maintainability. True, if the code needs to be changed, it only needs to be changed once, but all programs using the copybook need to be recompiled. There is also the possibility that the changes could adversely affect something in the base program.

Copybooks also require a great deal of compliance from the programs that will be using them. Files needed must be previously defined correctly, working variables must either be previously defined or reserved for use by the copybook. Parameters aren't passed either. Rather specific field names name be assigned with the correct data.

The following table summarizes the benefits and drawbacks of each of the three methods we've talked about so far. We'll see this table in later sections as we compare some of the ILE techniques with these. Each category is given a rating of 0 to 3 checks (the more, the better) based on the ease of using and maintaining code with common functionality.

By structured programming, we mean that the code is replicated as a subroutine in each of the programs that needs it. Called programs means the code is isolated to a separate program and called when needed. Copybooks are included at compile time when they are needed.

The four categories are:

1. Maintainability : How easy is it to make changes to the common code.

2. Performance : How long does it take (from a CPU standpoint) to execute the common code.

3. Data sharing : How easy is data shared between the common code and the base (calling) code.

4. Ease of use : How easy is it to use the common code as a utility. How much preparation must be done?

Maintainability Performance Data sharing Ease of use

Structured Programming

Page 25: Introduction to Rpg

Called programs

Copybooks

We can see that called programs would be a good solution if calling them were more efficient on the CPU. Data sharing is also difficult - all shared data must be passed as parameters. Numeric fields must be the same type (packed vs. zoned) and length.

Copybooks eliminate the performance concerns, and because ultimately they just get compiled as subroutines in the same program, the data sharing is much easier also (although you need to be careful with field names). However, they are still difficult to maintain if changes need to be made. There are also often many requirements placed on your program before you can use them.

This is where ILE comes in. The integrated language environment provides features which - depending how you use them - fix some or all of the above concerns.

Procedures are the building blocks for an ILE application. They can be thought of as hybrid between subroutines and external called programs. Procedures can be created either in the same source member they are called from (similar to a subroutine) or in separate source members that will be compiled into modules (we'll cover modules a little later).

The ultimate vision of ILE involves building a foundation of procedures. Those procedures are then used to help build more procedures, and so on. Not only are generic programming utilities built into procedures, but your business rules are as well. For example, you may have one procedure to validate a customer number, and another one to create a new invoice for that customer. Each of those procedures may call other procedures.

The idea is to keep procedures small -- re-use as much code as possible instead of re-writing it. If two or more procedures have common code between them, the common code should be moved to another procedure.

Conceptually this is done by creating a low layer of procedures that handle basic functionality:

Once this foundation of building blocks is developed, another layer of procedures can be written that call those procedures when common functionality is needed:

Page 26: Introduction to Rpg

This process is repeated as necessary until a full library of procedure utilities is developed. Keep in mind that procedures are not executable by themselves. Rather, they must be called by programs, similar to subroutines.

The benefit to all this, is that if enough forethought has been used designing the procedures, writing new programs is (theoritically) just a matter of writing some glue-code to bind together the procedures you need:

This modular system design philosophy provides many benefits over traditional systems design, not the least of which is the maximized re-use of code that has already been written, tested, verified, and implemented.

Also, note that the concepts we've talked about so far are not exclusive to RPG. Procedures may be written in any ILE language and combined with procedures from other ILE languages to form a single program.

In summary, some of the benefits offered by ILE include:

Code re-use: Benefits programming productivity as well as program accuracy. Once a procedure is tested and deemed to be bulletproof, you never again need to worry about the accuracy of that process. However, as a programmer you should take the extra time to make sure a production procedure is coded accurately.

Maintenance: When business rules change and additional functionality needs to be added to an application system, utilization of procedures can insure that a minimal number of procedures need to be changed and re-tested.

Page 27: Introduction to Rpg

Pre-build library of procedures: Once you move to ILE, you'll have access to literally hundreds of C procedures written by IBM that are already on your system. These procedure provide access to a wide array of system function that were unavailable with OPM programming languages.

Encapsulation: This term is traditionally associated with object-oriented programming languages (such as Java and C/C++). Encapsulation refers to the idea of isolating a process or data set from a user, and only allowing it to be accessed or modified by a set of procedure that encapsulate (or surround) the entity. Encapsulation provides many benefits, including data integrity and security.

Multiple Languages: Because ILE programs may integrate multiple programming languages into a single program, you are allowed the luxury of writing procedures in the most appropriate language for the task.

The above description of an ILE based system is the ultimate ILE solution. It will require a great deal of planning and design to reach this stage. However, ILE is not an all-or-nothing solution. There are many incremental benefits that can be obtained by using ILE procedures without re-writing your entire system.

In fact, there are many ways to implement ILE procedures as well. We'll start with the simplest, and work our way from there.